summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-11-12 15:28:39 +0100
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-11-12 15:28:39 +0100
commitf987e832a9e79d2ce8009a5ea9c7b677624b3b30 (patch)
tree0dd09a5e6b4c60ee0a9916907dfc2cda83f3e496 /drivers
parentf737b7f46a72c099cf8ac88baff02fbf61b1a47c (diff)
parentfc993d9bc48f772133d8cd156c67c296477db070 (diff)
Merge branch 'l4t/l4t-r16-r2' into colibri
Conflicts: arch/arm/mach-tegra/tegra3_usb_phy.c arch/arm/mach-tegra/usb_phy.c drivers/usb/gadget/tegra_udc.c drivers/usb/otg/Makefile drivers/video/tegra/fb.c sound/soc/tegra/tegra_pcm.c
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/base/power/runtime.c4
-rw-r--r--drivers/char/agp/Makefile1
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c334
-rw-r--r--drivers/cpufreq/cpufreq_stats.c28
-rw-r--r--drivers/cpuquiet/governor.c14
-rw-r--r--drivers/crypto/Makefile2
-rw-r--r--drivers/gpio/Makefile3
-rw-r--r--drivers/gpio/gpio-tegra.c8
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/tegra-tsensor.c82
-rw-r--r--drivers/i2c/busses/Makefile2
-rw-r--r--drivers/i2c/busses/i2c-tegra.c212
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c10
-rw-r--r--drivers/iommu/Makefile2
-rw-r--r--drivers/iommu/tegra-smmu.c19
-rw-r--r--drivers/media/video/tegra/ad5816.c135
-rw-r--r--drivers/media/video/tegra/ar0832_main.c25
-rw-r--r--drivers/media/video/tegra/nvavp/nvavp_dev.c149
-rw-r--r--drivers/media/video/tegra/ov5650.c5
-rw-r--r--drivers/media/video/tegra/ov9726.c57
-rw-r--r--drivers/media/video/tegra/sh532u.c8
-rw-r--r--drivers/media/video/tegra/tegra_camera.c24
-rw-r--r--drivers/mfd/Kconfig42
-rw-r--r--drivers/mfd/Makefile4
-rw-r--r--drivers/mfd/max77665.c371
-rw-r--r--drivers/mfd/tlv320aic3262-core.c885
-rw-r--r--drivers/mfd/tlv320aic3262-irq.c204
-rw-r--r--drivers/mfd/tps65090.c385
-rw-r--r--drivers/mfd/tps80031.c417
-rw-r--r--drivers/misc/Kconfig7
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/bcm4329_rfkill.c2
-rw-r--r--drivers/misc/inv_mpu/mpu6050/mldl_cfg.c10
-rw-r--r--drivers/misc/tegra-baseband/bb-m7400.c2
-rw-r--r--drivers/misc/tegra-baseband/bb-power.c3
-rw-r--r--drivers/misc/tegra-cec/Makefile2
-rw-r--r--drivers/misc/tegra-throughput.c242
-rw-r--r--drivers/mmc/core/core.c26
-rw-r--r--drivers/mmc/core/mmc.c19
-rw-r--r--drivers/mmc/core/sd_ops.c26
-rw-r--r--drivers/mmc/core/sd_ops.h3
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/sdhci-tegra.c123
-rw-r--r--drivers/mmc/host/sdhci.c38
-rw-r--r--drivers/mmc/host/sdhci.h1
-rw-r--r--drivers/mtd/devices/Makefile1
-rw-r--r--drivers/mtd/devices/tegra_nand.c1
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/tegra_nor.c87
-rw-r--r--drivers/net/caif/Makefile1
-rw-r--r--drivers/net/usb/cdc_ether.c8
-rw-r--r--drivers/net/usb/raw_ip_net.c185
-rw-r--r--drivers/net/usb/usbnet.c74
-rw-r--r--drivers/net/wireless/bcmdhd/Kconfig9
-rw-r--r--drivers/net/wireless/bcmdhd/Makefile18
-rw-r--r--drivers/net/wireless/bcmdhd/bcmevent.c1
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c5
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c5
-rw-r--r--drivers/net/wireless/bcmdhd/dhd.h6
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_common.c127
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c57
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmdevs.h3
-rw-r--r--drivers/net/wireless/bcmdhd/include/epivers.h9
-rw-r--r--drivers/net/wireless/bcmdhd/include/hndpmu.h5
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbchipc.h18
-rw-r--r--drivers/net/wireless/bcmdhd/include/siutils.h4
-rw-r--r--drivers/net/wireless/bcmdhd/include/wlioctl.h10
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c782
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h8
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.c48
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.h11
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.c1
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/max17048_battery.c20
-rw-r--r--drivers/power/smb349-charger.c13
-rw-r--r--drivers/power/tps80031-charger.c110
-rw-r--r--drivers/power/tps80031_battery_gauge.c17
-rw-r--r--drivers/regulator/Kconfig22
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/core.c14
-rw-r--r--drivers/regulator/tps51632-regulator.c307
-rw-r--r--drivers/regulator/tps62360-regulator.c6
-rw-r--r--drivers/regulator/tps65090-regulator.c296
-rw-r--r--drivers/regulator/tps80031-regulator.c397
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/alarm.c1
-rw-r--r--drivers/rtc/rtc-max77663.c11
-rw-r--r--drivers/rtc/rtc-tps6591x.c28
-rw-r--r--drivers/rtc/rtc-tps80031.c12
-rw-r--r--drivers/spi/Makefile2
-rw-r--r--drivers/spi/spi-tegra.c117
-rw-r--r--drivers/spi/spi_slave_tegra.c2
-rw-r--r--drivers/staging/android/logger.c190
-rw-r--r--drivers/staging/android/logger.h29
-rw-r--r--drivers/staging/brcm80211/Kconfig1
-rw-r--r--drivers/staging/brcm80211/Makefile4
-rw-r--r--drivers/staging/brcm80211/README65
-rw-r--r--drivers/staging/brcm80211/TODO13
-rw-r--r--drivers/staging/brcm80211/brcmfmac/Makefile10
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdh.c505
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c1228
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd.h526
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_bus.h39
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_cdc.c220
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_common.c887
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_dbg.h46
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_linux.c1152
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_proto.h25
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_sdio.c6651
-rw-r--r--drivers/staging/brcm80211/brcmfmac/sdio_host.h293
-rw-r--r--drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c3396
-rw-r--r--drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h91
-rw-r--r--drivers/staging/brcm80211/brcmsmac/Makefile21
-rw-r--r--drivers/staging/brcm80211/brcmsmac/aiutils.c1248
-rw-r--r--drivers/staging/brcm80211/brcmsmac/aiutils.h310
-rw-r--r--drivers/staging/brcm80211/brcmsmac/alloc.c275
-rw-r--r--drivers/staging/brcm80211/brcmsmac/ampdu.c594
-rw-r--r--drivers/staging/brcm80211/brcmsmac/antsel.c240
-rw-r--r--drivers/staging/brcm80211/brcmsmac/bmac.c3593
-rw-r--r--drivers/staging/brcm80211/brcmsmac/bmac.h174
-rw-r--r--drivers/staging/brcm80211/brcmsmac/brcms_trace_events.c (renamed from drivers/staging/brcm80211/brcmsmac/alloc.h)12
-rw-r--r--drivers/staging/brcm80211/brcmsmac/brcms_trace_events.h92
-rw-r--r--drivers/staging/brcm80211/brcmsmac/channel.c1216
-rw-r--r--drivers/staging/brcm80211/brcmsmac/channel.h87
-rw-r--r--drivers/staging/brcm80211/brcmsmac/d11.h705
-rw-r--r--drivers/staging/brcm80211/brcmsmac/dma.c1686
-rw-r--r--drivers/staging/brcm80211/brcmsmac/dma.h200
-rw-r--r--drivers/staging/brcm80211/brcmsmac/mac80211_if.c1557
-rw-r--r--drivers/staging/brcm80211/brcmsmac/mac80211_if.h38
-rw-r--r--drivers/staging/brcm80211/brcmsmac/main.c9417
-rw-r--r--drivers/staging/brcm80211/brcmsmac/main.h950
-rw-r--r--drivers/staging/brcm80211/brcmsmac/nicpci.c181
-rw-r--r--drivers/staging/brcm80211/brcmsmac/nicpci.h41
-rw-r--r--drivers/staging/brcm80211/brcmsmac/otp.c237
-rw-r--r--drivers/staging/brcm80211/brcmsmac/otp.h15
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c1163
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h85
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_int.h212
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c3478
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_n.c15452
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c172
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c1236
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c131
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h24
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy_shim.c53
-rw-r--r--drivers/staging/brcm80211/brcmsmac/phy_shim.h82
-rw-r--r--drivers/staging/brcm80211/brcmsmac/pmu.c76
-rw-r--r--drivers/staging/brcm80211/brcmsmac/pmu.h14
-rw-r--r--drivers/staging/brcm80211/brcmsmac/pub.h785
-rw-r--r--drivers/staging/brcm80211/brcmsmac/rate.c182
-rw-r--r--drivers/staging/brcm80211/brcmsmac/rate.h299
-rw-r--r--drivers/staging/brcm80211/brcmsmac/scb.h61
-rw-r--r--drivers/staging/brcm80211/brcmsmac/srom.c1427
-rw-r--r--drivers/staging/brcm80211/brcmsmac/srom.h4
-rw-r--r--drivers/staging/brcm80211/brcmsmac/stf.c259
-rw-r--r--drivers/staging/brcm80211/brcmsmac/stf.h6
-rw-r--r--drivers/staging/brcm80211/brcmsmac/types.h331
-rw-r--r--drivers/staging/brcm80211/brcmsmac/ucode_loader.c120
-rw-r--r--drivers/staging/brcm80211/brcmsmac/ucode_loader.h50
-rw-r--r--drivers/staging/brcm80211/brcmutil/Makefile3
-rw-r--r--drivers/staging/brcm80211/brcmutil/utils.c415
-rw-r--r--drivers/staging/brcm80211/brcmutil/wifi.c131
-rw-r--r--drivers/staging/brcm80211/include/brcmu_utils.h270
-rw-r--r--drivers/staging/brcm80211/include/brcmu_wifi.h190
-rw-r--r--drivers/staging/brcm80211/include/chipcommon.h13
-rw-r--r--drivers/staging/brcm80211/include/defs.h32
-rw-r--r--drivers/staging/brcm80211/include/soc.h9
-rw-r--r--drivers/staging/nvec/nvec.c1
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/tegra_hsuart.c101
-rw-r--r--drivers/usb/class/cdc-acm.c2
-rw-r--r--drivers/usb/gadget/Kconfig2
-rw-r--r--drivers/usb/gadget/Makefile1
-rw-r--r--drivers/usb/gadget/android.c68
-rw-r--r--drivers/usb/gadget/f_accessory.c404
-rw-r--r--drivers/usb/gadget/f_audio_source.c827
-rw-r--r--drivers/usb/gadget/tegra_udc.c178
-rw-r--r--drivers/usb/gadget/tegra_udc.h21
-rw-r--r--drivers/usb/host/ehci-q.c2
-rw-r--r--drivers/usb/host/ehci-tegra.c18
-rw-r--r--drivers/usb/host/ehci.h22
-rw-r--r--drivers/usb/otg/Makefile1
-rw-r--r--drivers/usb/otg/tegra-otg.c60
-rw-r--r--drivers/usb/serial/baseband_usb_chr.c98
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/tegra/Kconfig19
-rw-r--r--drivers/video/tegra/dc/csc.c2
-rw-r--r--drivers/video/tegra/dc/dc.c204
-rw-r--r--drivers/video/tegra/dc/dc_priv.h19
-rw-r--r--drivers/video/tegra/dc/dc_sysfs.c14
-rw-r--r--drivers/video/tegra/dc/dsi.c549
-rw-r--r--drivers/video/tegra/dc/ext/dev.c110
-rw-r--r--drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h4
-rw-r--r--drivers/video/tegra/dc/hdmi.c65
-rw-r--r--drivers/video/tegra/dc/mode.c25
-rw-r--r--drivers/video/tegra/dc/nvsd.c5
-rw-r--r--drivers/video/tegra/dc/window.c24
-rw-r--r--drivers/video/tegra/fb.c66
-rw-r--r--drivers/video/tegra/host/bus.c2
-rw-r--r--drivers/video/tegra/host/bus_client.c3
-rw-r--r--drivers/video/tegra/host/chip_support.h1
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d.c4
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d.h3
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d_t20.c14
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d_t30.c28
-rw-r--r--drivers/video/tegra/host/gr3d/scale3d.c602
-rw-r--r--drivers/video/tegra/host/host1x/host1x.c15
-rw-r--r--drivers/video/tegra/host/host1x/host1x_cdma.c11
-rw-r--r--drivers/video/tegra/host/host1x/host1x_channel.c8
-rw-r--r--drivers/video/tegra/host/host1x/host1x_intr.c13
-rw-r--r--drivers/video/tegra/host/mpe/mpe.c18
-rw-r--r--drivers/video/tegra/host/nvhost_acm.c23
-rw-r--r--drivers/video/tegra/host/nvhost_intr.c12
-rw-r--r--drivers/video/tegra/host/nvhost_intr.h2
-rw-r--r--drivers/video/tegra/host/nvhost_job.c31
-rw-r--r--drivers/video/tegra/host/nvhost_syncpt.c6
-rw-r--r--drivers/video/tegra/host/t30/t30.c2
-rw-r--r--drivers/video/tegra/nvmap/nvmap.c18
-rw-r--r--drivers/video/tegra/nvmap/nvmap_common.h3
-rw-r--r--drivers/video/tegra/nvmap/nvmap_dev.c7
-rw-r--r--drivers/video/tegra/nvmap/nvmap_handle.c99
-rw-r--r--drivers/video/tegra/nvmap/nvmap_heap.c5
-rw-r--r--drivers/video/tegra/nvmap/nvmap_ioctl.c58
-rw-r--r--drivers/w1/masters/Makefile1
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/tegra_wdt.c5
228 files changed, 36550 insertions, 39189 deletions
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 4245ecf30f05..5e939d5f49e4 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_ATA) += libata.o
# non-SFF interface
obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o
+CFLAGS_ahci-tegra.o = -Werror
obj-$(CONFIG_SATA_AHCI_TEGRA) += ahci-tegra.o libahci.o
obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o
obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 3f141ea9283d..37489733cb9d 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -406,8 +406,10 @@ static int rpm_suspend(struct device *dev, int rpmflags)
* reschedule another autosuspend.
*/
if ((rpmflags & RPM_AUTO) &&
- pm_runtime_autosuspend_expiration(dev) != 0)
+ pm_runtime_autosuspend_expiration(dev) != 0) {
+ wake_up_all(&dev->power.wait_queue);
goto repeat;
+ }
} else {
pm_runtime_cancel_pending(dev);
}
diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile
index 8eb56e273e75..2d3b713695c5 100644
--- a/drivers/char/agp/Makefile
+++ b/drivers/char/agp/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_AGP_PARISC) += parisc-agp.o
obj-$(CONFIG_AGP_I460) += i460-agp.o
obj-$(CONFIG_AGP_INTEL) += intel-agp.o
obj-$(CONFIG_AGP_INTEL) += intel-gtt.o
+CFLAGS_nvidia-agp.o = -Werror
obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o
obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o
obj-$(CONFIG_AGP_SIS) += sis-agp.o
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index baf4326e84c4..cf6ba6c1958e 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -30,8 +30,6 @@
#include <asm/cputime.h>
-static atomic_t active_count = ATOMIC_INIT(0);
-
struct cpufreq_interactive_cpuinfo {
struct timer_list cpu_timer;
int timer_idlecancel;
@@ -43,6 +41,7 @@ struct cpufreq_interactive_cpuinfo {
u64 freq_change_time;
u64 freq_change_time_in_idle;
u64 freq_change_time_in_iowait;
+ u64 last_high_freq_time;
struct cpufreq_policy *policy;
struct cpufreq_frequency_table *freq_table;
unsigned int target_freq;
@@ -60,6 +59,9 @@ static spinlock_t up_cpumask_lock;
static cpumask_t down_cpumask;
static spinlock_t down_cpumask_lock;
static struct mutex set_speed_lock;
+static struct mutex gov_state_lock;
+static struct kobject *interactive_kobj;
+static unsigned int active_count;
/* Go to max speed when CPU load at or above this value. */
#define DEFAULT_GO_MAXSPEED_LOAD 85
@@ -92,6 +94,24 @@ static unsigned long min_sample_time;
#define DEFAULT_TIMER_RATE 20000;
static unsigned long timer_rate;
+/*
+ * The minimum delay before frequency is allowed to raise over normal rate.
+ * Since it must remain at high frequency for a minimum of MIN_SAMPLE_TIME
+ * once it rises, setting this delay to a multiple of MIN_SAMPLE_TIME
+ * becomes the best way to enforce a square wave.
+ * e.g. 5*MIN_SAMPLE_TIME = 20% high freq duty cycle
+ */
+#define DEFAULT_HIGH_FREQ_MIN_DELAY 5*DEFAULT_MIN_SAMPLE_TIME
+static unsigned long high_freq_min_delay;
+
+/*
+ * The maximum frequency CPUs are allowed to run normally
+ * 0 if disabled
+ */
+#define DEFAULT_MAX_NORMAL_FREQ 0
+static unsigned long max_normal_freq;
+
+
/* Defines to control mid-range frequencies */
#define DEFAULT_MID_RANGE_GO_MAXSPEED_LOAD 95
@@ -274,6 +294,20 @@ static void cpufreq_interactive_timer(unsigned long data)
goto rearm;
}
+ /*
+ * Can only overclock if the delay is satisfy. Otherwise, cap it to
+ * maximum allowed normal frequency
+ */
+ if (max_normal_freq && (new_freq > max_normal_freq)) {
+ if (cputime64_sub(pcpu->timer_run_time, pcpu->last_high_freq_time)
+ < high_freq_min_delay) {
+ new_freq = max_normal_freq;
+ }
+ else {
+ pcpu->last_high_freq_time = pcpu->timer_run_time;
+ }
+ }
+
if (new_freq < pcpu->target_freq) {
pcpu->target_freq = new_freq;
spin_lock_irqsave(&down_cpumask_lock, flags);
@@ -520,220 +554,43 @@ static void cpufreq_interactive_freq_down(struct work_struct *work)
}
}
-static ssize_t show_go_maxspeed_load(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", go_maxspeed_load);
-}
-
-static ssize_t store_go_maxspeed_load(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- int ret;
- unsigned long val;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret < 0)
- return ret;
- go_maxspeed_load = val;
- return count;
-}
-
-static struct global_attr go_maxspeed_load_attr = __ATTR(go_maxspeed_load, 0644,
- show_go_maxspeed_load, store_go_maxspeed_load);
-
-static ssize_t show_midrange_freq(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", midrange_freq);
-}
-
-static ssize_t store_midrange_freq(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- int ret;
- unsigned long val;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret < 0)
- return ret;
- midrange_freq = val;
- return count;
-}
-
-static struct global_attr midrange_freq_attr = __ATTR(midrange_freq, 0644,
- show_midrange_freq, store_midrange_freq);
-
-static ssize_t show_midrange_go_maxspeed_load(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", midrange_go_maxspeed_load);
-}
-
-static ssize_t store_midrange_go_maxspeed_load(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- int ret;
- unsigned long val;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret < 0)
- return ret;
- midrange_go_maxspeed_load = val;
- return count;
-}
-
-static struct global_attr midrange_go_maxspeed_load_attr = __ATTR(midrange_go_maxspeed_load, 0644,
- show_midrange_go_maxspeed_load, store_midrange_go_maxspeed_load);
-
-static ssize_t show_boost_factor(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", boost_factor);
-}
-
-static ssize_t store_boost_factor(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- int ret;
- unsigned long val;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret < 0)
- return ret;
- boost_factor = val;
- return count;
-}
-
-static struct global_attr boost_factor_attr = __ATTR(boost_factor, 0644,
- show_boost_factor, store_boost_factor);
-
-static ssize_t show_io_is_busy(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", io_is_busy);
-}
-
-static ssize_t store_io_is_busy(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- if (!strict_strtoul(buf, 0, &io_is_busy))
- return count;
- return -EINVAL;
-}
-
-static struct global_attr io_is_busy_attr = __ATTR(io_is_busy, 0644,
- show_io_is_busy, store_io_is_busy);
-
-static ssize_t show_max_boost(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", max_boost);
-}
-
-static ssize_t store_max_boost(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- int ret;
- unsigned long val;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret < 0)
- return ret;
- max_boost = val;
- return count;
-}
-
-static struct global_attr max_boost_attr = __ATTR(max_boost, 0644,
- show_max_boost, store_max_boost);
-
-static ssize_t show_midrange_max_boost(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", midrange_max_boost);
-}
-
-static ssize_t store_midrange_max_boost(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- int ret;
- unsigned long val;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret < 0)
- return ret;
- midrange_max_boost = val;
- return count;
-}
-
-static struct global_attr midrange_max_boost_attr = __ATTR(midrange_max_boost, 0644,
- show_midrange_max_boost, store_midrange_max_boost);
-
-static ssize_t show_sustain_load(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", sustain_load);
-}
-
-static ssize_t store_sustain_load(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- int ret;
- unsigned long val;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret < 0)
- return ret;
- sustain_load = val;
- return count;
-}
-
-static struct global_attr sustain_load_attr = __ATTR(sustain_load, 0644,
- show_sustain_load, store_sustain_load);
-
-static ssize_t show_min_sample_time(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", min_sample_time);
-}
-
-static ssize_t store_min_sample_time(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- int ret;
- unsigned long val;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret < 0)
- return ret;
- min_sample_time = val;
- return count;
-}
-
-static struct global_attr min_sample_time_attr = __ATTR(min_sample_time, 0644,
- show_min_sample_time, store_min_sample_time);
-
-static ssize_t show_timer_rate(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", timer_rate);
-}
-
-static ssize_t store_timer_rate(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- int ret;
- unsigned long val;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret < 0)
- return ret;
- timer_rate = val;
- return count;
-}
-
-static struct global_attr timer_rate_attr = __ATTR(timer_rate, 0644,
- show_timer_rate, store_timer_rate);
+#define DECL_CPUFREQ_INTERACTIVE_ATTR(name) \
+static ssize_t show_##name(struct kobject *kobj, \
+ struct attribute *attr, char *buf) \
+{ \
+ return sprintf(buf, "%lu\n", name); \
+} \
+\
+static ssize_t store_##name(struct kobject *kobj,\
+ struct attribute *attr, const char *buf, size_t count) \
+{ \
+ int ret; \
+ unsigned long val; \
+\
+ ret = strict_strtoul(buf, 0, &val); \
+ if (ret < 0) \
+ return ret; \
+ name = val; \
+ return count; \
+} \
+\
+static struct global_attr name##_attr = __ATTR(name, 0644, \
+ show_##name, store_##name);
+
+DECL_CPUFREQ_INTERACTIVE_ATTR(go_maxspeed_load)
+DECL_CPUFREQ_INTERACTIVE_ATTR(midrange_freq)
+DECL_CPUFREQ_INTERACTIVE_ATTR(midrange_go_maxspeed_load)
+DECL_CPUFREQ_INTERACTIVE_ATTR(boost_factor)
+DECL_CPUFREQ_INTERACTIVE_ATTR(io_is_busy)
+DECL_CPUFREQ_INTERACTIVE_ATTR(max_boost)
+DECL_CPUFREQ_INTERACTIVE_ATTR(midrange_max_boost)
+DECL_CPUFREQ_INTERACTIVE_ATTR(sustain_load)
+DECL_CPUFREQ_INTERACTIVE_ATTR(min_sample_time)
+DECL_CPUFREQ_INTERACTIVE_ATTR(timer_rate)
+DECL_CPUFREQ_INTERACTIVE_ATTR(high_freq_min_delay)
+DECL_CPUFREQ_INTERACTIVE_ATTR(max_normal_freq)
+
+#undef DECL_CPUFREQ_INTERACTIVE_ATTR
static struct attribute *interactive_attributes[] = {
&go_maxspeed_load_attr.attr,
@@ -746,6 +603,8 @@ static struct attribute *interactive_attributes[] = {
&sustain_load_attr.attr,
&min_sample_time_attr.attr,
&timer_rate_attr.attr,
+ &high_freq_min_delay_attr.attr,
+ &max_normal_freq_attr.attr,
NULL,
};
@@ -783,7 +642,8 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
pcpu->freq_change_time_in_iowait =
get_cpu_iowait_time(j, NULL);
pcpu->time_in_iowait = pcpu->freq_change_time_in_iowait;
-
+ if (!pcpu->last_high_freq_time)
+ pcpu->last_high_freq_time = pcpu->freq_change_time;
pcpu->timer_idlecancel = 1;
pcpu->governor_enabled = 1;
smp_wmb();
@@ -792,17 +652,25 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
mod_timer(&pcpu->cpu_timer, jiffies + 2);
}
+ mutex_lock(&gov_state_lock);
+ active_count++;
/*
* Do not register the idle hook and create sysfs
* entries if we have already done so.
*/
- if (atomic_inc_return(&active_count) > 1)
- return 0;
-
- rc = sysfs_create_group(cpufreq_global_kobject,
- &interactive_attr_group);
- if (rc)
- return rc;
+ if (active_count == 1) {
+ rc = sysfs_create_group(cpufreq_global_kobject,
+ &interactive_attr_group);
+ interactive_kobj = kobject_create_and_add(
+ "gov_interactive",
+ cpufreq_global_kobject);
+ kobject_uevent(interactive_kobj, KOBJ_ADD);
+ if (rc) {
+ mutex_unlock(&gov_state_lock);
+ return rc;
+ }
+ }
+ mutex_unlock(&gov_state_lock);
break;
@@ -823,11 +691,18 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
}
flush_work(&freq_scale_down_work);
- if (atomic_dec_return(&active_count) > 0)
- return 0;
+ mutex_lock(&gov_state_lock);
+
+ active_count--;
+
+ if (active_count == 0) {
+ sysfs_remove_group(cpufreq_global_kobject,
+ &interactive_attr_group);
+ kobject_uevent(interactive_kobj, KOBJ_REMOVE);
+ kobject_put(interactive_kobj);
+ }
- sysfs_remove_group(cpufreq_global_kobject,
- &interactive_attr_group);
+ mutex_unlock(&gov_state_lock);
break;
@@ -873,6 +748,8 @@ static int __init cpufreq_interactive_init(void)
midrange_go_maxspeed_load = DEFAULT_MID_RANGE_GO_MAXSPEED_LOAD;
min_sample_time = DEFAULT_MIN_SAMPLE_TIME;
timer_rate = DEFAULT_TIMER_RATE;
+ high_freq_min_delay = DEFAULT_HIGH_FREQ_MIN_DELAY;
+ max_normal_freq = DEFAULT_MAX_NORMAL_FREQ;
/* Initalize per-cpu timers */
for_each_possible_cpu(i) {
@@ -903,6 +780,7 @@ static int __init cpufreq_interactive_init(void)
spin_lock_init(&up_cpumask_lock);
spin_lock_init(&down_cpumask_lock);
mutex_init(&set_speed_lock);
+ mutex_init(&gov_state_lock);
idle_notifier_register(&cpufreq_interactive_idle_nb);
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 1957eee7549e..d0344284a7d8 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -59,6 +59,11 @@ static int cpufreq_stats_update(unsigned int cpu)
cur_time = get_jiffies_64();
spin_lock(&cpufreq_stats_lock);
stat = per_cpu(cpufreq_stats_table, cpu);
+ if (!stat) {
+ spin_unlock(&cpufreq_stats_lock);
+ return 0;
+ }
+
if (stat->time_in_state && stat->last_index >= 0)
stat->time_in_state[stat->last_index] =
cputime64_add(stat->time_in_state[stat->last_index],
@@ -170,12 +175,17 @@ static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
*/
static void cpufreq_stats_free_table(unsigned int cpu)
{
- struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu);
+ struct cpufreq_stats *stat;
+
+ spin_lock(&cpufreq_stats_lock);
+ stat = per_cpu(cpufreq_stats_table, cpu);
+ per_cpu(cpufreq_stats_table, cpu) = NULL;
+ spin_unlock(&cpufreq_stats_lock);
+
if (stat) {
kfree(stat->time_in_state);
kfree(stat);
}
- per_cpu(cpufreq_stats_table, cpu) = NULL;
}
/* must be called early in the CPU removal sequence (before
@@ -299,19 +309,23 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
if (val != CPUFREQ_POSTCHANGE)
return 0;
+ cpufreq_stats_update(freq->cpu);
+
+ spin_lock(&cpufreq_stats_lock);
stat = per_cpu(cpufreq_stats_table, freq->cpu);
- if (!stat)
+ if (!stat) {
+ spin_unlock(&cpufreq_stats_lock);
return 0;
+ }
old_index = stat->last_index;
new_index = freq_table_get_index(stat, freq->new);
- cpufreq_stats_update(freq->cpu);
-
- if (old_index == new_index)
+ if (old_index == new_index) {
+ spin_unlock(&cpufreq_stats_lock);
return 0;
+ }
- spin_lock(&cpufreq_stats_lock);
stat->last_index = new_index;
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
if (old_index >= 0 && new_index >= 0)
diff --git a/drivers/cpuquiet/governor.c b/drivers/cpuquiet/governor.c
index 7895fccc7f42..176ba3bd705f 100644
--- a/drivers/cpuquiet/governor.c
+++ b/drivers/cpuquiet/governor.c
@@ -100,3 +100,17 @@ void cpuquiet_unregister_governor(struct cpuquiet_governor *gov)
list_del(&gov->governor_list);
mutex_unlock(&cpuquiet_lock);
}
+
+void cpuquiet_device_busy(void)
+{
+ if (cpuquiet_curr_governor &&
+ cpuquiet_curr_governor->device_busy_notification)
+ cpuquiet_curr_governor->device_busy_notification();
+}
+
+void cpuquiet_device_free(void)
+{
+ if (cpuquiet_curr_governor &&
+ cpuquiet_curr_governor->device_free_notification)
+ cpuquiet_curr_governor->device_free_notification();
+}
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index e244cfcdd505..7ab59856d755 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -15,5 +15,7 @@ obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o
obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o
obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o
obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
+CFLAGS_tegra-aes.o = -Werror
obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o
+CFLAGS_tegra-se.o = -Werror
obj-$(CONFIG_CRYPTO_DEV_TEGRA_SE) += tegra-se.o
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 4ef6785f446b..7754ff0c239d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -1,5 +1,7 @@
# generic gpio support: platform drivers, dedicated expander chips, etc
+GCOV_PROFILE := y
+
ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_GPIOLIB) += gpiolib.o
@@ -48,6 +50,7 @@ obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
+CFLAGS_gpio-tegra.o = -Werror
obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o
obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 49abdf016b26..c1a80fb8578d 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -6,7 +6,7 @@
* Author:
* Erik Gilling <konkers@google.com>
*
- * Copyright (c) 2011 NVIDIA Corporation.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -314,6 +314,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
+ tegra_gpio_mask_write(GPIO_MSK_OE(gpio), gpio, 0);
+ tegra_gpio_enable(gpio);
+
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
__irq_set_handler_locked(d->irq, handle_level_irq);
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
@@ -390,6 +393,9 @@ static int tegra_gpio_suspend(void)
bank->oe[p] = __raw_readl(GPIO_OE(gpio));
bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
+
+ /* disable gpio interrupts that are not wake sources */
+ __raw_writel(bank->wake_enb[p], GPIO_INT_ENB(gpio));
}
}
local_irq_restore(flags);
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index d9797487180d..66af4257ddc7 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -126,6 +126,7 @@ obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
obj-$(CONFIG_SENSORS_INA219) += ina219.o
obj-$(CONFIG_SENSORS_INA230) += ina230.o
+CFLAGS_tegra-tsensor.o = -Werror
obj-$(CONFIG_SENSORS_TEGRA_TSENSOR) += tegra-tsensor.o
obj-$(CONFIG_PMBUS) += pmbus/
diff --git a/drivers/hwmon/tegra-tsensor.c b/drivers/hwmon/tegra-tsensor.c
index 1c372a4bcce5..c5b16fe97063 100644
--- a/drivers/hwmon/tegra-tsensor.c
+++ b/drivers/hwmon/tegra-tsensor.c
@@ -1049,11 +1049,16 @@ static void get_quadratic_roots(struct tegra_tsensor_data *data,
and
(-(2*m*B+n)-sqrt(((2*m*B+n)^2-4*m(m*B^2+n*B+p-temp))))/(2*m*A)
+ After simplify ((2*m*B+n)^2-4*m(m*B^2+n*B+p-temp)),
+ Roots are:
+ (-(2*m*B+n)+sqrt((n^2-4*m(p-temp))))/(2*m*A)
+ and
+ (-(2*m*B+n)-sqrt((n^2-4*m(p-temp))))/(2*m*A)
*/
int v_e_minus6_2mB_n;
- int v_e_minus4_mB2_nB_p_minusTemp;
- int v_e_minus6_b2, v_e_minus6_4ac;
+ int v_e_minus6_4m_p_minusTemp;
+ int v_e_minus6_n2;
int v_e_minus6_b2_minus4ac;
int v_e_minus6_sqrt_b2_minus4ac;
s64 v_e_minus12_2mA;
@@ -1091,61 +1096,38 @@ static void get_quadratic_roots(struct tegra_tsensor_data *data,
v_e_minus12_2mA = temp_64;
/* computed 2mA */
- /* m * B^2 calculation */
- temp_64 = ((s64)data->B_e_minus6 * (s64)data->B_e_minus6);
+ temp_64 = ((s64)data->n_e_minus6 * (s64)data->n_e_minus6);
/* squaring give positive value */
temp_rem = do_div(temp_64, 1000000);
- /* we see overflow if do not divide above */
- temp_64 *= data->m_e_minus6;
- is_neg = false;
- if (temp_64 < 0) {
- is_neg = true;
- temp_64 *= -1;
- }
- temp_rem = do_div(temp_64, 1000000);
- temp_rem = do_div(temp_64, 100);
- if (is_neg)
- temp_64 *= -1;
- v_e_minus4_mB2_nB_p_minusTemp = (s32)temp_64;
-
- /* n * B calculation */
- temp_64 = ((s64)data->B_e_minus6 * (s64)data->n_e_minus6);
- is_neg = false;
- if (temp_64 < 0) {
- is_neg = true;
- temp_64 *= -1;
- }
- temp_rem = do_div(temp_64, 1000000);
- temp_rem = do_div(temp_64, 100);
- if (is_neg)
- temp_64 *= -1;
- temp_rem = (s32)temp_64;
- v_e_minus4_mB2_nB_p_minusTemp += temp_rem;
- v_e_minus4_mB2_nB_p_minusTemp += (
- (data->p_e_minus2 * 100) - (temp * 10000));
- /* computed ((m * B^2) + n * B + p - temp) * 10^4 */
-
- v_e_minus6_b2 = ((v_e_minus6_2mB_n / 1000)
- * (v_e_minus6_2mB_n / 1000));
- dev_dbg(data->hwmon_dev, "v_e_minus6_b2=%d\n", v_e_minus6_b2);
-
- v_e_minus6_4ac = ((4 * data->m_e_minus6) / 10)
- * ((v_e_minus4_mB2_nB_p_minusTemp) / 1000);
- dev_dbg(data->hwmon_dev, "v_e_minus6_4ac=%d\n", v_e_minus6_4ac);
-
- v_e_minus6_b2_minus4ac = (v_e_minus6_b2 - v_e_minus6_4ac);
+ v_e_minus6_n2 = (s32)temp_64;
+ /* computed n^2 */
+
+ v_e_minus6_4m_p_minusTemp = data->p_e_minus2 - (temp * 100);
+ v_e_minus6_4m_p_minusTemp *= 4 * data->m_e_minus6;
+ v_e_minus6_4m_p_minusTemp = DIV_ROUND_CLOSEST(
+ v_e_minus6_4m_p_minusTemp,100);
+ /* computed 4m*(p-T)*/
+
+ v_e_minus6_b2_minus4ac = (v_e_minus6_n2 - v_e_minus6_4m_p_minusTemp);
+
+ /* To preserve 1 decimal digits for sqrt(v_e_minus6_b2_minus4ac),
+ Make it 100 times, so
+ v_e_minus6_sqrt_b2_minus4ac=(int_sqrt(v_e_minus6_b2_minus4ac *100)*10^6)
+ /sqrt(10^6 * 100)
+ To avoid overflow,Simplify it to be:
+ v_e_minus6_sqrt_b2_minus4ac =(int_sqrt(v_e_minus6_b2_minus4ac *100)*100)
+ */
- v_e_minus6_sqrt_b2_minus4ac = DIV_ROUND_CLOSEST(
- (int_sqrt(v_e_minus6_b2_minus4ac)*1000000),
- int_sqrt(1000000));
+ v_e_minus6_sqrt_b2_minus4ac = (int_sqrt(v_e_minus6_b2_minus4ac * 100)
+ * 100);
dev_dbg(data->hwmon_dev, "A_e_minus12=%lld, B_e_minus6=%d, "
"m_e_minus6=%d, n_e_minus6=%d, p_e_minus2=%d, "
"temp=%d\n", data->A_e_minus12, data->B_e_minus6,
data->m_e_minus6,
data->n_e_minus6, data->p_e_minus2, (int)temp);
- dev_dbg(data->hwmon_dev, "2mB_n=%d, 2mA=%lld, mB2_nB_p_minusTemp=%d,"
+ dev_dbg(data->hwmon_dev, "2mB_n=%d, 2mA=%lld, 4m_p_minusTemp=%d,"
"b2_minus4ac=%d\n", v_e_minus6_2mB_n,
- v_e_minus12_2mA, v_e_minus4_mB2_nB_p_minusTemp,
+ v_e_minus12_2mA, v_e_minus6_4m_p_minusTemp,
v_e_minus6_b2_minus4ac);
temp_64=(s64)(-v_e_minus6_2mB_n - v_e_minus6_sqrt_b2_minus4ac) * 1000000;
@@ -1979,6 +1961,8 @@ static int __devexit tegra_tsensor_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+
static void save_tsensor_regs(struct tegra_tsensor_data *data)
{
int i;
@@ -2005,7 +1989,7 @@ static void restore_tsensor_regs(struct tegra_tsensor_data *data)
}
}
-#ifdef CONFIG_PM
+
static int tsensor_suspend(struct platform_device *pdev,
pm_message_t state)
{
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index ce35a87a7012..381a6ca1a6bb 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -62,7 +62,9 @@ obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
+CFLAGS_i2c-tegra.o = -Werror
obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
+CFLAGS_i2c-slave-tegra.o = -Werror
obj-$(CONFIG_I2C_SLAVE_TEGRA) += i2c-slave-tegra.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 1358dc70b0e4..b3c7a762760a 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -29,6 +29,7 @@
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/i2c-tegra.h>
#include <linux/of_i2c.h>
@@ -129,6 +130,15 @@ enum msg_end_type {
struct tegra_i2c_dev;
+/**
+ * struct tegra_i2c_hw_feature : Different HW support on Tegra
+ * @has_continue_xfer_support: Continue transfer supports.
+ */
+
+struct tegra_i2c_hw_feature {
+ bool has_continue_xfer_support;
+};
+
struct tegra_i2c_bus {
struct tegra_i2c_dev *dev;
const struct tegra_pingroup_config *mux;
@@ -142,10 +152,10 @@ struct tegra_i2c_bus {
/**
* struct tegra_i2c_dev - per device i2c context
* @dev: device reference for power management
+ * @hw: Tegra i2c hw feature.
* @adapter: core i2c layer adapter information
- * @clk: clock reference for i2c controller
- * @i2c_clk: clock reference for i2c bus
- * @iomem: memory resource for registers
+ * @div_clk: clock reference for div clock of i2c controller.
+ * @fast_clk: clock reference for fast clock of i2c controller.
* @base: ioremapped registers cookie
* @cont_id: i2c controller id, used for for packet header
* @irq: irq number of transfer complete interrupt
@@ -160,9 +170,9 @@ struct tegra_i2c_bus {
*/
struct tegra_i2c_dev {
struct device *dev;
+ struct tegra_i2c_hw_feature *hw;
struct clk *div_clk;
struct clk *fast_clk;
- struct resource *iomem;
struct rt_mutex dev_lock;
spinlock_t fifo_lock;
void __iomem *base;
@@ -170,7 +180,6 @@ struct tegra_i2c_dev {
int irq;
bool irq_disabled;
int is_dvc;
- bool is_slave;
struct completion msg_complete;
int msg_err;
u8 *msg_buf;
@@ -235,6 +244,10 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
unsigned long reg)
{
writel(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
+
+ /* Read back register to make sure that register writes completed */
+ if (reg != I2C_TX_FIFO)
+ readl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
}
static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg)
@@ -442,13 +455,13 @@ static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev)
ret = clk_enable(i2c_dev->fast_clk);
if (ret < 0) {
dev_err(i2c_dev->dev,
- "Error in enabling fast clock err %d\n", ret);
+ "Enabling fast clk failed, err %d\n", ret);
return ret;
}
ret = clk_enable(i2c_dev->div_clk);
if (ret < 0) {
dev_err(i2c_dev->dev,
- "Error in enabling div clock err %d\n", ret);
+ "Enabling div clk failed, err %d\n", ret);
clk_disable(i2c_dev->fast_clk);
}
return ret;
@@ -465,12 +478,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
u32 val;
int err = 0;
- if (!i2c_dev->is_clkon_always)
- tegra_i2c_clock_enable(i2c_dev);
-
- /* Interrupt generated before sending stop signal so
- * wait for some time so that stop signal can be send proerly */
- mdelay(1);
+ tegra_i2c_clock_enable(i2c_dev);
tegra_periph_reset_assert(i2c_dev->div_clk);
udelay(2);
@@ -499,14 +507,13 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
- if (i2c_dev->is_slave)
+ if (!i2c_dev->is_dvc)
tegra_i2c_slave_init(i2c_dev);
if (tegra_i2c_flush_fifos(i2c_dev))
err = -ETIMEDOUT;
- if (!i2c_dev->is_clkon_always)
- tegra_i2c_clock_disable(i2c_dev);
+ tegra_i2c_clock_disable(i2c_dev);
if (i2c_dev->irq_disabled) {
i2c_dev->irq_disabled = 0;
@@ -595,12 +602,9 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
}
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
- i2c_readl(i2c_dev, I2C_INT_STATUS);
- if (i2c_dev->is_dvc) {
+ if (i2c_dev->is_dvc)
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
- dvc_readl(i2c_dev, DVC_STATUS);
- }
if (status & I2C_INT_PACKET_XFER_COMPLETE) {
BUG_ON(i2c_dev->msg_buf_remaining);
@@ -636,16 +640,13 @@ err:
I2C_INT_RX_FIFO_DATA_REQ | I2C_INT_TX_FIFO_OVERFLOW);
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
- i2c_readl(i2c_dev, I2C_INT_STATUS);
/* An error occured, mask dvc interrupt */
if (i2c_dev->is_dvc)
dvc_i2c_mask_irq(i2c_dev, DVC_CTRL_REG3_I2C_DONE_INTR_EN);
- if (i2c_dev->is_dvc) {
+ if (i2c_dev->is_dvc)
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
- dvc_readl(i2c_dev, DVC_STATUS);
- }
complete(&i2c_dev->msg_complete);
return IRQ_HANDLED;
@@ -664,10 +665,6 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_bus *i2c_bus,
tegra_i2c_flush_fifos(i2c_dev);
- /* Toggle the direction flag if rev dir is selected */
- if (msg->flags & I2C_M_REV_DIR_ADDR)
- msg->flags ^= I2C_M_RD;
-
i2c_dev->msg_buf = msg->buf;
i2c_dev->msg_buf_remaining = msg->len;
i2c_dev->msg_err = I2C_ERR_NONE;
@@ -728,10 +725,6 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_bus *i2c_bus,
if (i2c_dev->is_dvc)
dvc_i2c_mask_irq(i2c_dev, DVC_CTRL_REG3_I2C_DONE_INTR_EN);
- /* Restore the message flag */
- if (msg->flags & I2C_M_REV_DIR_ADDR)
- msg->flags ^= I2C_M_RD;
-
if (WARN_ON(ret == 0)) {
dev_err(i2c_dev->dev,
"i2c transfer timed out, addr 0x%04x, data 0x%02x\n",
@@ -756,6 +749,14 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_bus *i2c_bus,
}
}
+ /*
+ * NACK interrupt is generated before the I2C controller generates the
+ * STOP condition on the bus. So wait for 2 clock periods before resetting
+ * the controller so that STOP condition has been delivered properly.
+ */
+ if (i2c_dev->msg_err == I2C_ERR_NO_ACK)
+ udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->last_bus_clk_rate));
+
tegra_i2c_init(i2c_dev);
if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
@@ -785,6 +786,17 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
return -EBUSY;
}
+ /* Support I2C_M_NOSTART only if HW support continue xfer. */
+ for (i = 0; i < num - 1; i++) {
+ if ((msgs[i + 1].flags & I2C_M_NOSTART) &&
+ !i2c_dev->hw->has_continue_xfer_support) {
+ dev_err(i2c_dev->dev,
+ "mesg %d have illegal flag\n", i + 1);
+ rt_mutex_unlock(&i2c_dev->dev_lock);
+ return -EINVAL;
+ }
+ }
+
if (i2c_dev->last_mux != i2c_bus->mux) {
tegra_pinmux_set_safe_pinmux_table(i2c_dev->last_mux,
i2c_dev->last_mux_len);
@@ -802,8 +814,8 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
i2c_dev->msgs = msgs;
i2c_dev->msgs_num = num;
- if (!i2c_dev->is_clkon_always)
- tegra_i2c_clock_enable(i2c_dev);
+ pm_runtime_get_sync(&adap->dev);
+ tegra_i2c_clock_enable(i2c_dev);
for (i = 0; i < num; i++) {
enum msg_end_type end_type = MSG_END_STOP;
@@ -818,8 +830,8 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
break;
}
- if (!i2c_dev->is_clkon_always)
- tegra_i2c_clock_disable(i2c_dev);
+ tegra_i2c_clock_disable(i2c_dev);
+ pm_runtime_put(&adap->dev);
rt_mutex_unlock(&i2c_dev->dev_lock);
@@ -840,16 +852,32 @@ static const struct i2c_algorithm tegra_i2c_algo = {
.functionality = tegra_i2c_func,
};
-static int tegra_i2c_probe(struct platform_device *pdev)
+static struct tegra_i2c_hw_feature tegra20_i2c_hw = {
+ .has_continue_xfer_support = false,
+};
+
+static struct tegra_i2c_hw_feature tegra30_i2c_hw = {
+ .has_continue_xfer_support = true,
+};
+
+#if defined(CONFIG_OF)
+/* Match table for of_platform binding */
+static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
+#endif
+
+static int __devinit tegra_i2c_probe(struct platform_device *pdev)
{
struct tegra_i2c_dev *i2c_dev;
struct tegra_i2c_platform_data *plat = pdev->dev.platform_data;
struct resource *res;
- struct resource *iomem;
struct clk *div_clk;
struct clk *fast_clk = NULL;
const unsigned int *prop;
- void *base;
+ void __iomem *base;
int irq;
int nbus;
int i = 0;
@@ -873,56 +901,54 @@ static int tegra_i2c_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "no mem resource\n");
return -EINVAL;
}
- iomem = request_mem_region(res->start, resource_size(res), pdev->name);
- if (!iomem) {
- dev_err(&pdev->dev, "I2C region already claimed\n");
- return -EBUSY;
- }
- base = ioremap(iomem->start, resource_size(iomem));
+ base = devm_request_and_ioremap(&pdev->dev, res);
if (!base) {
- dev_err(&pdev->dev, "Cannot ioremap I2C region\n");
- return -ENOMEM;
+ dev_err(&pdev->dev, "Cannot request/ioremap I2C registers\n");
+ return -EADDRNOTAVAIL;
}
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
dev_err(&pdev->dev, "no irq resource\n");
- ret = -EINVAL;
- goto err_iounmap;
+ return -EINVAL;
}
irq = res->start;
- div_clk = clk_get(&pdev->dev, "i2c-div");
+ div_clk = devm_clk_get(&pdev->dev, "div-clk");
if (IS_ERR(div_clk)) {
dev_err(&pdev->dev, "missing controller clock");
- ret = PTR_ERR(div_clk);
- goto err_release_region;
+ return PTR_ERR(div_clk);
}
- fast_clk = clk_get(&pdev->dev, "i2c-fast");
+ fast_clk = devm_clk_get(&pdev->dev, "fast-clk");
if (IS_ERR(fast_clk)) {
dev_err(&pdev->dev, "missing controller fast clock");
- ret = PTR_ERR(fast_clk);
- goto fast_clk_err;
+ return PTR_ERR(fast_clk);
}
- i2c_dev = kzalloc(sizeof(struct tegra_i2c_dev) +
+ i2c_dev = devm_kzalloc(&pdev->dev, sizeof(struct tegra_i2c_dev) +
(nbus-1) * sizeof(struct tegra_i2c_bus), GFP_KERNEL);
if (!i2c_dev) {
- ret = -ENOMEM;
- goto err_clk_put;
+ dev_err(&pdev->dev, "Could not allocate struct tegra_i2c_dev");
+ return -ENOMEM;
}
i2c_dev->base = base;
i2c_dev->div_clk = div_clk;
i2c_dev->fast_clk = fast_clk;
- i2c_dev->iomem = iomem;
i2c_dev->irq = irq;
i2c_dev->cont_id = pdev->id;
i2c_dev->dev = &pdev->dev;
i2c_dev->is_clkon_always = plat->is_clkon_always;
+
+#ifdef ARCH_TEGRA_2x_SOC
+ i2c_dev->hw = &tegra20_i2c_hw;
+#else
+ i2c_dev->hw = &tegra30_i2c_hw;
+#endif
+
i2c_dev->last_bus_clk_rate = 100000; /* default clock rate */
if (plat) {
i2c_dev->last_bus_clk_rate = plat->bus_clk_rate[0];
@@ -933,6 +959,9 @@ static int tegra_i2c_probe(struct platform_device *pdev)
"clock-frequency", NULL);
if (prop)
i2c_dev->last_bus_clk_rate = be32_to_cpup(prop);
+
+ /* FIXME! Populate the Tegra30 and then support M_NOSTART */
+ i2c_dev->hw = &tegra20_i2c_hw;
}
i2c_dev->is_high_speed_enable = plat->is_high_speed_enable;
@@ -948,9 +977,6 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->arb_recovery = plat->arb_recovery;
init_completion(&i2c_dev->msg_complete);
- if (irq == INT_I2C || irq == INT_I2C2 || irq == INT_I2C3)
- i2c_dev->is_slave = true;
-
platform_set_drvdata(pdev, i2c_dev);
if (i2c_dev->is_clkon_always)
@@ -959,15 +985,17 @@ static int tegra_i2c_probe(struct platform_device *pdev)
ret = tegra_i2c_init(i2c_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize i2c controller");
- goto err_free;
+ return ret;
}
- ret = request_irq(i2c_dev->irq, tegra_i2c_isr, 0, pdev->name, i2c_dev);
+ ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
+ tegra_i2c_isr, 0, pdev->name, i2c_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
- goto err_free;
+ return ret;
}
+ pm_runtime_enable(&pdev->dev);
for (i = 0; i < nbus; i++) {
struct tegra_i2c_bus *i2c_bus = &i2c_dev->busses[i];
@@ -1004,49 +1032,36 @@ static int tegra_i2c_probe(struct platform_device *pdev)
goto err_del_bus;
}
of_i2c_register_devices(&i2c_bus->adapter);
+ pm_runtime_enable(&i2c_bus->adapter.dev);
i2c_dev->bus_count++;
}
+
return 0;
err_del_bus:
while (i2c_dev->bus_count--)
i2c_del_adapter(&i2c_dev->busses[i2c_dev->bus_count].adapter);
- free_irq(i2c_dev->irq, i2c_dev);
-err_free:
- kfree(i2c_dev);
-err_clk_put:
- clk_put(fast_clk);
-fast_clk_err:
- clk_put(div_clk);
-err_release_region:
- release_mem_region(iomem->start, resource_size(iomem));
-err_iounmap:
- iounmap(base);
return ret;
}
-static int tegra_i2c_remove(struct platform_device *pdev)
+static int __devexit tegra_i2c_remove(struct platform_device *pdev)
{
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
- while (i2c_dev->bus_count--)
+
+ while (i2c_dev->bus_count--) {
i2c_del_adapter(&i2c_dev->busses[i2c_dev->bus_count].adapter);
+ pm_runtime_disable(&i2c_dev->busses[i2c_dev->bus_count].adapter.dev);
+ }
if (i2c_dev->is_clkon_always)
tegra_i2c_clock_disable(i2c_dev);
-
- free_irq(i2c_dev->irq, i2c_dev);
- clk_put(i2c_dev->div_clk);
- clk_put(i2c_dev->fast_clk);
- release_mem_region(i2c_dev->iomem->start,
- resource_size(i2c_dev->iomem));
- iounmap(i2c_dev->base);
- kfree(i2c_dev);
+ pm_runtime_disable(&pdev->dev);
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int tegra_i2c_suspend_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -1088,34 +1103,23 @@ static int tegra_i2c_resume_noirq(struct device *dev)
return 0;
}
-static const struct dev_pm_ops tegra_i2c_dev_pm_ops = {
+static const struct dev_pm_ops tegra_i2c_pm = {
.suspend_noirq = tegra_i2c_suspend_noirq,
.resume_noirq = tegra_i2c_resume_noirq,
};
-#define TEGRA_I2C_DEV_PM_OPS (&tegra_i2c_dev_pm_ops)
-#else
-#define TEGRA_I2C_DEV_PM_OPS NULL
-#endif
-
-#if defined(CONFIG_OF)
-/* Match table for of_platform binding */
-static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
- { .compatible = "nvidia,tegra20-i2c", },
- {},
-};
-MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
+#define TEGRA_I2C_PM (&tegra_i2c_pm)
#else
-#define tegra_i2c_of_match NULL
+#define TEGRA_I2C_PM NULL
#endif
static struct platform_driver tegra_i2c_driver = {
.probe = tegra_i2c_probe,
- .remove = tegra_i2c_remove,
+ .remove = __devexit_p(tegra_i2c_remove),
.driver = {
.name = "tegra-i2c",
.owner = THIS_MODULE,
- .of_match_table = tegra_i2c_of_match,
- .pm = TEGRA_I2C_DEV_PM_OPS,
+ .of_match_table = of_match_ptr(tegra_i2c_of_match),
+ .pm = TEGRA_I2C_PM,
},
};
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 23b440a4c27c..aced870f4e9d 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o
+CFLAGS_tegra-kbc.o = -Werror
obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o
obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o
obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index ad21ef9c0105..6721a1fd2456 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2010 Samsung Electronics Co.Ltd
* Copyright (C) 2011 Atmel Corporation
- * Copyright (C) 2011 NVIDIA Corporation
+ * Copyright (C) 2011-2012 NVIDIA Corporation
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
#if defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
#endif
+#define CREATE_TRACE_POINTS
+#include <trace/events/nvevent.h>
/* Family ID */
#define MXT224_ID 0x80
@@ -716,6 +718,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
finger[id].area = area;
finger[id].pressure = pressure;
+ trace_nvevent_irq_data_submit("mxt_input_touchevent");
mxt_input_report(data, id);
}
@@ -728,11 +731,15 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
int touchid;
u8 reportid;
+ trace_nvevent_irq_data_read_start_series("mxt_input_interrupt");
do {
+ trace_nvevent_irq_data_read_start_single("mxt_input_interrupt");
if (mxt_read_message(data, &message)) {
dev_err(dev, "Failed to read message\n");
goto end;
}
+ trace_nvevent_irq_data_read_finish_single(
+ "mxt_input_interrupt");
reportid = message.reportid;
@@ -751,6 +758,7 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
} else if (reportid != MXT_RPTID_NOMSG)
mxt_dump_message(dev, &message);
} while (reportid != MXT_RPTID_NOMSG);
+ trace_nvevent_irq_data_read_finish_series("mxt_input_interrupt");
end:
return IRQ_HANDLED;
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 7ad7a3bc1242..ed59619d1af8 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -8,5 +8,7 @@ obj-$(CONFIG_IRQ_REMAP) += intr_remapping.o
obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
+CFLAGS_tegra-gart.o = -Werror
obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
+CFLAGS_tegra-smmu.o = -Werror
obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 7b5ef3ffb7d0..25bff5c02bb4 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -320,8 +320,15 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c,
val = smmu_read(smmu, offs);
if (on) {
#if !defined(SKIP_SWGRP_CHECK)
- if (WARN_ON(val & mask))
- goto err_hw_busy;
+ if (WARN_ON(val & mask)) {
+ for_each_set_bit(i, &map, HWGRP_COUNT) {
+ offs = HWGRP_ASID_REG(i);
+ val = smmu_read(smmu, offs);
+ val &= ~mask;
+ smmu_write(smmu, val, offs);
+ }
+ return -EBUSY;
+ }
#endif
val |= mask;
} else {
@@ -336,14 +343,6 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c,
c->hwgrp = map;
return 0;
-err_hw_busy:
- for_each_set_bit(i, &map, HWGRP_COUNT) {
- offs = HWGRP_ASID_REG(i);
- val = smmu_read(smmu, offs);
- val &= ~mask;
- smmu_write(smmu, val, offs);
- }
- return -EBUSY;
}
static int smmu_client_set_hwgrp(struct smmu_client *c, u32 map, int on)
diff --git a/drivers/media/video/tegra/ad5816.c b/drivers/media/video/tegra/ad5816.c
index 9e31acc33cc3..6fdb9f184614 100644
--- a/drivers/media/video/tegra/ad5816.c
+++ b/drivers/media/video/tegra/ad5816.c
@@ -96,12 +96,14 @@
#define AD5816_ID 0x04
#define AD5816_FOCAL_LENGTH (4.570f)
#define AD5816_FNUMBER (2.8f)
-#define AD5816_ACTUATOR_RANGE 680
-#define AD5816_SETTLETIME 110
+#define AD5816_SLEW_RATE 1
+#define AD5816_ACTUATOR_RANGE 1023
+#define AD5816_SETTLETIME 50
#define AD5816_FOCUS_MACRO 810
#define AD5816_FOCUS_INFINITY 50 /* Exact value needs to be decided */
-#define AD5816_POS_LOW_DEFAULT 220
-#define AD5816_POS_HIGH_DEFAULT 900
+#define AD5816_POS_LOW_DEFAULT 0
+#define AD5816_POS_HIGH_DEFAULT 1023
+#define AD5816_POS_CLAMP 0x03ff
/* Need to decide exact value of VCM_THRESHOLD and its use */
/* define AD5816_VCM_THRESHOLD 20 */
@@ -140,6 +142,7 @@ struct ad5816_info {
struct ad5816_info *s_info;
struct nvc_focus_nvc nvc;
struct nvc_focus_cap cap;
+ struct nv_focuser_config nv_config;
struct ad5816_pdata_info config;
};
@@ -154,10 +157,12 @@ static struct ad5816_pdata_info ad5816_default_info = {
static struct nvc_focus_cap ad5816_default_cap = {
.version = NVC_FOCUS_CAP_VER2,
+ .slew_rate = AD5816_SLEW_RATE,
.actuator_range = AD5816_ACTUATOR_RANGE,
.settle_time = AD5816_SETTLETIME,
.focus_macro = AD5816_FOCUS_MACRO,
.focus_infinity = AD5816_FOCUS_INFINITY,
+ .focus_hyper = AD5816_FOCUS_INFINITY,
};
static struct nvc_focus_nvc ad5816_default_nvc = {
@@ -637,28 +642,76 @@ static int ad5816_position_rd(struct ad5816_info *info, unsigned *position)
int err = 0;
err = ad5816_i2c_rd8(info, 0, VCM_CODE_MSB, &t1);
- pos = t1 & 0x03;
+ pos = t1;
err = ad5816_i2c_rd8(info, 0, VCM_CODE_LSB, &t1);
pos = (pos << 8) | t1;
- if(pos)
- *position = pos - info->config.pos_low;
- else
- *position = info->config.pos_low;
- return 0;
+ if (pos < info->config.pos_low)
+ pos = info->config.pos_low;
+ else if (pos > info->config.pos_high)
+ pos = info->config.pos_high;
+
+ *position = pos;
+
+ return err;
}
-static int ad5816_position_wr(struct ad5816_info *info, unsigned position)
+static int ad5816_position_wr(struct ad5816_info *info, s32 position)
{
- u16 data;
+ s16 data;
- position = position + info->config.pos_low;
- if(position > info->config.pos_high)
- position = info->config.pos_high;
+ ad5816_set_arc_mode(info);
- data = position & 0x03ff;
+ if (position > info->config.pos_high)
+ return -EINVAL;
+ data = position & AD5816_POS_CLAMP;
return ad5816_i2c_wr16(info, VCM_CODE_MSB, data);
+
+}
+
+static void ad5816_get_focuser_capabilities(struct ad5816_info *info)
+{
+ memset(&info->nv_config, 0, sizeof(info->nv_config));
+
+ info->nv_config.focal_length = info->nvc.focal_length;
+ info->nv_config.fnumber = info->nvc.fnumber;
+ info->nv_config.max_aperture = info->nvc.fnumber;
+ info->nv_config.range_ends_reversed = 0;
+ info->nv_config.settle_time = info->cap.settle_time;
+
+ info->nv_config.pos_working_low = AF_POS_INVALID_VALUE;
+ info->nv_config.pos_working_high = AF_POS_INVALID_VALUE;
+
+ info->nv_config.pos_actual_low = info->config.pos_low;
+ info->nv_config.pos_actual_high = info->config.pos_high;
+
+ info->nv_config.slew_rate = info->cap.slew_rate;
+ info->nv_config.circle_of_confusion = -1;
+ info->nv_config.num_focuser_sets = 1;
+ info->nv_config.focuser_set[0].macro = info->cap.focus_macro;
+ info->nv_config.focuser_set[0].hyper = info->cap.focus_hyper;
+ info->nv_config.focuser_set[0].inf = info->cap.focus_infinity;
+ info->nv_config.focuser_set[0].settle_time = info->cap.settle_time;
+}
+
+static int ad5816_set_focuser_capabilities(struct ad5816_info *info,
+ struct nvc_param *params)
+{
+ if (copy_from_user(&info->nv_config, (const void __user *)params->p_value,
+ sizeof(struct nv_focuser_config))) {
+ dev_err(&info->i2c_client->dev, "%s Error: copy_from_user bytes %d\n",
+ __func__, sizeof(struct nv_focuser_config));
+ return -EFAULT;
+ }
+
+ /* set pre-set value, as currently ODM sets incorrect value */
+ info->cap.settle_time = AD5816_SETTLETIME;
+
+ dev_dbg(&info->i2c_client->dev, "%s: copy_from_user bytes %d info->cap.settle_time %d\n",
+ __func__, sizeof(struct nv_focuser_config), info->cap.settle_time);
+
+ return 0;
}
static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg)
@@ -706,13 +759,10 @@ static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg)
__func__, info->nvc.fnumber);
break;
case NVC_PARAM_CAPS:
- data_ptr = &info->cap;
- /* there are different sizes depending on the version */
/* send back just what's requested or our max size */
- if (params.sizeofvalue < sizeof(info->cap))
- data_size = params.sizeofvalue;
- else
- data_size = sizeof(info->cap);
+ ad5816_get_focuser_capabilities(info);
+ data_ptr = &info->nv_config;
+ data_size = sizeof(info->nv_config);
dev_err(&info->i2c_client->dev, "%s CAPS\n", __func__);
break;
case NVC_PARAM_STS:
@@ -745,16 +795,16 @@ static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg)
}
static int ad5816_param_wr_s(struct ad5816_info *info,
- struct nvc_param *params, u32 u32val)
+ struct nvc_param *params, s32 s32val)
{
int err = 0;
switch (params->param) {
case NVC_PARAM_LOCUS:
- dev_dbg(&info->i2c_client->dev, "%s LOCUS: %u\n", __func__, u32val);
- err = ad5816_position_wr(info, u32val);
+ dev_dbg(&info->i2c_client->dev, "%s LOCUS: %d\n", __func__, s32val);
+ err = ad5816_position_wr(info, s32val);
return err;
case NVC_PARAM_RESET:
- err = ad5816_reset(info, u32val);
+ err = ad5816_reset(info, s32val);
dev_dbg(&info->i2c_client->dev, "%s RESET: %d\n", __func__, err);
return err;
case NVC_PARAM_SELF_TEST:
@@ -773,7 +823,7 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg)
{
struct nvc_param params;
u8 u8val;
- u32 u32val;
+ s32 s32val;
int err = 0;
if (copy_from_user(&params, (const void __user *)arg,
sizeof(struct nvc_param))) {
@@ -781,11 +831,11 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg)
__func__, __LINE__);
return -EFAULT;
}
- if (copy_from_user(&u32val, (const void __user *)params.p_value, sizeof(u32val))) {
+ if (copy_from_user(&s32val, (const void __user *)params.p_value, sizeof(s32val))) {
dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n", __func__, __LINE__);
return -EFAULT;
}
- u8val = (u8)u32val;
+ u8val = (u8)s32val;
/* parameters independent of sync mode */
switch (params.param) {
case NVC_PARAM_STEREO:
@@ -833,7 +883,7 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg)
/* sync power */
info->s_info->pwr_api = info->pwr_api;
/* move slave lens to master position */
- err = ad5816_position_wr(info->s_info, info->pos);
+ err = ad5816_position_wr(info->s_info, (s32)info->pos);
if (!err) {
info->s_mode = u8val;
info->s_info->s_mode = u8val;
@@ -854,20 +904,29 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg)
if (info->pdata->cfg & NVC_CFG_NOERR)
return 0;
return err;
+
+ case NVC_PARAM_CAPS:
+ if (ad5816_set_focuser_capabilities(info, &params)) {
+ dev_err(&info->i2c_client->dev, "%s: Error: copy_from_user bytes %d\n",
+ __func__, params.sizeofvalue);
+ return -EFAULT;
+ }
+ return 0;
+
default:
/* parameters dependent on sync mode */
switch (info->s_mode) {
case NVC_SYNC_OFF:
case NVC_SYNC_MASTER:
- return ad5816_param_wr_s(info, &params, u32val);
+ return ad5816_param_wr_s(info, &params, s32val);
case NVC_SYNC_SLAVE:
- return ad5816_param_wr_s(info->s_info, &params, u32val);
+ return ad5816_param_wr_s(info->s_info, &params, s32val);
case NVC_SYNC_STEREO:
- err = ad5816_param_wr_s(info, &params, u32val);
+ err = ad5816_param_wr_s(info, &params, s32val);
if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX))
err |= ad5816_param_wr_s(info->s_info,
&params,
- u32val);
+ s32val);
return err;
default:
dev_err(&info->i2c_client->dev, "%s %d internal err\n",
@@ -886,10 +945,14 @@ static long ad5816_ioctl(struct file *file,
int err = 0;
switch (cmd) {
case NVC_IOCTL_PARAM_WR:
+ ad5816_pm_dev_wr(info, NVC_PWR_ON);
err = ad5816_param_wr(info, arg);
+ ad5816_pm_dev_wr(info, NVC_PWR_OFF);
return err;
case NVC_IOCTL_PARAM_RD:
+ ad5816_pm_dev_wr(info, NVC_PWR_ON);
err = ad5816_param_rd(info, arg);
+ ad5816_pm_dev_wr(info, NVC_PWR_OFF);
return err;
case NVC_IOCTL_PWR_WR:
/* This is a Guaranteed Level of Service (GLOS) call */
@@ -1032,8 +1095,8 @@ static int ad5816_open(struct inode *inode, struct file *file)
}
file->private_data = info;
ad5816_pm_dev_wr(info, NVC_PWR_ON);
- /* set ARC Mode to ensure faster focus */
- ad5816_set_arc_mode(info);
+ ad5816_position_wr(info, info->cap.focus_infinity);
+ ad5816_pm_dev_wr(info, NVC_PWR_OFF);
dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
return 0;
diff --git a/drivers/media/video/tegra/ar0832_main.c b/drivers/media/video/tegra/ar0832_main.c
index 4da9f7e833b9..b1f43da22ec8 100644
--- a/drivers/media/video/tegra/ar0832_main.c
+++ b/drivers/media/video/tegra/ar0832_main.c
@@ -23,10 +23,12 @@
#include <linux/regulator/consumer.h>
#include <media/ar0832_main.h>
+
#define POS_ACTUAL_LOW 0
#define POS_ACTUAL_HIGH 255
#define SETTLE_TIME 100
-#define SLEW_RATE_DEFAULT 1
+#define AR0832_SLEW_RATE_DISABLED 0
+#define AR0832_SLEW_RATE_SLOWEST 7
struct ar0832_sensor_info {
@@ -1930,13 +1932,26 @@ static int ar0832_focuser_set_config(struct ar0832_dev *dev)
struct i2c_client *i2c_client = dev->i2c_client;
struct ar0832_reg reg_vcm_ctrl, reg_vcm_step_time;
int ret = 0;
- u8 vcm_slew = 1;
+ u8 vcm_slew;
+ u16 vcm_control_data;
+ u16 vcm_step_time = 1024;
+
+ /* slew_rate of disabled (0) or default value (1) will disable */
+ /* the slew rate in this case. Any value of 2 onwards will enable */
+ /* the slew rate to a different degree */
+ if (dev->focuser_info->config.slew_rate == SLEW_RATE_DISABLED ||
+ dev->focuser_info->config.slew_rate == SLEW_RATE_DEFAULT)
+ vcm_slew = AR0832_SLEW_RATE_DISABLED;
+ else
+ vcm_slew = dev->focuser_info->config.slew_rate - 1;
+
+ if (vcm_slew > AR0832_SLEW_RATE_SLOWEST)
+ vcm_slew = AR0832_SLEW_RATE_SLOWEST;
/* bit15(0x80) means that VCM driver enable bit. */
/* bit3(0x08) means that keep VCM(AF position) */
/* while sensor is in soft standby mode during mode transitions. */
- u16 vcm_control_data = (0x80 << 8 | (0x08 | (vcm_slew & 0x07)));
- u16 vcm_step_time = 1024;
+ vcm_control_data = (0x80 << 8 | (0x08 | (vcm_slew & 0x07)));
ar0832_get_focuser_vcm_control_regs(&reg_vcm_ctrl, vcm_control_data);
ret = ar0832_write_reg16(dev->i2c_client, reg_vcm_ctrl.addr,
@@ -2422,7 +2437,7 @@ static void ar0832_create_debugfs(struct ar0832_dev *dev)
goto remove_debugfs;
ret = debugfs_create_file("test_pattern",
- S_IWUGO | S_IRUGO,
+ S_IWUSR | S_IRUGO,
dev->debugdir, dev,
&ar0832_debugfs_fops);
if (!ret)
diff --git a/drivers/media/video/tegra/nvavp/nvavp_dev.c b/drivers/media/video/tegra/nvavp/nvavp_dev.c
index 9a54f8e3d025..4501abb9a735 100644
--- a/drivers/media/video/tegra/nvavp/nvavp_dev.c
+++ b/drivers/media/video/tegra/nvavp/nvavp_dev.c
@@ -1,7 +1,7 @@
/*
* drivers/media/video/tegra/nvavp/nvavp_dev.c
*
- * Copyright (C) 2011-2012 NVIDIA Corp.
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
@@ -101,6 +101,10 @@ struct nvavp_info {
struct clk *bsev_clk;
struct clk *vde_clk;
struct clk *cop_clk;
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ struct clk *bsea_clk;
+ struct clk *vcp_clk;
+#endif
/* used for dvfs */
struct clk *sclk;
@@ -115,6 +119,7 @@ struct nvavp_info {
int video_initialized;
#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
int audio_initialized;
+ struct work_struct app_notify_work;
#endif
struct work_struct clock_disable_work;
@@ -263,14 +268,26 @@ static void nvavp_clks_disable(struct nvavp_info *nvavp)
}
}
-static u32 nvavp_check_idle(struct nvavp_info *nvavp)
+static u32 nvavp_check_idle(struct nvavp_info *nvavp, int channel_id)
{
- struct nvavp_channel *channel_info = nvavp_get_channel_info(nvavp, NVAVP_VIDEO_CHANNEL);
+ struct nvavp_channel *channel_info = nvavp_get_channel_info(nvavp, channel_id);
struct nv_e276_control *control = channel_info->os_control;
return (control->put == control->get) ? 1 : 0;
}
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+static void app_notify_handler(struct work_struct *work)
+{
+ struct nvavp_info *nvavp;
+
+ nvavp = container_of(work, struct nvavp_info,
+ app_notify_work);
+
+ kobject_uevent(&nvavp->nvhost_dev->dev.kobj, KOBJ_CHANGE);
+}
+#endif
+
static void clock_disable_handler(struct work_struct *work)
{
struct nvavp_info *nvavp;
@@ -282,7 +299,7 @@ static void clock_disable_handler(struct work_struct *work)
mutex_lock(&channel_info->pushbuffer_lock);
mutex_lock(&nvavp->open_lock);
- if (nvavp_check_idle(nvavp) && nvavp->pending) {
+ if (nvavp_check_idle(nvavp, NVAVP_VIDEO_CHANNEL) && nvavp->pending) {
nvavp->pending = false;
nvavp_clks_disable(nvavp);
}
@@ -328,6 +345,13 @@ static int nvavp_service(struct nvavp_info *nvavp)
dev_err(&nvavp->nvhost_dev->dev, "AVP timeout\n");
writel(inbox & NVAVP_INBOX_VALID, NVAVP_OS_INBOX);
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ if (inbox & NVE276_OS_INTERRUPT_APP_NOTIFY) {
+ pr_debug("nvavp_service NVE276_OS_INTERRUPT_APP_NOTIFY\n");
+ schedule_work(&nvavp->app_notify_work);
+ }
+#endif
+
return 0;
}
@@ -970,18 +994,14 @@ static void nvavp_uninit(struct nvavp_info *nvavp)
if (video_initialized) {
pr_debug("nvavp_uninit nvavp->video_initialized\n");
cancel_work_sync(&nvavp->clock_disable_work);
-
nvavp_halt_vde(nvavp);
-
- clk_disable(nvavp->sclk);
- clk_disable(nvavp->emc_clk);
-
nvavp_set_video_init_status(nvavp, 0);
video_initialized = 0;
}
#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
if (audio_initialized) {
+ cancel_work_sync(&nvavp->app_notify_work);
nvavp_set_audio_init_status(nvavp, 0);
audio_initialized = 0;
}
@@ -990,6 +1010,9 @@ static void nvavp_uninit(struct nvavp_info *nvavp)
/* Video and Audio both becomes uninitialized */
if (video_initialized == audio_initialized) {
pr_debug("nvavp_uninit both channels unitialized\n");
+
+ clk_disable(nvavp->sclk);
+ clk_disable(nvavp->emc_clk);
disable_irq(nvavp->mbox_from_avp_pend_irq);
nvavp_pushbuffer_deinit(nvavp);
nvavp_halt_avp(nvavp);
@@ -1250,6 +1273,62 @@ static int nvavp_force_clock_stay_on_ioctl(struct file *filp, unsigned int cmd,
return 0;
}
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+static int nvavp_enable_audio_clocks(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct nvavp_clientctx *clientctx = filp->private_data;
+ struct nvavp_info *nvavp = clientctx->nvavp;
+ struct nvavp_clock_args config;
+
+ if (copy_from_user(&config, (void __user *)arg, sizeof(struct nvavp_clock_args)))
+ return -EFAULT;
+
+ dev_dbg(&nvavp->nvhost_dev->dev, "%s: clk_id=%d\n",
+ __func__, config.id);
+
+ if (config.id == NVAVP_MODULE_ID_VCP)
+ clk_enable(nvavp->vcp_clk);
+ else if (config.id == NVAVP_MODULE_ID_BSEA)
+ clk_enable(nvavp->bsea_clk);
+
+ return 0;
+}
+
+static int nvavp_disable_audio_clocks(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct nvavp_clientctx *clientctx = filp->private_data;
+ struct nvavp_info *nvavp = clientctx->nvavp;
+ struct nvavp_clock_args config;
+
+ if (copy_from_user(&config, (void __user *)arg, sizeof(struct nvavp_clock_args)))
+ return -EFAULT;
+
+ dev_dbg(&nvavp->nvhost_dev->dev, "%s: clk_id=%d\n",
+ __func__, config.id);
+
+ if (config.id == NVAVP_MODULE_ID_VCP)
+ clk_disable(nvavp->vcp_clk);
+ else if (config.id == NVAVP_MODULE_ID_BSEA)
+ clk_disable(nvavp->bsea_clk);
+
+ return 0;
+}
+#else
+static int nvavp_enable_audio_clocks(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ return 0;
+}
+
+static int nvavp_disable_audio_clocks(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ return 0;
+}
+#endif
+
static int tegra_nvavp_open(struct inode *inode, struct file *filp, int channel_id)
{
struct miscdevice *miscdev = filp->private_data;
@@ -1367,6 +1446,12 @@ static long tegra_nvavp_ioctl(struct file *filp, unsigned int cmd,
case NVAVP_IOCTL_FORCE_CLOCK_STAY_ON:
ret = nvavp_force_clock_stay_on_ioctl(filp, cmd, arg);
break;
+ case NVAVP_IOCTL_ENABLE_AUDIO_CLOCKS:
+ ret = nvavp_enable_audio_clocks(filp, cmd, arg);
+ break;
+ case NVAVP_IOCTL_DISABLE_AUDIO_CLOCKS:
+ ret = nvavp_disable_audio_clocks(filp, cmd, arg);
+ break;
default:
ret = -EINVAL;
break;
@@ -1540,6 +1625,22 @@ static int tegra_nvavp_probe(struct nvhost_device *ndev,
goto err_get_emc_clk;
}
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ nvavp->bsea_clk = clk_get(&ndev->dev, "bsea");
+ if (IS_ERR(nvavp->bsea_clk)) {
+ dev_err(&ndev->dev, "cannot get bsea clock\n");
+ ret = -ENOENT;
+ goto err_get_bsea_clk;
+ }
+
+ nvavp->vcp_clk = clk_get(&ndev->dev, "vcp");
+ if (IS_ERR(nvavp->vcp_clk)) {
+ dev_err(&ndev->dev, "cannot get vcp clock\n");
+ ret = -ENOENT;
+ goto err_get_vcp_clk;
+ }
+#endif
+
nvavp->clk_enabled = 0;
nvavp_halt_avp(nvavp);
@@ -1558,6 +1659,7 @@ static int tegra_nvavp_probe(struct nvhost_device *ndev,
}
#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ INIT_WORK(&nvavp->app_notify_work, app_notify_handler);
nvavp->audio_misc_dev.minor = MISC_DYNAMIC_MINOR;
nvavp->audio_misc_dev.name = "tegra_audio_avpchannel";
nvavp->audio_misc_dev.fops = &tegra_audio_nvavp_fops;
@@ -1591,6 +1693,12 @@ err_audio_misc_reg:
#endif
misc_deregister(&nvavp->video_misc_dev);
err_misc_reg:
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ clk_put(nvavp->vcp_clk);
+err_get_vcp_clk:
+ clk_put(nvavp->bsea_clk);
+err_get_bsea_clk:
+#endif
clk_put(nvavp->emc_clk);
err_get_emc_clk:
clk_put(nvavp->sclk);
@@ -1639,6 +1747,8 @@ static int tegra_nvavp_remove(struct nvhost_device *ndev)
#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
misc_deregister(&nvavp->audio_misc_dev);
+ clk_put(nvavp->vcp_clk);
+ clk_put(nvavp->bsea_clk);
#endif
clk_put(nvavp->bsev_clk);
clk_put(nvavp->vde_clk);
@@ -1662,14 +1772,22 @@ static int tegra_nvavp_suspend(struct nvhost_device *ndev, pm_message_t state)
mutex_lock(&nvavp->open_lock);
if (nvavp->refcount) {
- if (!nvavp->clk_enabled)
+ if (!nvavp->clk_enabled) {
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ if (nvavp_check_idle(nvavp, NVAVP_AUDIO_CHANNEL))
+ nvavp_uninit(nvavp);
+ else
+ ret = -EBUSY;
+#else
nvavp_uninit(nvavp);
- else
+#endif
+ }
+ else {
ret = -EBUSY;
+ }
}
mutex_unlock(&nvavp->open_lock);
-
return ret;
}
@@ -1679,9 +1797,12 @@ static int tegra_nvavp_resume(struct nvhost_device *ndev)
mutex_lock(&nvavp->open_lock);
- if (nvavp->refcount)
+ if (nvavp->refcount) {
nvavp_init(nvavp, NVAVP_VIDEO_CHANNEL);
-
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ nvavp_init(nvavp, NVAVP_AUDIO_CHANNEL);
+#endif
+ }
mutex_unlock(&nvavp->open_lock);
return 0;
diff --git a/drivers/media/video/tegra/ov5650.c b/drivers/media/video/tegra/ov5650.c
index bac1d00c3bd0..7fae83c21fe2 100644
--- a/drivers/media/video/tegra/ov5650.c
+++ b/drivers/media/video/tegra/ov5650.c
@@ -639,6 +639,11 @@ static struct ov5650_reg mode_320x240[] = {
{0x380f, 0x38},
+ {0x3500, 0x00},
+ {0x3501, 0x13},
+ {0x3502, 0x80},
+ {0x350b, 0x7f},
+
{0x3815, 0x81},
{0x3824, 0x23},
{0x3825, 0x20},
diff --git a/drivers/media/video/tegra/ov9726.c b/drivers/media/video/tegra/ov9726.c
index 378d46fabedf..45d6c85f0925 100644
--- a/drivers/media/video/tegra/ov9726.c
+++ b/drivers/media/video/tegra/ov9726.c
@@ -38,6 +38,7 @@ struct ov9726_devinfo {
struct ov9726_power_rail power_rail;
atomic_t in_use;
__u32 mode;
+ struct ov9726_reg grphold_temp[10];
};
static struct ov9726_reg mode_1280x720[] = {
@@ -603,6 +604,46 @@ static int ov9726_set_gain(struct i2c_client *i2c_client, u16 gain)
return ret;
}
+static int ov9726_set_group_hold(struct ov9726_devinfo *dev,
+ struct ov9726_ae *ae)
+{
+#define OV9726_REG_PUSH8(p, a, v) \
+ do { \
+ (p)->addr = (a); \
+ (p)->val = (v); \
+ (p)++; \
+ } while (0)
+
+#define OV9726_REG_PUSH16(ptr, addr, val) do { \
+ OV9726_REG_PUSH8(ptr, (addr), (val) >> 8); \
+ OV9726_REG_PUSH8(ptr, (addr) + 1, (val) & 0xff); \
+ } while (0)
+
+ struct ov9726_reg *gptr = &dev->grphold_temp[0];
+
+ if (!ae->gain_enable &&
+ !ae->coarse_time_enable &&
+ !ae->frame_length_enable)
+ return 0;
+
+ OV9726_REG_PUSH8(gptr, 0x0104, 0x01);
+ if (ae->gain_enable)
+ OV9726_REG_PUSH16(gptr,
+ OV9726_REG_GAIN_HI, ae->gain);
+ if (ae->coarse_time_enable)
+ OV9726_REG_PUSH16(gptr,
+ OV9726_REG_COARSE_TIME_HI, ae->coarse_time);
+ if (ae->frame_length_enable) {
+ OV9726_REG_PUSH16(gptr,
+ OV9726_REG_FRAME_LENGTH_HI, ae->frame_length);
+ }
+ OV9726_REG_PUSH8(gptr, 0x0104, 0x00);
+ OV9726_REG_PUSH8(gptr, OV9726_TABLE_END, 0x00);
+
+ return ov9726_write_table(dev->i2c_client,
+ dev->grphold_temp, NULL, 0);
+}
+
static int ov9726_get_status(struct i2c_client *i2c_client, u8 *status)
{
int err;
@@ -681,19 +722,26 @@ ov9726_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
}
-
case OV9726_IOCTL_SET_FRAME_LENGTH:
err = ov9726_set_frame_length(i2c_client, (u32)arg);
break;
-
case OV9726_IOCTL_SET_COARSE_TIME:
err = ov9726_set_coarse_time(i2c_client, (u32)arg);
break;
-
case OV9726_IOCTL_SET_GAIN:
err = ov9726_set_gain(i2c_client, (u16)arg);
break;
-
+ case OV9726_IOCTL_SET_GROUP_HOLD:
+ {
+ struct ov9726_ae ae;
+ if (copy_from_user(&ae,
+ (const void __user *)arg, sizeof(struct ov9726_ae))) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ err = ov9726_set_group_hold(dev, &ae);
+ break;
+ }
case OV9726_IOCTL_GET_STATUS:
{
u8 status;
@@ -706,7 +754,6 @@ ov9726_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
break;
}
-
default:
err = -EINVAL;
break;
diff --git a/drivers/media/video/tegra/sh532u.c b/drivers/media/video/tegra/sh532u.c
index 84692d992154..e41dd1f4afb1 100644
--- a/drivers/media/video/tegra/sh532u.c
+++ b/drivers/media/video/tegra/sh532u.c
@@ -1406,9 +1406,9 @@ static int sh532u_set_focuser_capabilities(struct sh532u_info *info,
struct nvc_param *params)
{
if (copy_from_user(&info->config, (const void __user *)params->p_value,
- params->sizeofvalue)) {
+ sizeof(struct nv_focuser_config))) {
dev_err(&info->i2c_client->dev, "%s Error: copy_from_user bytes %d\n",
- __func__, params->sizeofvalue);
+ __func__, sizeof(struct nv_focuser_config));
return -EFAULT;
}
@@ -1420,7 +1420,7 @@ static int sh532u_set_focuser_capabilities(struct sh532u_info *info,
info->config.slew_rate = info->config.slew_rate;
dev_dbg(&info->i2c_client->dev, "%s: copy_from_user bytes %d\n",
- __func__, params->sizeofvalue);
+ __func__, sizeof(struct nv_focuser_config));
return 0;
}
@@ -1491,7 +1491,7 @@ static int sh532u_param_rd(struct sh532u_info *info, unsigned long arg)
sh532u_get_focuser_capabilities(info);
data_ptr = &info->config;
- data_size = params.sizeofvalue;
+ data_size = sizeof(info->config);
break;
case NVC_PARAM_STS:
diff --git a/drivers/media/video/tegra/tegra_camera.c b/drivers/media/video/tegra/tegra_camera.c
index 03eecf464c48..2b0cd005096c 100644
--- a/drivers/media/video/tegra/tegra_camera.c
+++ b/drivers/media/video/tegra/tegra_camera.c
@@ -2,7 +2,7 @@
* drivers/media/video/tegra/tegra_camera.c
*
* Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2012 Nvidia Corp
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -58,6 +58,25 @@ struct tegra_camera_block {
bool is_enabled;
};
+/*
+ * Declare and define two static variables to provide hint to
+ * gr3d module
+ */
+static int tegra_camera_on;
+static struct tegra_camera_platform_data *pdata;
+
+int is_tegra_camera_on(void)
+{
+ if (pdata) {
+ if (pdata->limit_3d_emc_clk)
+ return tegra_camera_on;
+ else
+ return 0;
+ } else {
+ return 0;
+ }
+}
+
static int tegra_camera_enable_clk(struct tegra_camera_dev *dev)
{
clk_enable(dev->vi_clk);
@@ -227,6 +246,7 @@ static int tegra_camera_power_on(struct tegra_camera_dev *dev)
__func__);
#endif
dev->power_on = 1;
+ tegra_camera_on = dev->power_on;
return ret;
}
@@ -255,6 +275,7 @@ static int tegra_camera_power_off(struct tegra_camera_dev *dev)
}
}
dev->power_on = 0;
+ tegra_camera_on = dev->power_on;
return ret;
}
@@ -425,6 +446,7 @@ static int tegra_camera_probe(struct platform_device *pdev)
mutex_unlock(&dev->tegra_camera_lock);
dev->dev = &pdev->dev;
+ pdata = pdev->dev.platform_data;
/* Get regulator pointer */
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index f37d3ec02123..10dba0cbda97 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -270,6 +270,11 @@ config TWL6040_CORE
select MFD_CORE
default n
+config AIC3262_CODEC
+ bool
+ select MFD_CORE
+ default n
+
config MFD_STMPE
bool "Support STMicroelectronics STMPE"
depends on I2C=y && GENERIC_HARDIRQS
@@ -353,6 +358,19 @@ config PMIC_ADP5520
individual components like LCD backlight, LEDs, GPIOs and Kepad
under the corresponding menus.
+config MFD_MAX77665
+ bool "Maxim Semiconductor MAX77665 Companion PMIC Support"
+ depends on I2C=y && GENERIC_HARDIRQS
+ select MFD_CORE
+ select REGMAP_I2C
+ help
+ Say yes here to support for Maxim Semiconductor MAX77665.
+ This is a Power Management IC with Flash, Fuel Gauge, Haptic,
+ MUIC controls on chip.
+ This driver provides common support for accessing the device;
+ additional drivers must be enabled in order to use the functionality
+ of the device.
+
config MFD_MAX8925
bool "Maxim Semiconductor MAX8925 PMIC Support"
depends on I2C=y && GENERIC_HARDIRQS
@@ -783,6 +801,18 @@ config MFD_PM8XXX_IRQ
config TPS65911_COMPARATOR
tristate
+config MFD_TPS65090
+ bool "TPS65090 Power Management chips"
+ depends on I2C=y && GENERIC_HARDIRQS
+ select MFD_CORE
+ select REGMAP_I2C
+ help
+ If you say yes here you get support for the TPS65090 series of
+ Power Management chips.
+ This driver provides common support for accessing the device,
+ additional drivers must be enabled in order to use the
+ functionality of the device.
+
config MFD_AAT2870_CORE
bool "Support for the AnalogicTech AAT2870"
select MFD_CORE
@@ -804,18 +834,6 @@ config MFD_TPS6591X
additional drivers must be enabled in order to use the
functionality of the device.
-config MFD_TPS65090
- bool "TPS65090 Power Management chips"
- depends on I2C && GENERIC_HARDIRQS
- select MFD_CORE
- select REGMAP_I2C
- help
- If you say yes here you get support for the TPS65090 series of
- Power Management chips.
- This driver provides common support for accessing the device,
- additional drivers must be enabled in order to use the
- functionality of the device.
-
config MFD_RC5T583
bool "Ricoh RC5T583 Power Management system device"
depends on I2C=y && GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 6634515b64e4..c8dc50450219 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o
obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o
+obj-$(CONFIG_AIC3262_CODEC) += tlv320aic3262-core.o tlv320aic3262-irq.o
obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
@@ -67,6 +68,7 @@ endif
obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o
obj-$(CONFIG_PMIC_DA903X) += da903x.o
+obj-$(CONFIG_MFD_MAX77665) += max77665.o
max8925-objs := max8925-core.o max8925-i2c.o
obj-$(CONFIG_MFD_MAX8925) += max8925.o
obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o
@@ -101,9 +103,9 @@ obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o
obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
+obj-$(CONFIG_MFD_TPS65090) += tps65090.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
obj-$(CONFIG_MFD_TPS6591X) += tps6591x.o
-obj-$(CONFIG_MFD_TPS65090) += tps65090.o
obj-$(CONFIG_MFD_TPS80031) += tps80031.o
obj-$(CONFIG_GPADC_TPS80031) += tps8003x-gpadc.o
obj-$(CONFIG_MFD_MAX8907C) += max8907c.o
diff --git a/drivers/mfd/max77665.c b/drivers/mfd/max77665.c
new file mode 100644
index 000000000000..b66712ba5737
--- /dev/null
+++ b/drivers/mfd/max77665.c
@@ -0,0 +1,371 @@
+/*
+ * Core driver for MAXIM MAX77665
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max77665.h>
+#include <linux/slab.h>
+
+#define MAX77665_INT_STS 0x22
+#define MAX77665_INT_MSK 0x23
+#define MAX77665_PMIC_FLASH 0x00 ... 0x10
+#define MAX77665_PMIC_PMIC 0x20 ... 0x2D
+#define MAX77665_PMIC_CHARGER 0xB0 ... 0xC6
+#define MAX77665_MUIC 0x00 ... 0x0E
+#define MAX77665_HAPTIC 0x00 ... 0x10
+
+static u8 max77665_i2c_slave_address[] = {
+ [MAX77665_I2C_SLAVE_PMIC] = 0x66,
+ [MAX77665_I2C_SLAVE_MUIC] = 0x25,
+ [MAX77665_I2C_SLAVE_HAPTIC] = 0x48,
+};
+
+struct max77665_irq_data {
+ int bit;
+};
+
+#define MAX77665_IRQ(_id, _bit_pos) \
+ [MAX77665_IRQ_##_id] = { \
+ .bit = (_bit_pos), \
+ }
+
+static const struct max77665_irq_data max77665_irqs[] = {
+ MAX77665_IRQ(CHARGER, 0),
+ MAX77665_IRQ(TOP_SYS, 1),
+ MAX77665_IRQ(FLASH, 2),
+ MAX77665_IRQ(MUIC, 3),
+};
+
+static struct mfd_cell max77665s[] = {
+ {.name = "max77665-charger",},
+ {.name = "max77665-flash",},
+ {.name = "max77665-muic",},
+ {.name = "max77665-haptic",},
+};
+
+static void max77665_irq_lock(struct irq_data *data)
+{
+ struct max77665 *max77665 = irq_data_get_irq_chip_data(data);
+
+ mutex_lock(&max77665->irq_lock);
+}
+
+static void max77665_irq_mask(struct irq_data *irq_data)
+{
+ struct max77665 *max77665 = irq_data_get_irq_chip_data(irq_data);
+ unsigned int __irq = irq_data->irq - max77665->irq_base;
+ const struct max77665_irq_data *data = &max77665_irqs[__irq];
+ int ret;
+
+ ret = max77665_set_bits(max77665->dev, MAX77665_I2C_SLAVE_PMIC,
+ MAX77665_INT_MSK, data->bit);
+ if (ret < 0)
+ dev_err(max77665->dev,
+ "Clearing mask reg failed e = %d\n", ret);
+}
+
+static void max77665_irq_unmask(struct irq_data *irq_data)
+{
+ struct max77665 *max77665 = irq_data_get_irq_chip_data(irq_data);
+ unsigned int __irq = irq_data->irq - max77665->irq_base;
+ const struct max77665_irq_data *data = &max77665_irqs[__irq];
+ int ret;
+
+ ret = max77665_clr_bits(max77665->dev, MAX77665_I2C_SLAVE_PMIC,
+ MAX77665_INT_MSK, data->bit);
+ if (ret < 0)
+ dev_err(max77665->dev,
+ "Setting mask reg failed e = %d\n", ret);
+}
+
+static void max77665_irq_sync_unlock(struct irq_data *data)
+{
+ struct max77665 *max77665 = irq_data_get_irq_chip_data(data);
+
+ mutex_unlock(&max77665->irq_lock);
+}
+
+static irqreturn_t max77665_irq(int irq, void *data)
+{
+ struct max77665 *max77665 = data;
+ int ret = 0;
+ u8 status = 0;
+ unsigned long int acks = 0;
+ int i;
+
+ ret = max77665_read(max77665->dev, MAX77665_I2C_SLAVE_PMIC,
+ MAX77665_INT_STS, &status);
+ if (ret < 0) {
+ dev_err(max77665->dev,
+ "failed to read status regi, e %d\n", ret);
+ return IRQ_NONE;
+ }
+ acks = status;
+ for_each_set_bit(i, &acks, ARRAY_SIZE(max77665_irqs))
+ handle_nested_irq(max77665->irq_base + i);
+ return acks ? IRQ_HANDLED : IRQ_NONE;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int max77665_irq_set_wake(struct irq_data *data, unsigned int enable)
+{
+ struct max77665 *max77665 = irq_data_get_irq_chip_data(data);
+
+ return irq_set_irq_wake(max77665->irq_base, enable);
+}
+
+#else
+#define max77665_irq_set_wake NULL
+#endif
+
+static int __devinit max77665_irq_init(struct max77665 *max77665, int irq,
+ int irq_base)
+{
+ int i, ret;
+
+ if (irq_base <= 0) {
+ dev_err(max77665->dev, "IRQ base not set, int not supported\n");
+ return -EINVAL;
+ }
+
+ mutex_init(&max77665->irq_lock);
+
+ ret = max77665_write(max77665->dev, MAX77665_I2C_SLAVE_PMIC,
+ MAX77665_INT_MSK, 0xFF);
+ if (ret < 0) {
+ dev_err(max77665->dev,
+ "Int mask reg write failed, e %d\n", ret);
+ return ret;
+ }
+
+ max77665->irq_base = irq_base;
+ max77665->irq_chip.name = "max77665";
+ max77665->irq_chip.irq_mask = max77665_irq_mask;
+ max77665->irq_chip.irq_unmask = max77665_irq_unmask;
+ max77665->irq_chip.irq_bus_lock = max77665_irq_lock;
+ max77665->irq_chip.irq_bus_sync_unlock = max77665_irq_sync_unlock;
+ max77665->irq_chip.irq_set_wake = max77665_irq_set_wake;
+
+ for (i = 0; i < ARRAY_SIZE(max77665_irqs); i++) {
+ int __irq = i + max77665->irq_base;
+ irq_set_chip_data(__irq, max77665);
+ irq_set_chip_and_handler(__irq, &max77665->irq_chip,
+ handle_simple_irq);
+ irq_set_nested_thread(__irq, 1);
+#ifdef CONFIG_ARM
+ set_irq_flags(__irq, IRQF_VALID);
+#endif
+ }
+
+ ret = request_threaded_irq(irq, NULL, max77665_irq, IRQF_ONESHOT,
+ "max77665", max77665);
+ if (ret < 0) {
+ dev_err(max77665->dev, "Int registration failed, e %d\n", ret);
+ return ret;
+ }
+
+ device_init_wakeup(max77665->dev, 1);
+ return ret;
+}
+
+static bool rd_wr_reg_pmic(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MAX77665_PMIC_FLASH:
+ case MAX77665_PMIC_PMIC:
+ case MAX77665_PMIC_CHARGER:
+ return true;
+ default:
+ dev_err(dev, "non-existing reg %s() reg 0x%x\n", __func__, reg);
+ return false;
+ }
+}
+
+static bool rd_wr_reg_muic(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MAX77665_MUIC:
+ return true;
+ default:
+ dev_err(dev, "non-existing reg %s() reg 0x%x\n", __func__, reg);
+ return false;
+ }
+}
+
+static bool rd_wr_reg_haptic(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MAX77665_HAPTIC:
+ return true;
+ default:
+ dev_err(dev, "non-existing reg %s() reg 0x%x\n", __func__, reg);
+ return false;
+ }
+}
+
+static const struct regmap_config max77665_regmap_config[] = {
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xFF,
+ .writeable_reg = rd_wr_reg_pmic,
+ .readable_reg = rd_wr_reg_pmic,
+ .cache_type = REGCACHE_RBTREE,
+ }, {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x0E,
+ .writeable_reg = rd_wr_reg_muic,
+ .readable_reg = rd_wr_reg_muic,
+ .cache_type = REGCACHE_RBTREE,
+ }, {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x10,
+ .writeable_reg = rd_wr_reg_haptic,
+ .readable_reg = rd_wr_reg_haptic,
+ .cache_type = REGCACHE_RBTREE,
+ },
+};
+
+static int __devinit max77665_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max77665_platform_data *pdata = client->dev.platform_data;
+ struct max77665 *max77665;
+ struct i2c_client *slv_client;
+ int ret;
+ int i;
+
+ if (!pdata) {
+ dev_err(&client->dev, "max77665 requires platform data\n");
+ return -EINVAL;
+ }
+
+ max77665 = devm_kzalloc(&client->dev, sizeof(*max77665), GFP_KERNEL);
+ if (!max77665) {
+ dev_err(&client->dev, "mem alloc for max77665 failed\n");
+ return -ENOMEM;
+ }
+
+ max77665->dev = &client->dev;
+
+ for (i = 0; i < MAX77665_I2C_SLAVE_MAX; ++i) {
+ slv_client = max77665->client[i];
+ if (i == 0)
+ slv_client = client;
+ else
+ slv_client = i2c_new_dummy(client->adapter,
+ max77665_i2c_slave_address[i]);
+ if (!slv_client) {
+ dev_err(&client->dev, "can't attach client %d\n", i);
+ ret = -ENOMEM;
+ goto err_exit;
+ }
+ i2c_set_clientdata(slv_client, max77665);
+
+ max77665->regmap[i] = devm_regmap_init_i2c(slv_client,
+ &max77665_regmap_config[i]);
+ if (IS_ERR(max77665->regmap[i])) {
+ ret = PTR_ERR(max77665->regmap[i]);
+ dev_err(&client->dev,
+ "regmap %d init failed with err: %d\n", i, ret);
+ goto err_exit;
+ }
+ }
+
+ if (client->irq > 0)
+ max77665_irq_init(max77665, client->irq, pdata->irq_base);
+
+ ret = mfd_add_devices(max77665->dev, -1, max77665s,
+ ARRAY_SIZE(max77665s), NULL, 0);
+ if (ret) {
+ dev_err(&client->dev, "add mfd devices failed with err: %d\n",
+ ret);
+ goto err_irq_exit;
+ }
+
+ return 0;
+
+err_irq_exit:
+ if (client->irq > 0)
+ free_irq(client->irq, max77665);
+err_exit:
+ for (i = 0; i < MAX77665_I2C_SLAVE_MAX; ++i) {
+ slv_client = max77665->client[i];
+ if (slv_client && slv_client != client)
+ i2c_unregister_device(slv_client);
+ }
+ return ret;
+}
+
+static int __devexit max77665_i2c_remove(struct i2c_client *client)
+{
+ struct max77665 *max77665 = i2c_get_clientdata(client);
+ int i;
+ struct i2c_client *slv_client;
+
+ mfd_remove_devices(max77665->dev);
+ if (client->irq > 0)
+ free_irq(client->irq, max77665);
+
+ for (i = 0; i < MAX77665_I2C_SLAVE_MAX; ++i) {
+ slv_client = max77665->client[i];
+ if (slv_client && slv_client != client)
+ i2c_unregister_device(slv_client);
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id max77665_id_table[] = {
+ { "max77665", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, max77665_id_table);
+
+static struct i2c_driver max77665_driver = {
+ .driver = {
+ .name = "max77665",
+ .owner = THIS_MODULE,
+ },
+ .probe = max77665_i2c_probe,
+ .remove = __devexit_p(max77665_i2c_remove),
+ .id_table = max77665_id_table,
+};
+
+static int __init max77665_init(void)
+{
+ return i2c_add_driver(&max77665_driver);
+}
+subsys_initcall(max77665_init);
+
+static void __exit max77665_exit(void)
+{
+ i2c_del_driver(&max77665_driver);
+}
+module_exit(max77665_exit);
+
+MODULE_DESCRIPTION("MAXIM MAX77665 core driver");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/tlv320aic3262-core.c b/drivers/mfd/tlv320aic3262-core.c
new file mode 100644
index 000000000000..7b61c7497a45
--- /dev/null
+++ b/drivers/mfd/tlv320aic3262-core.c
@@ -0,0 +1,885 @@
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+#include <linux/mfd/core.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
+
+#include <linux/mfd/tlv320aic3262-core.h>
+#include <linux/mfd/tlv320aic3262-registers.h>
+#define DEBUG
+struct aic3262_gpio {
+ unsigned int reg;
+ u8 mask;
+ u8 shift;
+};
+struct aic3262_gpio aic3262_gpio_control[] = {
+ {
+ .reg = AIC3262_GPIO1_IO_CNTL,
+ .mask = AIC3262_GPIO_D6_D2,
+ .shift = AIC3262_GPIO_D2_SHIFT,
+ },
+ {
+ .reg = AIC3262_GPIO2_IO_CNTL,
+ .mask = AIC3262_GPIO_D6_D2,
+ .shift = AIC3262_GPIO_D2_SHIFT,
+ },
+ {
+ .reg = AIC3262_GPI1_EN,
+ .mask = AIC3262_GPI1_D2_D1,
+ .shift = AIC3262_GPIO_D1_SHIFT,
+ },
+ {
+ .reg = AIC3262_GPI2_EN,
+ .mask = AIC3262_GPI2_D5_D4,
+ .shift = AIC3262_GPIO_D4_SHIFT,
+ },
+ {
+ .reg = AIC3262_GPO1_OUT_CNTL,
+ .mask = AIC3262_GPO1_D4_D1,
+ .shift = AIC3262_GPIO_D1_SHIFT,
+ },
+};
+static int aic3262_read(struct aic3262 *aic3262, unsigned int reg,
+ int bytes, void *dest)
+{
+ int ret;
+ int i;
+ u8 *buf = dest;
+
+ BUG_ON(bytes <= 0);
+
+ ret = aic3262->read_dev(aic3262, reg, bytes, dest);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < bytes ; i++) {
+ dev_vdbg(aic3262->dev, "Read %04x from R%d(0x%x)\n",
+ buf[i], reg + i, reg + i);
+ }
+
+ return ret;
+}
+
+/**
+ * aic3262_reg_read: Read a single TLV320AIC3262 register.
+ *
+ * @aic3262: Device to read from.
+ * @reg: Register to read.
+ */
+int aic3262_reg_read(struct aic3262 *aic3262, unsigned int reg)
+{
+ unsigned char val;
+ int ret;
+
+ mutex_lock(&aic3262->io_lock);
+
+ ret = aic3262_read(aic3262, reg, 1, &val);
+
+ mutex_unlock(&aic3262->io_lock);
+
+ if (ret < 0)
+ return ret;
+ else
+ return val;
+}
+EXPORT_SYMBOL_GPL(aic3262_reg_read);
+
+/**
+ * aic3262_bulk_read: Read multiple TLV320AIC3262 registers
+ *
+ * @aic3262: Device to read from
+ * @reg: First register
+ * @count: Number of registers
+ * @buf: Buffer to fill. The data will be returned big endian.
+ */
+int aic3262_bulk_read(struct aic3262 *aic3262, unsigned int reg,
+ int count, u8 *buf)
+{
+ int ret;
+
+ mutex_lock(&aic3262->io_lock);
+
+ ret = aic3262_read(aic3262, reg, count, buf);
+
+ mutex_unlock(&aic3262->io_lock);
+
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(aic3262_bulk_read);
+
+static int aic3262_write(struct aic3262 *aic3262, unsigned int reg,
+ int bytes, const void *src)
+{
+ const u8 *buf = src;
+ int i;
+
+ BUG_ON(bytes <= 0);
+
+ for (i = 0; i < bytes ; i++) {
+ dev_vdbg(aic3262->dev, "Write %04x to R%d(0x%x)\n",
+ buf[i], reg + i, reg + i);
+ }
+
+ return aic3262->write_dev(aic3262, reg, bytes, src);
+}
+
+/**
+ * aic3262_reg_write: Write a single TLV320AIC3262 register.
+ *
+ * @aic3262: Device to write to.
+ * @reg: Register to write to.
+ * @val: Value to write.
+ */
+int aic3262_reg_write(struct aic3262 *aic3262, unsigned int reg,
+ unsigned char val)
+{
+ int ret;
+
+
+ mutex_lock(&aic3262->io_lock);
+
+ dev_dbg(aic3262->dev, "w 30 %x %x", reg, val);
+ ret = aic3262_write(aic3262, reg, 1, &val);
+
+ mutex_unlock(&aic3262->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(aic3262_reg_write);
+
+/**
+ * aic3262_bulk_write: Write multiple TLV320AIC3262 registers
+ *
+ * @aic3262: Device to write to
+ * @reg: First register
+ * @count: Number of registers
+ * @buf: Buffer to write from. Data must be big-endian formatted.
+ */
+int aic3262_bulk_write(struct aic3262 *aic3262, unsigned int reg,
+ int count, const u8 *buf)
+{
+ int ret;
+
+ mutex_lock(&aic3262->io_lock);
+
+ ret = aic3262_write(aic3262, reg, count, buf);
+
+ mutex_unlock(&aic3262->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(aic3262_bulk_write);
+
+/**
+ * aic3262_set_bits: Set the value of a bitfield in a TLV320AIC3262 register
+ *
+ * @aic3262: Device to write to.
+ * @reg: Register to write to.
+ * @mask: Mask of bits to set.
+ * @val: Value to set (unshifted)
+ */
+int aic3262_set_bits(struct aic3262 *aic3262, unsigned int reg,
+ unsigned char mask, unsigned char val)
+{
+ int ret;
+ u8 r;
+
+ mutex_lock(&aic3262->io_lock);
+
+ ret = aic3262_read(aic3262, reg, 1, &r);
+ if (ret < 0)
+ goto out;
+
+
+ r &= ~mask;
+ r |= (val & mask);
+
+ dev_dbg(aic3262->dev, "w 30 %x %x", reg, r);
+ ret = aic3262_write(aic3262, reg, 1, &r);
+
+out:
+ mutex_unlock(&aic3262->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(aic3262_set_bits);
+
+/**
+ * aic3262_wait_bits: wait for a value of a bitfield in a TLV320AIC3262 register
+ *
+ * @aic3262: Device to write to.
+ * @reg: Register to write to.
+ * @mask: Mask of bits to set.
+ * @val: Value to set (unshifted)
+ * @sleep: mdelay value in each iteration in milliseconds
+ * @count: iteration count for timeout
+ */
+int aic3262_wait_bits(struct aic3262 *aic3262, unsigned int reg,
+ unsigned char mask, unsigned char val, int sleep, int counter)
+{
+ int status;
+ int timeout = sleep*counter;
+
+ status = aic3262_reg_read(aic3262, reg);
+ while (((status & mask) != val) && counter) {
+ mdelay(sleep);
+ status = aic3262_reg_read(aic3262, reg);
+ counter--;
+ };
+ if (!counter)
+ dev_err(aic3262->dev,
+ "wait_bits timedout (%d millisecs). lastval 0x%x\n",
+ timeout, status);
+ return counter;
+}
+EXPORT_SYMBOL_GPL(aic3262_wait_bits);
+
+/* to be changed -- Mukund*/
+static struct resource aic3262_codec_resources[] = {
+ {
+ .start = AIC3262_IRQ_HEADSET_DETECT,
+ .end = AIC3262_IRQ_SPEAKER_OVER_TEMP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource aic3262_gpio_resources[] = {
+ {
+ .start = AIC3262_GPIO1,
+ .end = AIC3262_GPO1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mfd_cell aic3262_devs[] = {
+ {
+ .name = "tlv320aic3262-codec",
+ .num_resources = ARRAY_SIZE(aic3262_codec_resources),
+ .resources = aic3262_codec_resources,
+ },
+
+ {
+ .name = "tlv320aic3262-gpio",
+ .num_resources = ARRAY_SIZE(aic3262_gpio_resources),
+ .resources = aic3262_gpio_resources,
+ .pm_runtime_no_callbacks = true,
+ },
+};
+
+
+#ifdef CONFIG_PM
+static int aic3262_suspend(struct device *dev)
+{
+ struct aic3262 *aic3262 = dev_get_drvdata(dev);
+
+ aic3262->suspended = true;
+
+ return 0;
+}
+
+static int aic3262_resume(struct device *dev)
+{
+ struct aic3262 *aic3262 = dev_get_drvdata(dev);
+
+
+ aic3262->suspended = false;
+
+ return 0;
+}
+
+static UNIVERSAL_DEV_PM_OPS(aic3262_pm_ops, aic3262_suspend, aic3262_resume,
+ NULL);
+#endif
+
+
+/*
+ * Instantiate the generic non-control parts of the device.
+ */
+static int aic3262_device_init(struct aic3262 *aic3262, int irq)
+{
+ struct aic3262_pdata *pdata = aic3262->dev->platform_data;
+ const char *devname;
+ int ret, i;
+ u8 revID, pgID;
+ unsigned int naudint = 0;
+ u8 resetVal = 1;
+
+ mutex_init(&aic3262->io_lock);
+ dev_set_drvdata(aic3262->dev, aic3262);
+ if (pdata) {
+ if (pdata->gpio_reset) {
+ ret = gpio_request(pdata->gpio_reset,
+ "aic3262-reset-pin");
+ if (ret != 0) {
+ dev_err(aic3262->dev,
+ "Failed to reset aic3262 using gpio %d\n",
+ pdata->gpio_reset);
+ goto err_return;
+ }
+ gpio_direction_output(pdata->gpio_reset, 1);
+ mdelay(5);
+ gpio_direction_output(pdata->gpio_reset, 0);
+ mdelay(5);
+ gpio_direction_output(pdata->gpio_reset, 1);
+ mdelay(5);
+ }
+ }
+
+
+ /* run the codec through software reset */
+ ret = aic3262_reg_write(aic3262, AIC3262_RESET_REG, resetVal);
+ if (ret < 0) {
+ dev_err(aic3262->dev, "Could not write to AIC3262 register\n");
+ goto err_return;
+ }
+
+ mdelay(10);
+
+ ret = aic3262_reg_read(aic3262, AIC3262_REV_PG_ID);
+ if (ret < 0) {
+ dev_err(aic3262->dev, "Failed to read ID register\n");
+ goto err_return;
+ }
+ revID = (ret & AIC3262_REV_MASK) >> AIC3262_REV_SHIFT;
+ pgID = (ret & AIC3262_PG_MASK) >> AIC3262_PG_SHIFT;
+ switch (revID) {
+ case 3:
+ devname = "TLV320AIC3262";
+ if (aic3262->type != TLV320AIC3262)
+ dev_warn(aic3262->dev, "Device registered as type %d\n",
+ aic3262->type);
+ aic3262->type = TLV320AIC3262;
+ break;
+ case 1:
+ devname = "TLV320AIC3262";
+ if (aic3262->type != TLV320AIC3262)
+ dev_warn(aic3262->dev, "Device registered as type %d\n",
+ aic3262->type);
+ aic3262->type = TLV320AIC3262;
+ break;
+
+ default:
+ dev_err(aic3262->dev, "Device is not a TLV320AIC3262, ID is %x\n",
+ ret);
+ ret = -EINVAL;
+ goto err_return;
+
+ }
+
+ dev_info(aic3262->dev, "%s revision %c\n", devname, 'D' + ret);
+
+
+ if (pdata) {
+ if (pdata->gpio_irq == 1) {
+ naudint = gpio_to_irq(pdata->naudint_irq);
+ gpio_request(pdata->naudint_irq, "aic3262-gpio-irq");
+ gpio_direction_input(pdata->naudint_irq);
+ } else
+ naudint = pdata->naudint_irq;
+
+ aic3262->irq = naudint;
+ aic3262->irq_base = pdata->irq_base;
+ for (i = 0; i < AIC3262_NUM_GPIO; i++) {
+ if (pdata->gpio[i].used) {
+ /* Direction is input */
+ if (pdata->gpio[i].in) {
+ /* set direction to input for GPIO,
+ and enable for GPI */
+ aic3262_set_bits(aic3262,
+ aic3262_gpio_control[i].reg,
+ aic3262_gpio_control[i].mask,
+ 0x1 <<
+ aic3262_gpio_control[i].shift);
+
+ if (pdata->gpio[i].in_reg)
+ /* Some input modes, does not
+ need extra registers to be
+ written */
+ aic3262_set_bits(aic3262,
+ pdata->gpio[i].in_reg,
+ pdata->gpio[i].
+ in_reg_bitmask,
+ pdata->gpio[i].value <<
+ pdata->gpio[i].
+ in_reg_shift);
+ } else {
+ /* Direction si output */
+ aic3262_set_bits(aic3262,
+ aic3262_gpio_control[i].reg,
+ aic3262_gpio_control[i].mask,
+ pdata->gpio[i].value <<
+ aic3262_gpio_control[i].shift);
+ }
+ } else
+ aic3262_set_bits(aic3262,
+ aic3262_gpio_control[i].reg,
+ aic3262_gpio_control[i].mask, 0x0);
+ }
+ }
+
+ if (naudint) {
+ /* codec interrupt */
+ ret = aic3262_irq_init(aic3262);
+ if (ret)
+ goto err_irq;
+ }
+
+ ret = mfd_add_devices(aic3262->dev, -1,
+ aic3262_devs, ARRAY_SIZE(aic3262_devs),
+ NULL, 0);
+ if (ret != 0) {
+ dev_err(aic3262->dev, "Failed to add children: %d\n", ret);
+ goto err_irq;
+ }
+
+ pm_runtime_enable(aic3262->dev);
+ pm_runtime_resume(aic3262->dev);
+
+ return 0;
+
+err_irq:
+ aic3262_irq_exit(aic3262);
+err_return:
+ kfree(aic3262);
+ return ret;
+}
+
+static void aic3262_device_exit(struct aic3262 *aic3262)
+{
+ pm_runtime_disable(aic3262->dev);
+ mfd_remove_devices(aic3262->dev);
+ aic3262_irq_exit(aic3262);
+ kfree(aic3262);
+}
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+
+static int aic3262_i2c_read_device(struct aic3262 *aic3262, unsigned int reg,
+ int bytes, void *dest)
+{
+ struct i2c_client *i2c = aic3262->control_data;
+ union aic326x_reg_union *aic_reg = (union aic326x_reg_union *) &reg;
+ char *value;
+ int ret;
+ u8 buf[2];
+ u8 page, book, offset;
+ page = aic_reg->aic326x_register.page;
+ book = aic_reg->aic326x_register.book;
+ offset = aic_reg->aic326x_register.offset;
+ if (aic3262->book_no != book) {
+ /* We should change to page 0.
+ Change the book by writing to offset 127 of page 0
+ Change the page back to whatever was set before change page */
+ buf[0] = 0x0;
+ buf[1] = 0x0;
+ ret = i2c_master_send(i2c, (unsigned char *)buf, 2);
+ if (ret < 0)
+ return ret;
+ if (ret != 2)
+ return -EIO;
+ buf[0] = 127;
+ buf[1] = book;
+ ret = i2c_master_send(i2c, (unsigned char *)buf, 2);
+ if (ret < 0)
+ return ret;
+ if (ret != 2)
+ return -EIO;
+ aic3262->book_no = book;
+ aic3262->page_no = 0x0;
+ }
+
+ if (aic3262->page_no != page) {
+ buf[0] = 0x0;
+ buf[1] = page;
+ ret = i2c_master_send(i2c, (unsigned char *) buf, 2);
+
+ if (ret < 0)
+ return ret;
+ if (ret != 2)
+ return -EIO;
+ aic3262->page_no = page;
+ }
+
+ /* Send the required offset */
+ buf[0] = offset ;
+ ret = i2c_master_send(i2c, (unsigned char *)buf, 1);
+ if (ret < 0)
+ return ret;
+ if (ret != 1)
+ return -EIO;
+
+ ret = i2c_master_recv(i2c, dest, bytes);
+ value = dest;
+ if (ret < 0)
+ return ret;
+ if (ret != bytes)
+ return -EIO;
+ return ret;
+}
+
+static int aic3262_i2c_write_device(struct aic3262 *aic3262, unsigned int reg,
+ int bytes, const void *src)
+{
+ struct i2c_client *i2c = aic3262->control_data;
+ int ret;
+
+ union aic326x_reg_union *aic_reg = (union aic326x_reg_union *) &reg;
+
+ u8 buf[2];
+ u8 write_buf[bytes + 1];
+ u8 page, book, offset;
+ page = aic_reg->aic326x_register.page;
+ book = aic_reg->aic326x_register.book;
+ offset = aic_reg->aic326x_register.offset;
+ if (aic3262->book_no != book) {
+ /* We should change to page 0.
+ Change the book by writing to offset 127 of page 0
+ Change the page back to whatever was set before change page*/
+ buf[0] = 0x0;
+ buf[1] = 0x0;
+ ret = i2c_master_send(i2c, (unsigned char *)buf, 2);
+
+ if (ret < 0)
+ return ret;
+ if (ret != 2)
+ return -EIO;
+ buf[0] = 127;
+ buf[1] = book;
+ ret = i2c_master_send(i2c, (unsigned char *)buf, 2);
+ if (ret < 0)
+ return ret;
+ if (ret != 2)
+ return -EIO;
+ aic3262->book_no = book;
+ aic3262->page_no = 0x0;
+ }
+
+ if (aic3262->page_no != page) {
+ buf[0] = 0x0;
+ buf[1] = page;
+ ret = i2c_master_send(i2c, (unsigned char *) buf, 2);
+ if (ret < 0)
+ return ret;
+ if (ret != 2)
+ return -EIO;
+ aic3262->page_no = page;
+ }
+ write_buf[0] = offset;
+ memcpy(&write_buf[1], src, bytes);
+ ret = i2c_master_send(i2c, write_buf, bytes + 1);
+ if (ret < 0)
+ return ret;
+ if (ret != (bytes + 1))
+ return -EIO;
+
+ return 0;
+}
+
+static int aic3262_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct aic3262 *aic3262;
+
+ aic3262 = kzalloc(sizeof(struct aic3262), GFP_KERNEL);
+ if (aic3262 == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, aic3262);
+ aic3262->dev = &i2c->dev;
+ aic3262->control_data = i2c;
+ aic3262->read_dev = aic3262_i2c_read_device;
+ aic3262->write_dev = aic3262_i2c_write_device;
+ aic3262->type = id->driver_data;
+ aic3262->book_no = 255;
+ aic3262->page_no = 255;
+
+ return aic3262_device_init(aic3262, i2c->irq);
+}
+
+static int aic3262_i2c_remove(struct i2c_client *i2c)
+{
+ struct aic3262 *aic3262 = i2c_get_clientdata(i2c);
+
+ aic3262_device_exit(aic3262);
+
+ return 0;
+}
+
+static const struct i2c_device_id aic3262_i2c_id[] = {
+ { "tlv320aic3262", TLV320AIC3262 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, aic3262_i2c_id);
+
+
+static struct i2c_driver aic3262_i2c_driver = {
+ .driver = {
+ .name = "tlv320aic3262",
+ .owner = THIS_MODULE,
+ .pm = &aic3262_pm_ops,
+ },
+ .probe = aic3262_i2c_probe,
+ .remove = aic3262_i2c_remove,
+ .id_table = aic3262_i2c_id,
+};
+
+static int __init aic3262_i2c_init(void)
+{
+ int ret;
+ ret = i2c_add_driver(&aic3262_i2c_driver);
+ if (ret != 0)
+ pr_err("Failed to register aic3262 I2C driver: %d\n", ret);
+
+ return ret;
+}
+module_init(aic3262_i2c_init);
+
+static void __exit aic3262_i2c_exit(void)
+{
+ i2c_del_driver(&aic3262_i2c_driver);
+}
+module_exit(aic3262_i2c_exit);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+/* TODO: UGLY
+ * NVidia's CS differs from what TI requires on the SPI bus. So before
+ * we do any write/read we pull down the CS gpio :(
+ * The problem is in spi_read.
+ * Can we set the flag spi_transfer.cs_change during read so that CS is
+ * pulled low until the next transaction occurs
+ * (spi_read requires a spi_write followed by spi_read)
+ */
+#include <linux/gpio.h>
+#include "../../../arch/arm/mach-tegra/gpio-names.h"
+#include <linux/delay.h>
+#define SPI_CS TEGRA_GPIO_PX3
+#define CS(a) gpio_set_value(SPI_CS, a)
+void nvidia_spi_cs_en(bool stop)
+{
+ if (stop) {
+ CS(1);
+ udelay(1);
+ } else {
+ CS(0);
+ udelay(1);
+ }
+ return;
+}
+static int aic3262_spi_read_device(struct aic3262 *aic3262, unsigned int reg,
+ int bytes, void *dest)
+{
+ struct spi_device *spi = aic3262->control_data;
+ union aic326x_reg_union *aic_reg = (union aic326x_reg_union *) &reg;
+ u8 *write_read_buf;
+ unsigned int i;
+ unsigned int time;
+ unsigned int last_count;
+ unsigned int spi_read_bufsize = max(32, SMP_CACHE_BYTES)-1;
+ struct spi_message message;
+ struct spi_transfer x[2];
+ int ret;
+ u8 buf[2];
+ u8 page, book, offset;
+ page = aic_reg->aic326x_register.page;
+ book = aic_reg->aic326x_register.book;
+ offset = aic_reg->aic326x_register.offset;
+ if (aic3262->book_no != book) {
+ /* We should change to page 0.
+ Change the book by writing to offset 127 of page 0
+ Change the page back to whatever was set before change page */
+
+ buf[0] = 0x0;
+ buf[1] = 0x0;
+
+ nvidia_spi_cs_en(0);
+ ret = spi_write(spi, (unsigned char *)buf, 2);
+ nvidia_spi_cs_en(1);
+
+ if (ret < 0)
+ return ret;
+ buf[0] = (127 << 1) ;
+ buf[1] = book;
+
+ nvidia_spi_cs_en(0);
+ ret = spi_write(spi, (unsigned char *)buf, 2);
+ nvidia_spi_cs_en(1);
+
+ if (ret < 0)
+ return ret;
+ aic3262->book_no = book;
+ aic3262->page_no = 0x0;
+ }
+
+ if (aic3262->page_no != page) {
+ buf[0] = 0x0;
+ buf[1] = page;
+
+ nvidia_spi_cs_en(0);
+ ret = spi_write(spi, (unsigned char *)buf, 2);
+ nvidia_spi_cs_en(1);
+
+ if (ret < 0)
+ return ret;
+ aic3262->page_no = page;
+ }
+
+ buf[0] = (offset << 1) | (0x01) ;
+ memset(x, 0, sizeof x);
+ spi_message_init(&message);
+ x[0].len = 1;
+ x[0].tx_buf = buf;
+ x[1].len = bytes;
+ x[1].rx_buf = dest ;
+
+ spi_message_add_tail(&x[0], &message);
+ spi_message_add_tail(&x[1], &message);
+
+ nvidia_spi_cs_en(0);
+ ret = spi_sync(spi, &message);
+ nvidia_spi_cs_en(1);
+ if (ret < 0)
+ return ret;
+
+ return bytes;
+
+}
+/* NVidia's CS differs from what TI requires on the SPI bus. So before
+ * we do any write/read we pull down the CS gpio :(
+ */
+static int aic3262_spi_write_device(struct aic3262 *aic3262, unsigned int reg,
+ int bytes, const void *src)
+{
+ struct spi_device *spi = aic3262->control_data;
+ int ret;
+
+ union aic326x_reg_union *aic_reg = (union aic326x_reg_union *) &reg;
+
+ u8 buf[2];
+ u8 write_buf[bytes + 1];
+ u8 page, book, offset;
+ page = aic_reg->aic326x_register.page;
+ book = aic_reg->aic326x_register.book;
+ offset = aic_reg->aic326x_register.offset;
+ if (aic3262->book_no != book) {
+ /* We should change to page 0.
+ Change the book by writing to offset 127 of page 0
+ Change the page back to whatever was set before change page */
+
+ buf[0] = 0x0;
+ buf[1] = 0x0;
+
+ nvidia_spi_cs_en(0);
+ ret = spi_write(spi, (unsigned char *)buf, 2);
+ nvidia_spi_cs_en(1);
+
+ if (ret < 0)
+ return ret;
+ buf[0] = (127 << 1) ;
+ buf[1] = book;
+
+ nvidia_spi_cs_en(0);
+ ret = spi_write(spi, (unsigned char *)buf, 2);
+ nvidia_spi_cs_en(1);
+
+ if (ret < 0)
+ return ret;
+ aic3262->book_no = book;
+ aic3262->page_no = 0x0;
+ }
+
+ if (aic3262->page_no != page) {
+ buf[0] = 0x0;
+ buf[1] = page;
+ nvidia_spi_cs_en(0);
+ ret = spi_write(spi, (unsigned char *) buf, 2);
+ nvidia_spi_cs_en(1);
+ if (ret < 0)
+ return ret;
+ aic3262->page_no = page;
+ }
+ write_buf[0] = offset << 1 ;
+ memcpy(&write_buf[1], src, bytes);
+ nvidia_spi_cs_en(0);
+ ret = spi_write(spi, write_buf, bytes + 1);
+ nvidia_spi_cs_en(1);
+ if (ret < 0)
+ return ret;
+
+ return bytes;
+}
+
+static int aic3262_spi_probe(struct spi_device *spi)
+{
+ struct aic3262 *aic3262;
+
+ aic3262 = kzalloc(sizeof(struct aic3262), GFP_KERNEL);
+ if (aic3262 == NULL)
+ return -ENOMEM;
+
+ spi_set_drvdata(spi, aic3262);
+ aic3262->dev = &spi->dev;
+ aic3262->control_data = spi;
+ aic3262->read_dev = aic3262_spi_read_device;
+ aic3262->write_dev = aic3262_spi_write_device;
+ spi->bits_per_word = 8;
+ spi->mode = SPI_MODE_1;
+ spi->max_speed_hz = 4000*1000;
+ spi_setup(spi);
+
+ if (strcmp(spi->modalias, "tlv320aic3262") == 0)
+ aic3262->type = TLV320AIC3262;
+ aic3262->book_no = 255;
+ aic3262->page_no = 255;
+
+ return aic3262_device_init(aic3262, spi->irq);
+}
+
+static int aic3262_spi_remove(struct spi_device *spi)
+{
+ struct aic3262 *aic3262 = spi_get_drvdata(spi);
+
+ aic3262_device_exit(aic3262);
+
+ return 0;
+}
+
+static struct spi_driver aic3262_spi_driver = {
+ .driver = {
+ .name = "tlv320aic3262",
+ .owner = THIS_MODULE,
+ .pm = &aic3262_pm_ops,
+ },
+ .probe = aic3262_spi_probe,
+ .remove = aic3262_spi_remove,
+};
+
+static int __init aic3262_spi_init(void)
+{
+ int ret;
+ ret = spi_register_driver(&aic3262_spi_driver);
+ if (ret != 0)
+ pr_err("Failed to register aic3262 SPI driver: %d\n", ret);
+
+ return ret;
+}
+module_init(aic3262_spi_init);
+
+static void __exit aic3262_spi_exit(void)
+{
+ spi_unregister_driver(&aic3262_spi_driver);
+}
+module_exit(aic3262_spi_exit);
+#endif
+
+MODULE_DESCRIPTION("Core support for the TLV320AIC3262 audio CODEC");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mukund Navada <navada@ti.com>");
diff --git a/drivers/mfd/tlv320aic3262-irq.c b/drivers/mfd/tlv320aic3262-irq.c
new file mode 100644
index 000000000000..7e7a5499f3e5
--- /dev/null
+++ b/drivers/mfd/tlv320aic3262-irq.c
@@ -0,0 +1,204 @@
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/interrupt.h>
+
+#include <linux/mfd/tlv320aic3262-core.h>
+#include <linux/mfd/tlv320aic3262-registers.h>
+
+#include <linux/delay.h>
+struct aic3262_irq_data {
+ int mask;
+ int status;
+};
+
+static struct aic3262_irq_data aic3262_irqs[] = {
+ {
+ .mask = AIC3262_HEADSET_IN_MASK,
+ .status = AIC3262_HEADSET_PLUG_UNPLUG_INT,
+ },
+ {
+ .mask = AIC3262_BUTTON_PRESS_MASK,
+ .status = AIC3262_BUTTON_PRESS_INT,
+ },
+ {
+ .mask = AIC3262_DAC_DRC_THRES_MASK,
+ .status = AIC3262_LEFT_DRC_THRES_INT | AIC3262_RIGHT_DRC_THRES_INT,
+ },
+ {
+ .mask = AIC3262_AGC_NOISE_MASK,
+ .status = AIC3262_LEFT_AGC_NOISE_INT | AIC3262_RIGHT_AGC_NOISE_INT,
+ },
+ {
+ .mask = AIC3262_OVER_CURRENT_MASK,
+ .status = AIC3262_LEFT_OUTPUT_DRIVER_OVERCURRENT_INT
+ | AIC3262_RIGHT_OUTPUT_DRIVER_OVERCURRENT_INT,
+ },
+ {
+ .mask = AIC3262_OVERFLOW_MASK,
+ .status =
+ AIC3262_LEFT_DAC_OVERFLOW_INT | AIC3262_RIGHT_DAC_OVERFLOW_INT |
+ AIC3262_MINIDSP_D_BARREL_SHIFT_OVERFLOW_INT |
+ AIC3262_LEFT_ADC_OVERFLOW_INT | AIC3262_RIGHT_ADC_OVERFLOW_INT |
+ AIC3262_MINIDSP_D_BARREL_SHIFT_OVERFLOW_INT,
+ },
+ {
+ .mask = AIC3262_SPK_OVERCURRENT_MASK,
+ .status = AIC3262_SPK_OVER_CURRENT_INT,
+ },
+
+};
+
+struct aic3262_gpio_data {
+
+};
+
+static inline struct aic3262_irq_data *irq_to_aic3262_irq(struct aic3262
+ *aic3262, int irq)
+{
+ return &aic3262_irqs[irq - aic3262->irq_base];
+}
+
+static void aic3262_irq_lock(struct irq_data *data)
+{
+ struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
+
+ mutex_lock(&aic3262->irq_lock);
+}
+
+static void aic3262_irq_sync_unlock(struct irq_data *data)
+{
+ struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
+
+ /* write back to hardware any change in irq mask */
+ if (aic3262->irq_masks_cur != aic3262->irq_masks_cache) {
+ aic3262->irq_masks_cache = aic3262->irq_masks_cur;
+ aic3262_reg_write(aic3262, AIC3262_INT1_CNTL,
+ aic3262->irq_masks_cur);
+ }
+
+ mutex_unlock(&aic3262->irq_lock);
+}
+
+static void aic3262_irq_unmask(struct irq_data *data)
+{
+ struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
+ struct aic3262_irq_data *irq_data =
+ irq_to_aic3262_irq(aic3262, data->irq);
+
+ aic3262->irq_masks_cur |= irq_data->mask;
+}
+
+static void aic3262_irq_mask(struct irq_data *data)
+{
+ struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
+ struct aic3262_irq_data *irq_data =
+ irq_to_aic3262_irq(aic3262, data->irq);
+
+ aic3262->irq_masks_cur &= ~irq_data->mask;
+}
+
+static struct irq_chip aic3262_irq_chip = {
+ .name = "tlv320aic3262",
+ .irq_bus_lock = aic3262_irq_lock,
+ .irq_bus_sync_unlock = aic3262_irq_sync_unlock,
+ .irq_mask = aic3262_irq_mask,
+ .irq_unmask = aic3262_irq_unmask,
+};
+
+static irqreturn_t aic3262_irq_thread(int irq, void *data)
+{
+ struct aic3262 *aic3262 = data;
+ u8 status[4];
+ int i = 0;
+ /* Reading the sticky bit registers acknowledges
+ the interrupt to the device */
+ aic3262_bulk_read(aic3262, AIC3262_INT_STICKY_FLAG1, 4, status);
+
+ /* report */
+ if (status[2] & aic3262_irqs[AIC3262_IRQ_HEADSET_DETECT].status)
+ handle_nested_irq(aic3262->irq_base);
+
+ if (status[2] & aic3262_irqs[AIC3262_IRQ_BUTTON_PRESS].status)
+ handle_nested_irq(aic3262->irq_base + 1);
+ if (status[2] & aic3262_irqs[AIC3262_IRQ_DAC_DRC].status)
+ handle_nested_irq(aic3262->irq_base + 2);
+ if (status[3] & aic3262_irqs[AIC3262_IRQ_AGC_NOISE].status)
+ handle_nested_irq(aic3262->irq_base + 3);
+ if (status[2] & aic3262_irqs[AIC3262_IRQ_OVER_CURRENT].status)
+ handle_nested_irq(aic3262->irq_base + 4);
+ if (status[0] & aic3262_irqs[AIC3262_IRQ_OVERFLOW_EVENT].status)
+ handle_nested_irq(aic3262->irq_base + 5);
+ if (status[3] & aic3262_irqs[AIC3262_IRQ_SPEAKER_OVER_TEMP].status)
+ handle_nested_irq(aic3262->irq_base + 6);
+
+ /* ack unmasked irqs */
+ /* No need to acknowledge the interrupt on AIC3262 */
+
+ return IRQ_HANDLED;
+}
+
+int aic3262_irq_init(struct aic3262 *aic3262)
+{
+ int cur_irq, ret;
+
+ mutex_init(&aic3262->irq_lock);
+
+ /* mask the individual interrupt sources */
+ aic3262->irq_masks_cur = 0x0;
+ aic3262->irq_masks_cache = 0x0;
+ aic3262_reg_write(aic3262, AIC3262_INT1_CNTL, 0x0);
+
+ if (!aic3262->irq) {
+ dev_warn(aic3262->dev,
+ "no interrupt specified, no interrupts\n");
+ aic3262->irq_base = 0;
+ return 0;
+ }
+
+ if (!aic3262->irq_base) {
+ dev_err(aic3262->dev,
+ "no interrupt base specified, no interrupts\n");
+ return 0;
+ }
+
+ /* Register them with genirq */
+ for (cur_irq = aic3262->irq_base;
+ cur_irq < aic3262->irq_base + ARRAY_SIZE(aic3262_irqs);
+ cur_irq++) {
+ irq_set_chip_data(cur_irq, aic3262);
+ irq_set_chip_and_handler(cur_irq, &aic3262_irq_chip,
+ handle_edge_irq);
+ irq_set_nested_thread(cur_irq, 1);
+
+ /* ARM needs us to explicitly flag the IRQ as valid
+ * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+ set_irq_flags(cur_irq, IRQF_VALID);
+#else
+ set_irq_noprobe(cur_irq);
+#endif
+ }
+
+ ret = request_threaded_irq(aic3262->irq, NULL, aic3262_irq_thread,
+ IRQF_TRIGGER_RISING,
+ "tlv320aic3262", aic3262);
+ if (ret) {
+ dev_err(aic3262->dev, "failed to request IRQ %d: %d\n",
+ aic3262->irq, ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(aic3262_irq_init);
+
+void aic3262_irq_exit(struct aic3262 *aic3262)
+{
+ if (aic3262->irq)
+ free_irq(aic3262->irq, aic3262);
+}
+EXPORT_SYMBOL(aic3262_irq_exit);
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index 080f97aa264b..25f463de1513 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -1,37 +1,33 @@
/*
- * driver/mfd/tps65090.c
- *
* Core driver for TI TPS65090 PMIC family
*
- * Copyright (C) 2012 NVIDIA Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+
+ * This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-
#include <linux/mfd/core.h>
#include <linux/mfd/tps65090.h>
-#include <linux/regmap.h>
+#include <linux/err.h>
+
+#define NUM_INT_REG 2
+#define TOTAL_NUM_REG 0x18
/* interrupt status registers */
#define TPS65090_INT_STS 0x0
@@ -41,95 +37,41 @@
#define TPS65090_INT_MSK 0x2
#define TPS65090_INT_MSK2 0x3
-
-enum irq_type {
- EVENT,
-};
-
struct tps65090_irq_data {
u8 mask_reg;
u8 mask_pos;
- enum irq_type type;
};
-#define TPS65090_IRQ(_reg, _mask_pos, _type) \
+#define TPS65090_IRQ(_reg, _mask_pos) \
{ \
.mask_reg = (_reg), \
.mask_pos = (_mask_pos), \
- .type = (_type), \
}
static const struct tps65090_irq_data tps65090_irqs[] = {
- [0] = TPS65090_IRQ(0, 0, EVENT),
- [1] = TPS65090_IRQ(0, 1, EVENT),
- [2] = TPS65090_IRQ(0, 2, EVENT),
- [3] = TPS65090_IRQ(0, 3, EVENT),
- [4] = TPS65090_IRQ(0, 4, EVENT),
- [5] = TPS65090_IRQ(0, 5, EVENT),
- [6] = TPS65090_IRQ(0, 6, EVENT),
- [7] = TPS65090_IRQ(0, 7, EVENT),
- [8] = TPS65090_IRQ(1, 0, EVENT),
- [9] = TPS65090_IRQ(1, 1, EVENT),
- [10] = TPS65090_IRQ(1, 2, EVENT),
- [11] = TPS65090_IRQ(1, 3, EVENT),
- [12] = TPS65090_IRQ(1, 4, EVENT),
- [13] = TPS65090_IRQ(1, 5, EVENT),
- [14] = TPS65090_IRQ(1, 6, EVENT),
- [15] = TPS65090_IRQ(1, 7, EVENT),
+ [0] = TPS65090_IRQ(0, 0),
+ [1] = TPS65090_IRQ(0, 1),
+ [2] = TPS65090_IRQ(0, 2),
+ [3] = TPS65090_IRQ(0, 3),
+ [4] = TPS65090_IRQ(0, 4),
+ [5] = TPS65090_IRQ(0, 5),
+ [6] = TPS65090_IRQ(0, 6),
+ [7] = TPS65090_IRQ(0, 7),
+ [8] = TPS65090_IRQ(1, 0),
+ [9] = TPS65090_IRQ(1, 1),
+ [10] = TPS65090_IRQ(1, 2),
+ [11] = TPS65090_IRQ(1, 3),
+ [12] = TPS65090_IRQ(1, 4),
+ [13] = TPS65090_IRQ(1, 5),
+ [14] = TPS65090_IRQ(1, 6),
+ [15] = TPS65090_IRQ(1, 7),
};
-struct tps65090 {
- struct mutex lock;
- struct device *dev;
- struct i2c_client *client;
- struct regmap *rmap;
- struct irq_chip irq_chip;
- struct mutex irq_lock;
- int irq_base;
- u32 irq_en;
- u8 mask_cache[2];
- u8 mask_reg[2];
+static struct mfd_cell tps65090s[] = {
+ {
+ .name = "tps65910-pmic",
+ },
};
-int tps65090_write(struct device *dev, int reg, uint8_t val)
-{
- struct tps65090 *tps = dev_get_drvdata(dev);
- return regmap_write(tps->rmap, reg, val);
-}
-int tps65090_read(struct device *dev, int reg, uint8_t *val)
-{
- int rval, ret = 0;
- struct tps65090 *tps = dev_get_drvdata(dev);
- ret = regmap_read(tps->rmap, reg, &rval);
- *val = rval;
- return 0;
-}
-EXPORT_SYMBOL_GPL(tps65090_read);
-
-int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num)
-{
- struct tps65090 *tps = dev_get_drvdata(dev);
- return regmap_update_bits_lazy(tps->rmap, reg, BIT(bit_num), ~0u);
-
-}
-EXPORT_SYMBOL_GPL(tps65090_set_bits);
-
-int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num)
-{
- struct tps65090 *tps = dev_get_drvdata(dev);
- return regmap_update_bits_lazy(tps->rmap, reg, BIT(bit_num), 0u);
-}
-EXPORT_SYMBOL_GPL(tps65090_clr_bits);
-
-static int __remove_subdev(struct device *dev, void *unused)
-{
- platform_device_unregister(to_platform_device(dev));
- return 0;
-}
-
-static int tps65090_remove_subdevs(struct tps65090 *tps65090)
-{
- return device_for_each_child(tps65090->dev, NULL, __remove_subdev);
-}
static void tps65090_irq_lock(struct irq_data *data)
{
@@ -141,135 +83,97 @@ static void tps65090_irq_lock(struct irq_data *data)
static void tps65090_irq_mask(struct irq_data *irq_data)
{
struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
- unsigned int __irq = irq_data->irq - tps65090->irq_base;
+ unsigned int __irq = irq_data->hwirq;
const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
- if (data->type == EVENT)
- tps65090->mask_reg[data->mask_reg] |= (1 << data->mask_pos);
- else
- tps65090->mask_reg[data->mask_reg] |= (3 << data->mask_pos);
-
- tps65090->irq_en &= ~(1 << __irq);
+ tps65090_set_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg),
+ data->mask_pos);
}
static void tps65090_irq_unmask(struct irq_data *irq_data)
{
struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
-
unsigned int __irq = irq_data->irq - tps65090->irq_base;
const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
- if (data->type == EVENT) {
- tps65090->mask_reg[data->mask_reg] &= ~(1 << data->mask_pos);
- tps65090->irq_en |= (1 << __irq);
- }
+ tps65090_clr_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg),
+ data->mask_pos);
}
static void tps65090_irq_sync_unlock(struct irq_data *data)
{
struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(tps65090->mask_reg); i++) {
- if (tps65090->mask_reg[i] != tps65090->mask_cache[i]) {
- if (!WARN_ON(tps65090_write(tps65090->dev,
- TPS65090_INT_MSK + 2*i,
- tps65090->mask_reg[i])))
- tps65090->mask_cache[i] = tps65090->mask_reg[i];
- }
- }
mutex_unlock(&tps65090->irq_lock);
}
-static int tps65090_irq_set_type(struct irq_data *irq_data, unsigned int type)
-{
- struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
-
- unsigned int __irq = irq_data->irq - tps65090->irq_base;
- const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
-
- if (data->type != EVENT) /* add support for GPIO, if needed */
- return -EINVAL;
-
- return 0;
-}
-
static irqreturn_t tps65090_irq(int irq, void *data)
{
struct tps65090 *tps65090 = data;
int ret = 0;
- u8 tmp[3];
- u8 int_ack;
- u32 acks, mask = 0;
+ u8 status = 0, mask = 0;
+ unsigned long int acks = 0;
int i;
- for (i = 0; i < 3; i++) {
- ret = tps65090_read(tps65090->dev, TPS65090_INT_STS + 2*i,
- &tmp[i]);
+ for (i = 0; i < NUM_INT_REG; i++) {
+ ret = tps65090_read(tps65090->dev, TPS65090_INT_MSK + i, &mask);
if (ret < 0) {
dev_err(tps65090->dev,
- "failed to read interrupt status\n");
+ "failed to read mask reg [addr:%d]\n",
+ TPS65090_INT_MSK + i);
return IRQ_NONE;
}
- if (tmp[i]) {
- /* Ack only those interrupts which are enabled */
- int_ack = tmp[i] & (~(tps65090->mask_cache[i]));
+ ret = tps65090_read(tps65090->dev, TPS65090_INT_STS + i,
+ &status);
+ if (ret < 0) {
+ dev_err(tps65090->dev,
+ "failed to read status reg [addr:%d]\n",
+ TPS65090_INT_STS + i);
+ return IRQ_NONE;
+ }
+ if (status) {
+ /* Ack only those interrupts which are not masked */
+ status &= (~mask);
ret = tps65090_write(tps65090->dev,
- TPS65090_INT_STS + 2*i, int_ack);
+ TPS65090_INT_STS + i, status);
if (ret < 0) {
dev_err(tps65090->dev,
"failed to write interrupt status\n");
return IRQ_NONE;
}
+ acks |= (status << (i * 8));
}
}
- acks = (tmp[2] << 16) | (tmp[1] << 8) | tmp[0];
-
- for (i = 0; i < ARRAY_SIZE(tps65090_irqs); i++) {
- if (tps65090_irqs[i].type == EVENT)
- mask = (1 << (tps65090_irqs[i].mask_pos
- + tps65090_irqs[i].mask_reg*8));
- else
- return -EINVAL;
- if ((acks & mask) && (tps65090->irq_en & (1 << i)))
- handle_nested_irq(tps65090->irq_base + i);
- }
- return IRQ_HANDLED;
+ for_each_set_bit(i, &acks, ARRAY_SIZE(tps65090_irqs))
+ handle_nested_irq(tps65090->irq_base + i);
+ return acks ? IRQ_HANDLED : IRQ_NONE;
}
static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq,
- int irq_base)
+ int irq_base)
{
int i, ret;
if (!irq_base) {
- dev_warn(tps65090->dev, "No interrupt support on IRQ base\n");
+ dev_err(tps65090->dev, "IRQ base not set\n");
return -EINVAL;
}
mutex_init(&tps65090->irq_lock);
- tps65090->mask_reg[0] = 0xFF;
- tps65090->mask_reg[1] = 0xFF;
- for (i = 0; i < 2; i++) {
- tps65090->mask_cache[i] = tps65090->mask_reg[i];
- tps65090_write(tps65090->dev, TPS65090_INT_MSK + i,
- tps65090->mask_cache[i]);
- }
+ for (i = 0; i < NUM_INT_REG; i++)
+ tps65090_write(tps65090->dev, TPS65090_INT_MSK + i, 0xFF);
- for (i = 0; i < 2; i++)
+ for (i = 0; i < NUM_INT_REG; i++)
tps65090_write(tps65090->dev, TPS65090_INT_STS + i, 0xff);
tps65090->irq_base = irq_base;
-
tps65090->irq_chip.name = "tps65090";
tps65090->irq_chip.irq_mask = tps65090_irq_mask;
tps65090->irq_chip.irq_unmask = tps65090_irq_unmask;
tps65090->irq_chip.irq_bus_lock = tps65090_irq_lock;
tps65090->irq_chip.irq_bus_sync_unlock = tps65090_irq_sync_unlock;
- tps65090->irq_chip.irq_set_type = tps65090_irq_set_type;
for (i = 0; i < ARRAY_SIZE(tps65090_irqs); i++) {
int __irq = i + tps65090->irq_base;
@@ -292,90 +196,21 @@ static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq,
return ret;
}
-static int __devinit tps65090_add_subdevs(struct tps65090 *tps65090,
- struct tps65090_platform_data *pdata)
-{
- struct tps65090_subdev_info *subdev;
- struct platform_device *pdev;
- int i, ret = 0;
-
- for (i = 0; i < pdata->num_subdevs; i++) {
- subdev = &pdata->subdevs[i];
-
- pdev = platform_device_alloc(subdev->name, subdev->id);
-
- pdev->dev.parent = tps65090->dev;
- pdev->dev.platform_data = subdev->platform_data;
-
- ret = platform_device_add(pdev);
- if (ret)
- goto failed;
- }
- return 0;
-
-failed:
- tps65090_remove_subdevs(tps65090);
- return ret;
-}
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-static void print_regs(const char *header, struct seq_file *s,
- struct i2c_client *client, int start_offset,
- int end_offset)
+static bool is_volatile_reg(struct device *dev, unsigned int reg)
{
- int reg_val;
- int i;
- int ret;
- struct tps65090 *tps = s->private;
- seq_printf(s, "%s\n", header);
- for (i = start_offset; i <= end_offset; ++i) {
- ret = regmap_read(tps->rmap, i, &reg_val);
- if (ret >= 0)
- seq_printf(s, "Reg 0x%02x Value 0x%02x\n", i, reg_val);
- }
- seq_printf(s, "------------------\n");
-}
-
-static int dbg_tps_show(struct seq_file *s, void *unused)
-{
- struct tps65090 *tps = s->private;
- struct i2c_client *client = tps->client;
-
- seq_printf(s, "TPS65090 Registers\n");
- seq_printf(s, "------------------\n");
-
- print_regs("All Regs", s, client, 0x0, 24);
- return 0;
-}
-
-static int dbg_tps_open(struct inode *inode, struct file *file)
-{
- return single_open(file, dbg_tps_show, inode->i_private);
-}
-
-static const struct file_operations debug_fops = {
- .open = dbg_tps_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static void __init tps65090_debuginit(struct tps65090 *tps)
-{
- (void)debugfs_create_file("tps65090", S_IRUGO, NULL,
- tps, &debug_fops);
-}
-#else
-static void __init tps65090_debuginit(struct tps65090 *tpsi)
-{
- return;
+ if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS))
+ return true;
+ else
+ return false;
}
-#endif
static const struct regmap_config tps65090_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
+ .max_register = TOTAL_NUM_REG,
+ .num_reg_defaults_raw = TOTAL_NUM_REG,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = is_volatile_reg,
};
static int __devinit tps65090_i2c_probe(struct i2c_client *client,
@@ -387,50 +222,47 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client,
if (!pdata) {
dev_err(&client->dev, "tps65090 requires platform data\n");
- return -ENOTSUPP;
+ return -EINVAL;
}
- tps65090 = kzalloc(sizeof(struct tps65090), GFP_KERNEL);
- if (tps65090 == NULL)
+ tps65090 = devm_kzalloc(&client->dev, sizeof(*tps65090), GFP_KERNEL);
+ if (!tps65090) {
+ dev_err(&client->dev, "mem alloc for tps65090 failed\n");
return -ENOMEM;
+ }
- tps65090->client = client;
tps65090->dev = &client->dev;
i2c_set_clientdata(client, tps65090);
- mutex_init(&tps65090->lock);
+ tps65090->rmap = devm_regmap_init_i2c(client, &tps65090_regmap_config);
+ if (IS_ERR(tps65090->rmap)) {
+ ret = PTR_ERR(tps65090->rmap);
+ dev_err(&client->dev, "regmap_init failed with err: %d\n", ret);
+ return ret;
+ }
if (client->irq) {
- ret = tps65090_irq_init(tps65090, client->irq,
- pdata->irq_base);
+ ret = tps65090_irq_init(tps65090, client->irq, pdata->irq_base);
if (ret) {
- dev_err(&client->dev, "IRQ init failed: %d\n", ret);
- goto err_irq_init;
+ dev_err(&client->dev, "IRQ init failed with err: %d\n",
+ ret);
+ return ret;
}
}
- ret = tps65090_add_subdevs(tps65090, pdata);
+ ret = mfd_add_devices(tps65090->dev, -1, tps65090s,
+ ARRAY_SIZE(tps65090s), NULL, 0);
if (ret) {
- dev_err(&client->dev, "add devices failed: %d\n", ret);
- goto err_add_devs;
+ dev_err(&client->dev, "add mfd devices failed with err: %d\n",
+ ret);
+ goto err_irq_exit;
}
- tps65090->rmap = regmap_init_i2c(tps65090->client,
- &tps65090_regmap_config);
- if (IS_ERR(tps65090->rmap)) {
- dev_err(&client->dev, "regmap_init failed: %ld\n",
- PTR_ERR(tps65090->rmap));
- goto err_add_devs;
- };
- tps65090_debuginit(tps65090);
-
return 0;
-err_add_devs:
+err_irq_exit:
if (client->irq)
free_irq(client->irq, tps65090);
-err_irq_init:
- kfree(tps65090);
return ret;
}
@@ -438,29 +270,34 @@ static int __devexit tps65090_i2c_remove(struct i2c_client *client)
{
struct tps65090 *tps65090 = i2c_get_clientdata(client);
+ mfd_remove_devices(tps65090->dev);
if (client->irq)
free_irq(client->irq, tps65090);
- regmap_exit(tps65090->rmap);
- kfree(tps65090);
return 0;
}
-#ifdef CONFIG_PM
-static int tps65090_i2c_suspend(struct i2c_client *client, pm_message_t state)
+
+#ifdef CONFIG_PM_SLEEP
+static int tps65090_suspend(struct device *dev)
{
+ struct i2c_client *client = to_i2c_client(dev);
if (client->irq)
disable_irq(client->irq);
return 0;
}
-static int tps65090_i2c_resume(struct i2c_client *client)
+static int tps65090_resume(struct device *dev)
{
+ struct i2c_client *client = to_i2c_client(dev);
if (client->irq)
enable_irq(client->irq);
return 0;
}
#endif
+static const struct dev_pm_ops tps65090_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(tps65090_suspend, tps65090_resume)
+};
static const struct i2c_device_id tps65090_id_table[] = {
{ "tps65090", 0 },
@@ -472,13 +309,10 @@ static struct i2c_driver tps65090_driver = {
.driver = {
.name = "tps65090",
.owner = THIS_MODULE,
+ .pm = &tps65090_pm_ops,
},
.probe = tps65090_i2c_probe,
.remove = __devexit_p(tps65090_i2c_remove),
-#ifdef CONFIG_PM
- .suspend = tps65090_i2c_suspend,
- .resume = tps65090_i2c_resume,
-#endif
.id_table = tps65090_id_table,
};
@@ -495,4 +329,5 @@ static void __exit tps65090_exit(void)
module_exit(tps65090_exit);
MODULE_DESCRIPTION("TPS65090 core driver");
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c
index f0f2ce1f6840..002b7d022d70 100644
--- a/drivers/mfd/tps80031.c
+++ b/drivers/mfd/tps80031.c
@@ -30,6 +30,7 @@
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/pm.h>
+#include <linux/regmap.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps80031.h>
@@ -108,6 +109,43 @@
#define TPS80031_BBSPOR_CFG 0xE6
#define TPS80031_BBSPOR_CHG_EN 0x8
+/* Valid Address ranges */
+#define TPS80031_ID0_PMIC_SLAVE_SMPS_DVS 0x55 ... 0x5C
+
+#define TPS80031_ID1_RTC 0x00 ... 0x16
+#define TPS80031_ID1_MEMORY 0x17 ... 0x1E
+#define TPS80031_ID1_PMC_MASTER 0x1F ... 0x2D
+#define TPS80031_ID1_PMC_SLAVE_MISC 0x31 ... 0x34
+#define TPS80031_ID1_PMC_SLAVE_SMPS 0x40 ... 0x68
+#define TPS80031_ID1_PMC_SLAVE_LDO 0x80 ... 0xA7
+#define TPS80031_ID1_PMC_SLAVE_REOSURCES 0XAD ... 0xD0
+#define TPS80031_ID1_PMC_PREQ_ASSIGN 0XD7 ... 0xDF
+#define TPS80031_ID1_PMC_MISC 0xE2 ... 0xEF
+#define TPS80031_ID1_PMC_PU_PD_HZ 0xF0 ... 0xF6
+#define TPS80031_ID1_PMC_BACKUP 0xFA
+
+#define TPS80031_ID2_USB 0x00 ... 0x1A
+#define TPS80031_ID2_GPADC_CONTROL 0x2E ... 0x36
+#define TPS80031_ID2_GPADC_RESULTS 0x37 ... 0x3C
+#define TPS80031_ID2_AUXILLIARIES 0x90 ... 0x9C
+#define TPS80031_ID2_CUSTOM 0xA0 ... 0xB9
+#define TPS80031_ID2_PWM 0xBA ... 0xBE
+#define TPS80031_ID2_FUEL_GAUSE 0xC0 ... 0xCB
+#define TPS80031_ID2_INTERFACE_INTERRUPTS 0xD0 ... 0xD8
+#define TPS80031_ID2_CHARGER 0xDA ... 0xF5
+
+#define TPS80031_ID3_TEST_LDO 0x00 ... 0x09
+#define TPS80031_ID3_TEST_SMPS 0x10 ... 0x2B
+#define TPS80031_ID3_TEST_POWER 0x30 ... 0x36
+#define TPS80031_ID3_TEST_CHARGER 0x40 ... 0x48
+#define TPS80031_ID3_TEST_AUXILIIARIES 0x50 ... 0xB1
+
+#define TPS80031_ID3_DIEID 0xC0 ... 0xC8
+#define TPS80031_ID3_TRIM_PHOENIX 0xCC ... 0xEA
+#define TPS80031_ID3_TRIM_CUSTOM 0xEC ... 0xED
+
+#define TPS80031_MAX_REGISTER 0x100
+
struct tps80031_pupd_data {
u8 reg;
u8 pullup_bit;
@@ -256,159 +294,84 @@ struct tps80031 {
u8 cont_int_en;
u8 prev_cont_stat1;
struct tps80031_client tps_clients[TPS_NUM_SLAVES];
+ struct regmap *regmap[TPS_NUM_SLAVES];
};
-static inline int __tps80031_read(struct i2c_client *client,
- int reg, uint8_t *val)
-{
- int ret;
-
- ret = i2c_smbus_read_byte_data(client, reg);
- if (ret < 0) {
- dev_err(&client->dev,
- "failed reading from addr 0x%02x, reg 0x%02x\n",
- client->addr, reg);
- return ret;
- }
-
- *val = (uint8_t)ret;
-
- return 0;
-}
-
-static inline int __tps80031_reads(struct i2c_client *client, int reg,
- int len, uint8_t *val)
-{
- int ret;
-
- ret = i2c_smbus_read_i2c_block_data(client, reg, len, val);
- if (ret < 0) {
- dev_err(&client->dev,
- "failed reading from addr 0x%02x, reg 0x%02x\n",
- client->addr, reg);
- return ret;
- }
-
- return 0;
-}
-
-static inline int __tps80031_write(struct i2c_client *client,
- int reg, uint8_t val)
-{
- int ret;
- ret = i2c_smbus_write_byte_data(client, reg, val);
- if (ret < 0) {
- dev_err(&client->dev,
- "failed writing 0x%02x to 0x%02x\n", val, reg);
- return ret;
- }
-
- return 0;
-}
-
-static inline int __tps80031_writes(struct i2c_client *client, int reg,
- int len, uint8_t *val)
-{
- int ret;
-
- ret = i2c_smbus_write_i2c_block_data(client, reg, len, val);
- if (ret < 0) {
- dev_err(&client->dev, "failed writings to 0x%02x\n", reg);
- return ret;
- }
+/* TPS80031 sub mfd devices */
+static struct mfd_cell tps80031_cell[] = {
+ {
+ .name = "tps80031-regulators",
+ },
+ {
+ .name = "tps80031-rtc",
+ },
+ {
+ .name = "tps80031-gpadc",
+ },
+ {
+ .name = "tps80031-battery-gauge",
+ },
+ {
+ .name = "tps80031-charger",
+ },
+};
- return 0;
-}
int tps80031_write(struct device *dev, int sid, int reg, uint8_t val)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- int ret;
- mutex_lock(&tps->lock);
- ret = __tps80031_write(tps->client, reg, val);
- mutex_unlock(&tps->lock);
-
- return ret;
+ return regmap_write(tps80031->regmap[sid], reg, val);
}
EXPORT_SYMBOL_GPL(tps80031_write);
int tps80031_writes(struct device *dev, int sid, int reg, int len, uint8_t *val)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- int ret;
- mutex_lock(&tps->lock);
- ret = __tps80031_writes(tps->client, reg, len, val);
- mutex_unlock(&tps->lock);
-
- return ret;
+ return regmap_bulk_write(tps80031->regmap[sid], reg, val, len);
}
EXPORT_SYMBOL_GPL(tps80031_writes);
int tps80031_read(struct device *dev, int sid, int reg, uint8_t *val)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
+ unsigned int ival;
+ int ret;
- return __tps80031_read(tps->client, reg, val);
+ ret = regmap_read(tps80031->regmap[sid], reg, &ival);
+ if (ret < 0) {
+ dev_err(dev, "failed reading from reg 0x%02x\n", reg);
+ return ret;
+ }
+
+ *val = ival;
+ return ret;
}
EXPORT_SYMBOL_GPL(tps80031_read);
int tps80031_reads(struct device *dev, int sid, int reg, int len, uint8_t *val)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- return __tps80031_reads(tps->client, reg, len, val);
+ return regmap_bulk_read(tps80031->regmap[sid], reg, val, len);
}
EXPORT_SYMBOL_GPL(tps80031_reads);
int tps80031_set_bits(struct device *dev, int sid, int reg, uint8_t bit_mask)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- uint8_t reg_val;
- int ret = 0;
-
- mutex_lock(&tps->lock);
-
- ret = __tps80031_read(tps->client, reg, &reg_val);
- if (ret)
- goto out;
- if ((reg_val & bit_mask) != bit_mask) {
- reg_val |= bit_mask;
- ret = __tps80031_write(tps->client, reg, reg_val);
- }
-out:
- mutex_unlock(&tps->lock);
- return ret;
+ return regmap_update_bits(tps80031->regmap[sid], reg,
+ bit_mask, bit_mask);
}
EXPORT_SYMBOL_GPL(tps80031_set_bits);
int tps80031_clr_bits(struct device *dev, int sid, int reg, uint8_t bit_mask)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- uint8_t reg_val;
- int ret = 0;
-
- mutex_lock(&tps->lock);
- ret = __tps80031_read(tps->client, reg, &reg_val);
- if (ret)
- goto out;
-
- if (reg_val & bit_mask) {
- reg_val &= ~bit_mask;
- ret = __tps80031_write(tps->client, reg, reg_val);
- }
-out:
- mutex_unlock(&tps->lock);
- return ret;
+ return regmap_update_bits(tps80031->regmap[sid], reg, bit_mask, 0);
}
EXPORT_SYMBOL_GPL(tps80031_clr_bits);
@@ -416,23 +379,8 @@ int tps80031_update(struct device *dev, int sid, int reg, uint8_t val,
uint8_t mask)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- uint8_t reg_val;
- int ret = 0;
- mutex_lock(&tps->lock);
-
- ret = __tps80031_read(tps->client, reg, &reg_val);
- if (ret)
- goto out;
-
- if ((reg_val & mask) != val) {
- reg_val = (reg_val & ~mask) | (val & mask);
- ret = __tps80031_write(tps->client, reg, reg_val);
- }
-out:
- mutex_unlock(&tps->lock);
- return ret;
+ return regmap_update_bits(tps80031->regmap[sid], reg, mask, val);
}
EXPORT_SYMBOL_GPL(tps80031_update);
@@ -446,12 +394,12 @@ int tps80031_force_update(struct device *dev, int sid, int reg, uint8_t val,
mutex_lock(&tps->lock);
- ret = __tps80031_read(tps->client, reg, &reg_val);
+ ret = tps80031_read(dev, sid, reg, &reg_val);
if (ret)
goto out;
reg_val = (reg_val & ~mask) | (val & mask);
- ret = __tps80031_write(tps->client, reg, reg_val);
+ ret = tps80031_write(dev, sid, reg, reg_val);
out:
mutex_unlock(&tps->lock);
@@ -544,7 +492,8 @@ static void tps80031_power_off(void)
if (!tps->client)
return;
dev_info(&tps->client->dev, "switching off PMU\n");
- __tps80031_write(tps->client, TPS80031_PHOENIX_DEV_ON, DEVOFF);
+ tps80031_write(&tps->client->dev, SLAVE_ID1,
+ TPS80031_PHOENIX_DEV_ON, DEVOFF);
}
static void tps80031_pupd_init(struct tps80031 *tps80031,
@@ -589,7 +538,7 @@ static void tps80031_init_ext_control(struct tps80031 *tps80031,
/* Clear all external control for this rail */
for (i = 0; i < 9; ++i) {
- tps80031_write(tps80031->dev, SLAVE_ID1,
+ ret = tps80031_write(tps80031->dev, SLAVE_ID1,
TPS80031_PREQ1_RES_ASS_A + i, 0);
if (ret < 0)
dev_err(tps80031->dev, "%s() Error in clearing "
@@ -613,14 +562,14 @@ static int tps80031_gpio_get(struct gpio_chip *gc, unsigned offset)
uint8_t trans;
int ret;
- ret = __tps80031_read(tps->client,
+ ret = tps80031_read(&tps->client->dev, SLAVE_ID1,
pmc_ext_control_base[offset] +
EXT_CONTROL_CFG_STATE, &state);
if (ret)
return ret;
if (state != 0) {
- ret = __tps80031_read(tps->client,
+ ret = tps80031_read(&tps->client->dev, SLAVE_ID1,
pmc_ext_control_base[offset] +
EXT_CONTROL_CFG_TRANS, &trans);
if (ret)
@@ -742,17 +691,6 @@ static void tps80031_gpio_init(struct tps80031 *tps80031,
dev_warn(tps80031->dev, "GPIO registration failed: %d\n", ret);
}
-static int __remove_subdev(struct device *dev, void *unused)
-{
- platform_device_unregister(to_platform_device(dev));
- return 0;
-}
-
-static int tps80031_remove_subdevs(struct tps80031 *tps80031)
-{
- return device_for_each_child(tps80031->dev, NULL, __remove_subdev);
-}
-
static void tps80031_irq_lock(struct irq_data *data)
{
struct tps80031 *tps80031 = irq_data_get_irq_chip_data(data);
@@ -1075,32 +1013,6 @@ static void tps80031_clk32k_init(struct tps80031 *tps80031,
}
}
-static int __devinit tps80031_add_subdevs(struct tps80031 *tps80031,
- struct tps80031_platform_data *pdata)
-{
- struct tps80031_subdev_info *subdev;
- struct platform_device *pdev;
- int i, ret = 0;
-
- for (i = 0; i < pdata->num_subdevs; i++) {
- subdev = &pdata->subdevs[i];
-
- pdev = platform_device_alloc(subdev->name, subdev->id);
-
- pdev->dev.parent = tps80031->dev;
- pdev->dev.platform_data = subdev->platform_data;
-
- ret = platform_device_add(pdev);
- if (ret)
- goto failed;
- }
- return 0;
-
-failed:
- tps80031_remove_subdevs(tps80031);
- return ret;
-}
-
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>
@@ -1115,7 +1027,7 @@ static void print_regs(const char *header, struct seq_file *s,
seq_printf(s, "%s\n", header);
for (i = start_offset; i <= end_offset; ++i) {
- ret = __tps80031_read(tps->client, i, &reg_val);
+ ret = tps80031_read(&tps->client->dev, sid, i, &reg_val);
if (ret >= 0)
seq_printf(s, "Addr = 0x%02x Reg 0x%02x Value 0x%02x\n",
tps->client->addr, i, reg_val);
@@ -1189,11 +1101,116 @@ static void __init tps80031_debuginit(struct tps80031 *tpsi)
}
#endif
+static bool rd_wr_reg_id0(struct device *dev, unsigned int reg)
+{
+ switch(reg) {
+ case TPS80031_ID0_PMIC_SLAVE_SMPS_DVS:
+ return true;
+ default:
+ pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+ BUG();
+ return false;
+ }
+}
+
+static bool rd_wr_reg_id1(struct device *dev, unsigned int reg)
+{
+ switch(reg) {
+ case TPS80031_ID1_RTC:
+ case TPS80031_ID1_MEMORY:
+ case TPS80031_ID1_PMC_MASTER:
+ case TPS80031_ID1_PMC_SLAVE_SMPS:
+ case TPS80031_ID1_PMC_SLAVE_MISC:
+ case TPS80031_ID1_PMC_SLAVE_LDO:
+ case TPS80031_ID1_PMC_SLAVE_REOSURCES:
+ case TPS80031_ID1_PMC_PREQ_ASSIGN:
+ case TPS80031_ID1_PMC_MISC:
+ case TPS80031_ID1_PMC_PU_PD_HZ:
+ case TPS80031_ID1_PMC_BACKUP:
+ return true;
+ default:
+ pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+ BUG();
+ return false;
+ }
+}
+
+static bool rd_wr_reg_id2(struct device *dev, unsigned int reg)
+{
+ switch(reg) {
+ case TPS80031_ID2_USB:
+ case TPS80031_ID2_GPADC_CONTROL:
+ case TPS80031_ID2_GPADC_RESULTS:
+ case TPS80031_ID2_AUXILLIARIES:
+ case TPS80031_ID2_CUSTOM:
+ case TPS80031_ID2_PWM:
+ case TPS80031_ID2_FUEL_GAUSE:
+ case TPS80031_ID2_INTERFACE_INTERRUPTS:
+ case TPS80031_ID2_CHARGER:
+ return true;
+ default:
+ pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+ BUG();
+ return false;
+ }
+}
+static bool rd_wr_reg_id3(struct device *dev, unsigned int reg)
+{
+ switch(reg) {
+ case TPS80031_ID3_TEST_LDO:
+ case TPS80031_ID3_TEST_SMPS:
+ case TPS80031_ID3_TEST_POWER:
+ case TPS80031_ID3_TEST_CHARGER:
+ case TPS80031_ID3_TEST_AUXILIIARIES:
+ case TPS80031_ID3_DIEID:
+ case TPS80031_ID3_TRIM_PHOENIX:
+ case TPS80031_ID3_TRIM_CUSTOM:
+ return true;
+ default:
+ pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+ BUG();
+ return false;
+ }
+}
+
+static const struct regmap_config tps80031_regmap_configs[] = {
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = rd_wr_reg_id0,
+ .readable_reg = rd_wr_reg_id0,
+ .max_register = TPS80031_MAX_REGISTER - 1,
+ },
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = rd_wr_reg_id1,
+ .readable_reg = rd_wr_reg_id1,
+ .max_register = TPS80031_MAX_REGISTER - 1,
+ },
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = rd_wr_reg_id2,
+ .readable_reg = rd_wr_reg_id2,
+ .max_register = TPS80031_MAX_REGISTER - 1,
+ },
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = rd_wr_reg_id3,
+ .readable_reg = rd_wr_reg_id3,
+ .max_register = TPS80031_MAX_REGISTER - 1,
+ },
+};
+
static int __devexit tps80031_i2c_remove(struct i2c_client *client)
{
struct tps80031 *tps80031 = i2c_get_clientdata(client);
int i;
+ mfd_remove_devices(tps80031->dev);
+
if (client->irq)
free_irq(client->irq, tps80031);
@@ -1209,7 +1226,6 @@ static int __devexit tps80031_i2c_remove(struct i2c_client *client)
mutex_destroy(&tps->lock);
}
- kfree(tps80031);
return 0;
}
@@ -1246,9 +1262,11 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
dev_info(&client->dev, "Jtag version 0x%02x and Eeprom version 0x%02x\n",
jtag_ver, ep_ver);
- tps80031 = kzalloc(sizeof(struct tps80031), GFP_KERNEL);
- if (tps80031 == NULL)
+ tps80031 = devm_kzalloc(&client->dev, sizeof(*tps80031), GFP_KERNEL);
+ if (!tps80031) {
+ dev_err(&client->dev, "Memory alloc for tps80031 failed\n");
return -ENOMEM;
+ }
tps80031->es_version = jtag_ver;
tps80031->dev = &client->dev;
@@ -1270,10 +1288,19 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
if (!tps->client) {
dev_err(&client->dev, "can't attach client %d\n", i);
ret = -ENOMEM;
- goto fail;
+ goto fail_client_reg;
}
i2c_set_clientdata(tps->client, tps80031);
mutex_init(&tps->lock);
+
+ tps80031->regmap[i] = devm_regmap_init_i2c(tps->client,
+ &tps80031_regmap_configs[i]);
+ if (IS_ERR(tps80031->regmap[i])) {
+ ret = PTR_ERR(tps80031->regmap[i]);
+ dev_err(&client->dev,
+ "regmap %d init failed, err %d\n", i, ret);
+ goto fail_client_reg;
+ }
}
if (client->irq) {
@@ -1281,7 +1308,7 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
pdata->irq_base);
if (ret) {
dev_err(&client->dev, "IRQ init failed: %d\n", ret);
- goto fail;
+ goto fail_client_reg;
}
}
@@ -1289,10 +1316,11 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
tps80031_init_ext_control(tps80031, pdata);
- ret = tps80031_add_subdevs(tps80031, pdata);
- if (ret) {
- dev_err(&client->dev, "add devices failed: %d\n", ret);
- goto fail;
+ ret = mfd_add_devices(tps80031->dev, -1,
+ tps80031_cell, ARRAY_SIZE(tps80031_cell), NULL, 0);
+ if (ret < 0) {
+ dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret);
+ goto fail_mfd_add;
}
tps80031_gpio_init(tps80031, pdata);
@@ -1310,14 +1338,24 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
return 0;
-fail:
- tps80031_i2c_remove(client);
+fail_mfd_add:
+ if (client->irq)
+ free_irq(client->irq, tps80031);
+fail_client_reg:
+ for (i = 0; i < TPS_NUM_SLAVES; i++) {
+ struct tps80031_client *tps = &tps80031->tps_clients[i];
+ if (tps->client && tps->client != client)
+ i2c_unregister_device(tps->client);
+ tps80031->tps_clients[i].client = NULL;
+ mutex_destroy(&tps->lock);
+ }
return ret;
}
#ifdef CONFIG_PM
-static int tps80031_i2c_suspend(struct i2c_client *client, pm_message_t state)
+static int tps80031_i2c_suspend(struct device *dev)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct tps80031 *tps80031 = i2c_get_clientdata(client);
if (client->irq)
disable_irq(client->irq);
@@ -1325,14 +1363,22 @@ static int tps80031_i2c_suspend(struct i2c_client *client, pm_message_t state)
return 0;
}
-static int tps80031_i2c_resume(struct i2c_client *client)
+static int tps80031_i2c_resume(struct device *dev)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct tps80031 *tps80031 = i2c_get_clientdata(client);
tps80031_backup_battery_charger_control(tps80031, 1);
if (client->irq)
enable_irq(client->irq);
return 0;
}
+static const struct dev_pm_ops tps80031_dev_pm_ops = {
+ .suspend = tps80031_i2c_suspend,
+ .resume = tps80031_i2c_resume,
+};
+#define TPS80031_DEV_PM (&tps80031_dev_pm_ops)
+#else
+#define TPS80031_DEV_PM NULL
#endif
@@ -1346,13 +1392,10 @@ static struct i2c_driver tps80031_driver = {
.driver = {
.name = "tps80031",
.owner = THIS_MODULE,
+ .pm = TPS80031_DEV_PM,
},
.probe = tps80031_i2c_probe,
.remove = __devexit_p(tps80031_i2c_remove),
-#ifdef CONFIG_PM
- .suspend = tps80031_i2c_suspend,
- .resume = tps80031_i2c_resume,
-#endif
.id_table = tps80031_id_table,
};
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index dcf345e23487..0d6210e50e43 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -568,6 +568,13 @@ config THERM_EST
---help---
Thermal driver which estimates temperature based of other sensors.
+config TEGRA_THROUGHPUT
+ bool "Device node to set throughput target"
+ depends on TEGRA_DC && TEGRA_DC_EXTENSIONS
+ default y
+ ---help---
+ Dev node /dev/tegra-throughput used to set a throughput target.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index d9172c99bf6d..0912d6d2ea53 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -55,8 +55,10 @@ obj-$(CONFIG_SENSORS_AK8975) += akm8975.o
obj-$(CONFIG_SENSORS_NCT1008) += nct1008.o
obj-$(CONFIG_BCM4329_RFKILL) += bcm4329_rfkill.o
obj-$(CONFIG_INV_SENSORS) += inv_mpu/
+CFLAGS_tegra-cryptodev.o = -Werror
obj-$(CONFIG_TEGRA_CRYPTO_DEV) += tegra-cryptodev.o
obj-$(CONFIG_TEGRA_BB_SUPPORT) += tegra-baseband/
obj-$(CONFIG_TEGRA_CEC_SUPPORT) += tegra-cec/
obj-$(CONFIG_MAX1749_VIBRATOR) += max1749.o
obj-$(CONFIG_THERM_EST) += therm_est.o
+obj-$(CONFIG_TEGRA_THROUGHPUT) += tegra-throughput.o
diff --git a/drivers/misc/bcm4329_rfkill.c b/drivers/misc/bcm4329_rfkill.c
index 9dc33fd51e59..a2d5ca6699cc 100644
--- a/drivers/misc/bcm4329_rfkill.c
+++ b/drivers/misc/bcm4329_rfkill.c
@@ -107,7 +107,6 @@ static int bcm4329_rfkill_probe(struct platform_device *pdev)
"bcm4329_nreset_gpio");
if (res) {
bcm4329_rfkill->gpio_reset = res->start;
- tegra_gpio_enable(bcm4329_rfkill->gpio_reset);
ret = gpio_request(bcm4329_rfkill->gpio_reset,
"bcm4329_nreset_gpio");
} else {
@@ -121,7 +120,6 @@ static int bcm4329_rfkill_probe(struct platform_device *pdev)
"bcm4329_nshutdown_gpio");
if (res) {
bcm4329_rfkill->gpio_shutdown = res->start;
- tegra_gpio_enable(bcm4329_rfkill->gpio_shutdown);
ret = gpio_request(bcm4329_rfkill->gpio_shutdown,
"bcm4329_nshutdown_gpio");
} else {
diff --git a/drivers/misc/inv_mpu/mpu6050/mldl_cfg.c b/drivers/misc/inv_mpu/mpu6050/mldl_cfg.c
index 22af0c200985..920f4ae8a4b7 100644
--- a/drivers/misc/inv_mpu/mpu6050/mldl_cfg.c
+++ b/drivers/misc/inv_mpu/mpu6050/mldl_cfg.c
@@ -1786,6 +1786,16 @@ int inv_mpu_suspend(struct mldl_cfg *mldl_cfg,
return result;
}
}
+ /* Disable irq when suspend all sensors */
+ if (sensors == INV_ALL_SENSORS) {
+ result = inv_serial_single_write(
+ gyro_handle, mldl_cfg->mpu_chip_info->addr,
+ MPUREG_INT_ENABLE, 0);
+ if (result) {
+ LOG_RESULT_LOCATION(result);
+ return result;
+ }
+ }
mldl_cfg->inv_mpu_cfg->requested_sensors = (~sensors) & INV_ALL_SENSORS;
return result;
diff --git a/drivers/misc/tegra-baseband/bb-m7400.c b/drivers/misc/tegra-baseband/bb-m7400.c
index adabefdb100d..edde7d1786ed 100644
--- a/drivers/misc/tegra-baseband/bb-m7400.c
+++ b/drivers/misc/tegra-baseband/bb-m7400.c
@@ -241,7 +241,7 @@ static int m7400_attrib_write(struct device *dev, int value)
} else {
/* Unregister ehci controller */
if (ehci_device != NULL)
- pdata->ehci_unregister(ehci_device);
+ pdata->ehci_unregister(&ehci_device);
/* Signal AP going down */
m7400_apdown_handshake();
diff --git a/drivers/misc/tegra-baseband/bb-power.c b/drivers/misc/tegra-baseband/bb-power.c
index 9210a8f3e84a..c070fd45160e 100644
--- a/drivers/misc/tegra-baseband/bb-power.c
+++ b/drivers/misc/tegra-baseband/bb-power.c
@@ -71,9 +71,6 @@ static int tegra_bb_power_gpio_init(struct tegra_bb_power_gdata *gdata)
else
gpio_direction_output(gpio_id, (!gpio_flags ? 0 : 1));
- /* Enable the gpio */
- tegra_gpio_enable(gpio_id);
-
/* Create a sysfs node, if requested */
if (gpiolist->doexport)
gpio_export(gpio_id, false);
diff --git a/drivers/misc/tegra-cec/Makefile b/drivers/misc/tegra-cec/Makefile
index ab380305c35f..8bac2a519046 100644
--- a/drivers/misc/tegra-cec/Makefile
+++ b/drivers/misc/tegra-cec/Makefile
@@ -2,4 +2,6 @@
# Makefile for tegra cec support.
#
+subdir-ccflags-y = -Werror
+
obj-$(CONFIG_TEGRA_CEC_T30) += tegra_cec.o
diff --git a/drivers/misc/tegra-throughput.c b/drivers/misc/tegra-throughput.c
new file mode 100644
index 000000000000..d491ef8c06cf
--- /dev/null
+++ b/drivers/misc/tegra-throughput.c
@@ -0,0 +1,242 @@
+/*
+ * drivers/misc/throughput.c
+ *
+ * Copyright (C) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/kthread.h>
+#include <linux/ktime.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/throughput_ioctl.h>
+#include <linux/nvhost.h>
+#include <mach/dc.h>
+
+#define DEFAULT_SYNC_RATE 60000 /* 60 Hz */
+
+static unsigned short target_frame_time;
+static unsigned short last_frame_time;
+static ktime_t last_flip;
+static unsigned int multiple_app_disable;
+static spinlock_t lock;
+
+static struct work_struct work;
+static int throughput_hint;
+
+static void set_throughput_hint(struct work_struct *work)
+{
+ /* notify throughput hint clients here */
+ nvhost_scale3d_set_throughput_hint(throughput_hint);
+}
+
+static int throughput_flip_callback(void)
+{
+ long timediff;
+ ktime_t now;
+
+ /* only register flips when a single app is active */
+ if (multiple_app_disable)
+ return NOTIFY_DONE;
+
+ now = ktime_get();
+ if (last_flip.tv64 != 0) {
+ timediff = (long) ktime_us_delta(now, last_flip);
+ if (timediff > (long) USHRT_MAX)
+ last_frame_time = USHRT_MAX;
+ else
+ last_frame_time = (unsigned short) timediff;
+
+ if (last_frame_time == 0) {
+ pr_warn("%s: flips %lld nsec apart\n",
+ __func__, now.tv64 - last_flip.tv64);
+ return NOTIFY_DONE;
+ }
+
+ throughput_hint =
+ ((int) target_frame_time * 1000) / last_frame_time;
+
+ if (!work_pending(&work))
+ schedule_work(&work);
+ }
+ last_flip = now;
+
+ return NOTIFY_OK;
+}
+
+static int sync_rate;
+static int throughput_active_app_count;
+
+static void reset_target_frame_time(void)
+{
+ if (sync_rate == 0) {
+ sync_rate = tegra_dc_get_panel_sync_rate();
+
+ if (sync_rate == 0)
+ sync_rate = DEFAULT_SYNC_RATE;
+ }
+
+ target_frame_time = (unsigned short) (1000000000 / sync_rate);
+
+ pr_debug("%s: panel sync rate %d, target frame time %u\n",
+ __func__, sync_rate, target_frame_time);
+}
+
+static int callback_initialized;
+
+static int throughput_open(struct inode *inode, struct file *file)
+{
+ spin_lock(&lock);
+
+ if (!callback_initialized) {
+ callback_initialized = 1;
+ tegra_dc_set_flip_callback(throughput_flip_callback);
+ }
+
+ throughput_active_app_count++;
+ if (throughput_active_app_count > 1)
+ multiple_app_disable = 1;
+
+ spin_unlock(&lock);
+
+
+ pr_debug("throughput_open node %p file %p\n", inode, file);
+
+ return 0;
+}
+
+static int throughput_release(struct inode *inode, struct file *file)
+{
+ spin_lock(&lock);
+
+ throughput_active_app_count--;
+ if (throughput_active_app_count == 0) {
+ reset_target_frame_time();
+ multiple_app_disable = 0;
+ callback_initialized = 0;
+ tegra_dc_unset_flip_callback();
+ }
+
+ spin_unlock(&lock);
+
+ pr_debug("throughput_release node %p file %p\n", inode, file);
+
+ return 0;
+}
+
+static int throughput_set_target_fps(unsigned long arg)
+{
+ int disable;
+
+ pr_debug("%s: target fps %lu requested\n", __func__, arg);
+
+ disable = multiple_app_disable;
+
+ if (disable) {
+ pr_debug("%s: %d active apps, disabling fps usage\n",
+ __func__, throughput_active_app_count);
+ return 0;
+ }
+
+ if (arg == 0)
+ reset_target_frame_time();
+ else {
+ unsigned long frame_time = (1000000 / arg);
+
+ if (frame_time > USHRT_MAX)
+ frame_time = USHRT_MAX;
+
+ target_frame_time = (unsigned short) frame_time;
+ }
+
+ return 0;
+}
+
+static long
+throughput_ioctl(struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ int err = 0;
+
+ if ((_IOC_TYPE(cmd) != TEGRA_THROUGHPUT_MAGIC) ||
+ (_IOC_NR(cmd) == 0) ||
+ (_IOC_NR(cmd) > TEGRA_THROUGHPUT_IOCTL_MAXNR))
+ return -EFAULT;
+
+ switch (cmd) {
+ case TEGRA_THROUGHPUT_IOCTL_TARGET_FPS:
+ pr_debug("%s: TEGRA_THROUGHPUT_IOCTL_TARGET_FPS %lu\n",
+ __func__, arg);
+ err = throughput_set_target_fps(arg);
+ break;
+
+ default:
+ err = -ENOTTY;
+ }
+
+ return err;
+}
+
+static const struct file_operations throughput_user_fops = {
+ .owner = THIS_MODULE,
+ .open = throughput_open,
+ .release = throughput_release,
+ .unlocked_ioctl = throughput_ioctl,
+};
+
+#define TEGRA_THROUGHPUT_MINOR 1
+
+static struct miscdevice throughput_miscdev = {
+ .minor = TEGRA_THROUGHPUT_MINOR,
+ .name = "tegra-throughput",
+ .fops = &throughput_user_fops,
+ .mode = 0666,
+};
+
+int __init throughput_init_miscdev(void)
+{
+ int ret;
+
+ pr_debug("%s: initializing\n", __func__);
+
+ spin_lock_init(&lock);
+ INIT_WORK(&work, set_throughput_hint);
+
+ ret = misc_register(&throughput_miscdev);
+ if (ret) {
+ pr_err("can\'t reigster throughput miscdev"
+ " (minor %d err %d)\n", TEGRA_THROUGHPUT_MINOR, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+module_init(throughput_init_miscdev);
+
+void __exit throughput_exit_miscdev(void)
+{
+ pr_debug("%s: exiting\n", __func__);
+
+ cancel_work_sync(&work);
+
+ misc_deregister(&throughput_miscdev);
+}
+
+module_exit(throughput_exit_miscdev);
+
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 35f3df8810e0..f7528db8fd06 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2109,6 +2109,26 @@ void mmc_stop_host(struct mmc_host *host)
mmc_power_off(host);
}
+int mmc_speed_class_control(struct mmc_host *host,
+ unsigned int speed_class_ctrl_arg)
+{
+ int err = -ENOSYS;
+ u32 status;
+
+ err = mmc_send_speed_class_ctrl(host, speed_class_ctrl_arg);
+ if (err)
+ return err;
+
+ /* Issue CMD13 to check for any errors during the busy period of CMD20 */
+ err = mmc_send_status(host->card, &status);
+ if (!err) {
+ if (status & R1_ERROR)
+ err = -EINVAL;
+ }
+ return err;
+}
+EXPORT_SYMBOL(mmc_speed_class_control);
+
int mmc_power_save_host(struct mmc_host *host)
{
int ret = 0;
@@ -2163,6 +2183,9 @@ int mmc_card_awake(struct mmc_host *host)
{
int err = -ENOSYS;
+ if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
+ return 0;
+
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead && host->bus_ops->awake)
@@ -2178,6 +2201,9 @@ int mmc_card_sleep(struct mmc_host *host)
{
int err = -ENOSYS;
+ if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
+ return 0;
+
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead && host->bus_ops->awake)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 40c93b3dccd7..0e8001facac3 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -976,13 +976,19 @@ static void mmc_detect(struct mmc_host *host)
*/
static int mmc_suspend(struct mmc_host *host)
{
+ int err;
+
BUG_ON(!host);
BUG_ON(!host->card);
mmc_claim_host(host);
- if (!mmc_host_is_spi(host))
+ if (mmc_card_can_sleep(host)) {
+ err = mmc_card_sleep(host);
+ if (!err)
+ mmc_card_set_sleep(host->card);
+ } else if (!mmc_host_is_spi(host))
mmc_deselect_cards(host);
- host->card->state &= ~MMC_STATE_HIGHSPEED;
+ host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
mmc_release_host(host);
return 0;
@@ -1002,7 +1008,11 @@ static int mmc_resume(struct mmc_host *host)
BUG_ON(!host->card);
mmc_claim_host(host);
- err = mmc_init_card(host, host->ocr, host->card);
+ if (mmc_card_is_sleep(host->card)) {
+ err = mmc_card_awake(host);
+ mmc_card_clr_sleep(host->card);
+ } else
+ err = mmc_init_card(host, host->ocr, host->card);
mmc_release_host(host);
return err;
@@ -1012,7 +1022,8 @@ static int mmc_power_restore(struct mmc_host *host)
{
int ret;
- host->card->state &= ~MMC_STATE_HIGHSPEED;
+ host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
+ mmc_card_clr_sleep(host->card);
mmc_claim_host(host);
ret = mmc_init_card(host, host->ocr, host->card);
mmc_release_host(host);
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index 021fed153804..b06781e69ce3 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -389,3 +389,29 @@ int mmc_app_sd_status(struct mmc_card *card, void *ssr)
return 0;
}
+
+int mmc_send_speed_class_ctrl(struct mmc_host *host,
+ unsigned int speed_class_ctrl_arg)
+{
+ int err = 0;
+ struct mmc_command cmd = {
+ .opcode = SD_SPEED_CLASS_CONTROL,
+ .arg = (speed_class_ctrl_arg << 28),
+ .flags = MMC_RSP_R1B | MMC_CMD_AC | MMC_RSP_BUSY,
+ };
+
+ BUG_ON(!host);
+ BUG_ON(speed_class_ctrl_arg > 3);
+ err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+ if (err)
+ return err;
+
+ /*
+ * If the host does not wait while the card signals busy, then we will
+ * will have to wait the max busy indication timeout.
+ */
+ if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
+ mmc_delay(1000);
+ return err;
+}
+
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
index ffc2305d905f..a77b8facceb4 100644
--- a/drivers/mmc/core/sd_ops.h
+++ b/drivers/mmc/core/sd_ops.h
@@ -20,6 +20,7 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr);
int mmc_sd_switch(struct mmc_card *card, int mode, int group,
u8 value, u8 *resp);
int mmc_app_sd_status(struct mmc_card *card, void *ssr);
-
+int mmc_send_speed_class_ctrl(struct mmc_host *host,
+ unsigned int speed_class_ctrl_arg);
#endif
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index f5ea51bd0ed3..2f9d6f4f43e1 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o
+CFLAGS_sdhci-tegra.o = -Werror
obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o
obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o
obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 609fd6391d1f..8ff35e4cbfe4 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -74,7 +74,9 @@ static unsigned int tegra_sdhost_std_freq;
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
static void tegra_3x_sdhci_set_card_clock(struct sdhci_host *sdhci, unsigned int clock);
static void tegra3_sdhci_post_reset_init(struct sdhci_host *sdhci);
+#endif
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
static unsigned int tegra3_sdhost_max_clk[4] = {
208000000, 104000000, 208000000, 104000000 };
#endif
@@ -227,7 +229,7 @@ static void tegra3_sdhci_post_reset_init(struct sdhci_host *sdhci)
SDHCI_VENDOR_MISC_CNTRL_ENABLE_SDR50_SUPPORT;
sdhci_writew(sdhci, misc_ctrl, SDHCI_VENDOR_MISC_CNTRL);
}
-#endif
+#endif /* #ifdef CONFIG_ARCH_TEGRA_3x_SOC */
static int tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
unsigned int uhs)
@@ -372,14 +374,7 @@ static void tegra_sdhci_set_clk_rate(struct sdhci_host *sdhci,
unsigned int clk_rate;
unsigned int emc_clk;
- /*
- * In SDR50 mode, run the sdmmc controller at freq greater than
- * 104MHz to ensure the core voltage is at 1.2V. If the core voltage
- * is below 1.2V, CRC errors would occur during data transfers.
- */
- if (sdhci->mmc->card &&
- (mmc_card_ddr_mode(sdhci->mmc->card) ||
- (sdhci->mmc->ios.timing == MMC_TIMING_UHS_SDR50))) {
+ if (sdhci->mmc->ios.timing == MMC_TIMING_UHS_DDR50) {
/*
* In ddr mode, tegra sdmmc controller clock frequency
* should be double the card clock frequency.
@@ -394,6 +389,13 @@ static void tegra_sdhci_set_clk_rate(struct sdhci_host *sdhci,
} else {
clk_rate = clock * 2;
}
+ } else if (sdhci->mmc->ios.timing == MMC_TIMING_UHS_SDR50) {
+ /*
+ * In SDR50 mode, run the sdmmc controller at freq greater than
+ * 104MHz to ensure the core voltage is at 1.2V. If the core voltage
+ * is below 1.2V, CRC errors would occur during data transfers.
+ */
+ clk_rate = clock * 2;
} else {
if (clock <= tegra_sdhost_min_freq)
clk_rate = tegra_sdhost_min_freq;
@@ -410,7 +412,6 @@ static void tegra_sdhci_set_clk_rate(struct sdhci_host *sdhci,
clk_set_rate(pltfm_host->clk, clk_rate);
sdhci->max_clk = clk_get_rate(pltfm_host->clk);
}
-
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
static void tegra_3x_sdhci_set_card_clock(struct sdhci_host *sdhci, unsigned int clock)
{
@@ -496,7 +497,7 @@ set_clk:
out:
sdhci->clock = clock;
}
-#endif
+#endif /* #ifdef CONFIG_ARCH_TEGRA_3x_SOC */
static void tegra_sdhci_set_clock(struct sdhci_host *sdhci, unsigned int clock)
{
@@ -509,7 +510,12 @@ static void tegra_sdhci_set_clock(struct sdhci_host *sdhci, unsigned int clock)
if (clock) {
/* bring out sd instance from io dpd mode */
- tegra_io_dpd_disable(tegra_host->dpd);
+ if (tegra_host->dpd) {
+ mutex_lock(&tegra_host->dpd->delay_lock);
+ cancel_delayed_work_sync(&tegra_host->dpd->delay_dpd);
+ tegra_io_dpd_disable(tegra_host->dpd);
+ mutex_unlock(&tegra_host->dpd->delay_lock);
+ }
if (!tegra_host->clk_enabled) {
clk_enable(pltfm_host->clk);
@@ -530,7 +536,18 @@ static void tegra_sdhci_set_clock(struct sdhci_host *sdhci, unsigned int clock)
clk_disable(pltfm_host->clk);
tegra_host->clk_enabled = false;
/* io dpd enable call for sd instance */
- tegra_io_dpd_enable(tegra_host->dpd);
+
+ if (tegra_host->dpd) {
+ mutex_lock(&tegra_host->dpd->delay_lock);
+ if (tegra_host->dpd->need_delay_dpd) {
+ schedule_delayed_work(
+ &tegra_host->dpd->delay_dpd,
+ msecs_to_jiffies(100));
+ } else {
+ tegra_io_dpd_enable(tegra_host->dpd);
+ }
+ mutex_unlock(&tegra_host->dpd->delay_lock);
+ }
}
}
@@ -658,36 +675,15 @@ static void sdhci_tegra_set_tap_delay(struct sdhci_host *sdhci,
sdhci_writel(sdhci, vendor_ctrl, SDHCI_VENDOR_CLOCK_CNTRL);
}
-static void sdhci_tegra_clear_set_irqs(struct sdhci_host *host,
- u32 clear, u32 set)
-{
- u32 ier;
-
- ier = sdhci_readl(host, SDHCI_INT_ENABLE);
- ier &= ~clear;
- ier |= set;
- sdhci_writel(host, ier, SDHCI_INT_ENABLE);
- sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
-}
-
static int sdhci_tegra_run_frequency_tuning(struct sdhci_host *sdhci)
{
int err = 0;
u8 ctrl;
- u32 ier;
u32 mask;
unsigned int timeout = 10;
int flags;
u32 intstatus;
- /*
- * As per the Host Controller spec v3.00, tuning command
- * generates Buffer Read Ready interrupt only, so enable that.
- */
- ier = sdhci_readl(sdhci, SDHCI_INT_ENABLE);
- sdhci_tegra_clear_set_irqs(sdhci, ier, SDHCI_INT_DATA_AVAIL |
- SDHCI_INT_DATA_CRC);
-
mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;
while (sdhci_readl(sdhci, SDHCI_PRESENT_STATE) & mask) {
if (timeout == 0) {
@@ -759,7 +755,6 @@ static int sdhci_tegra_run_frequency_tuning(struct sdhci_host *sdhci)
}
mdelay(1);
out:
- sdhci_tegra_clear_set_irqs(sdhci, SDHCI_INT_DATA_AVAIL, ier);
return err;
}
@@ -773,6 +768,7 @@ static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci)
unsigned int temp_pass_window = 0;
unsigned int best_low_pass_tap = 0;
unsigned int best_pass_window = 0;
+ u32 ier;
/* Tuning is valid only in SDR104 and SDR50 modes */
ctrl_2 = sdhci_readw(sdhci, SDHCI_HOST_CONTROL2);
@@ -785,11 +781,20 @@ static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci)
if (tap_delay_status == NULL) {
dev_err(mmc_dev(sdhci->mmc), "failed to allocate memory"
"for storing tap_delay_status\n");
- err = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
/*
+ * Disable all interrupts signalling.Enable interrupt status
+ * detection for buffer read ready and data crc. We use
+ * polling for tuning as it involves less overhead.
+ */
+ ier = sdhci_readl(sdhci, SDHCI_INT_ENABLE);
+ sdhci_writel(sdhci, 0, SDHCI_SIGNAL_ENABLE);
+ sdhci_writel(sdhci, SDHCI_INT_DATA_AVAIL |
+ SDHCI_INT_DATA_CRC, SDHCI_INT_ENABLE);
+
+ /*
* Set each tap delay value and run frequency tuning. After each
* run, update the tap delay status as working or not working.
*/
@@ -840,7 +845,10 @@ static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci)
/* Run frequency tuning */
err = sdhci_tegra_run_frequency_tuning(sdhci);
-out:
+ /* Enable the normal interrupts signalling */
+ sdhci_writel(sdhci, ier, SDHCI_INT_ENABLE);
+ sdhci_writel(sdhci, ier, SDHCI_SIGNAL_ENABLE);
+
if (tap_delay_status)
kfree(tap_delay_status);
@@ -865,6 +873,12 @@ static int tegra_sdhci_suspend(struct sdhci_host *sdhci, pm_message_t state)
}
}
+ if (tegra_host->dpd) {
+ mutex_lock(&tegra_host->dpd->delay_lock);
+ tegra_host->dpd->need_delay_dpd = 1;
+ mutex_unlock(&tegra_host->dpd->delay_lock);
+ }
+
return 0;
}
@@ -905,9 +919,6 @@ static struct sdhci_ops tegra_sdhci_ops = {
.read_w = tegra_sdhci_readw,
.write_l = tegra_sdhci_writel,
.platform_8bit_width = tegra_sdhci_8bit,
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
- .set_card_clock = tegra_3x_sdhci_set_card_clock,
-#endif
.set_clock = tegra_sdhci_set_clock,
.suspend = tegra_sdhci_suspend,
.resume = tegra_sdhci_resume,
@@ -981,7 +992,6 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
"failed to allocate power gpio\n");
goto err_power_req;
}
- tegra_gpio_enable(plat->power_gpio);
gpio_direction_output(plat->power_gpio, 1);
}
@@ -992,7 +1002,6 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
"failed to allocate cd gpio\n");
goto err_cd_req;
}
- tegra_gpio_enable(plat->cd_gpio);
gpio_direction_input(plat->cd_gpio);
tegra_host->card_present = (gpio_get_value(plat->cd_gpio) == 0);
@@ -1027,7 +1036,6 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
"failed to allocate wp gpio\n");
goto err_wp_req;
}
- tegra_gpio_enable(plat->wp_gpio);
gpio_direction_input(plat->wp_gpio);
}
@@ -1133,12 +1141,6 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
host->mmc->caps |= MMC_CAP_BKOPS;
#endif
-#ifdef CONFIG_MMC_EMBEDDED_SDIO
- /* Do not turn OFF embedded sdio cards as it support Wake on Wireless */
- if (plat->mmc_data.embedded_sdio)
- host->mmc->pm_flags |= MMC_PM_KEEP_POWER;
-#endif
-
tegra_sdhost_min_freq = TEGRA_SDHOST_MIN_FREQ;
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
tegra_host->hw_ops = &tegra_2x_sdhci_ops;
@@ -1160,23 +1162,17 @@ err_add_host:
err_clk_put:
clk_put(pltfm_host->clk);
err_clk_get:
- if (gpio_is_valid(plat->wp_gpio)) {
- tegra_gpio_disable(plat->wp_gpio);
+ if (gpio_is_valid(plat->wp_gpio))
gpio_free(plat->wp_gpio);
- }
err_wp_req:
if (gpio_is_valid(plat->cd_gpio))
free_irq(gpio_to_irq(plat->cd_gpio), host);
err_cd_irq_req:
- if (gpio_is_valid(plat->cd_gpio)) {
- tegra_gpio_disable(plat->cd_gpio);
+ if (gpio_is_valid(plat->cd_gpio))
gpio_free(plat->cd_gpio);
- }
err_cd_req:
- if (gpio_is_valid(plat->power_gpio)) {
- tegra_gpio_disable(plat->power_gpio);
+ if (gpio_is_valid(plat->power_gpio))
gpio_free(plat->power_gpio);
- }
err_power_req:
err_no_mem:
kfree(tegra_host);
@@ -1209,21 +1205,16 @@ static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
regulator_put(tegra_host->vdd_io_reg);
}
- if (gpio_is_valid(plat->wp_gpio)) {
- tegra_gpio_disable(plat->wp_gpio);
+ if (gpio_is_valid(plat->wp_gpio))
gpio_free(plat->wp_gpio);
- }
if (gpio_is_valid(plat->cd_gpio)) {
free_irq(gpio_to_irq(plat->cd_gpio), host);
- tegra_gpio_disable(plat->cd_gpio);
gpio_free(plat->cd_gpio);
}
- if (gpio_is_valid(plat->power_gpio)) {
- tegra_gpio_disable(plat->power_gpio);
+ if (gpio_is_valid(plat->power_gpio))
gpio_free(plat->power_gpio);
- }
if (tegra_host->clk_enabled)
clk_disable(pltfm_host->clk);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index d3e9a4a4169f..aa03ca7d5226 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1852,19 +1852,15 @@ static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
int sdhci_enable(struct mmc_host *mmc)
{
struct sdhci_host *host = mmc_priv(mmc);
+ u16 clk;
- if (!mmc->card)
+ if (!mmc->card || mmc->card->type == MMC_TYPE_SDIO)
return 0;
if (mmc->ios.clock) {
- if (mmc->card->type != MMC_TYPE_SDIO) {
- if (host->ops->set_clock)
- host->ops->set_clock(host, mmc->ios.clock);
- sdhci_set_clock(host, mmc->ios.clock);
- } else {
- if (host->ops->set_card_clock)
- host->ops->set_card_clock(host, mmc->ios.clock);
- }
+ if (host->ops->set_clock)
+ host->ops->set_clock(host, mmc->ios.clock);
+ sdhci_set_clock(host, mmc->ios.clock);
}
return 0;
@@ -1873,19 +1869,14 @@ int sdhci_enable(struct mmc_host *mmc)
int sdhci_disable(struct mmc_host *mmc, int lazy)
{
struct sdhci_host *host = mmc_priv(mmc);
+ u16 clk;
- if (!mmc->card)
+ if (!mmc->card || mmc->card->type == MMC_TYPE_SDIO)
return 0;
- /* For SDIO cards, only disable the card clock. */
- if (mmc->card->type != MMC_TYPE_SDIO) {
- sdhci_set_clock(host, 0);
- if (host->ops->set_clock)
- host->ops->set_clock(host, 0);
- } else {
- if (host->ops->set_card_clock)
- host->ops->set_card_clock(host, 0);
- }
+ sdhci_set_clock(host, 0);
+ if (host->ops->set_clock)
+ host->ops->set_clock(host, 0);
return 0;
}
@@ -2348,6 +2339,15 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
}
if (mmc->card) {
+ /*
+ * If eMMC cards are put in sleep state, Vccq can be disabled
+ * but Vcc would still be powered on. In resume, we only restore
+ * the controller context. So, set MMC_PM_KEEP_POWER flag.
+ */
+ if (mmc_card_can_sleep(mmc) &&
+ !(mmc->caps & MMC_CAP2_NO_SLEEP_CMD))
+ mmc->pm_flags = MMC_PM_KEEP_POWER;
+
ret = mmc_suspend_host(host->mmc);
if (ret) {
if (has_tuning_timer) {
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index bf48767e0ef2..c00833de19da 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -260,7 +260,6 @@ struct sdhci_ops {
#endif
void (*set_clock)(struct sdhci_host *host, unsigned int clock);
- void (*set_card_clock)(struct sdhci_host *host, unsigned int clock);
int (*enable_dma)(struct sdhci_host *host);
unsigned int (*get_max_clock)(struct sdhci_host *host);
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 67345a00a5ab..b9337a4f0c06 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -18,4 +18,5 @@ obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
obj-$(CONFIG_MTD_M25P80) += m25p80.o
obj-$(CONFIG_MTD_SST25L) += sst25l.o
+CFLAGS_tegra_nand.o = -Werror
obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o
diff --git a/drivers/mtd/devices/tegra_nand.c b/drivers/mtd/devices/tegra_nand.c
index 92cd70f2fd46..6034f0b2f239 100644
--- a/drivers/mtd/devices/tegra_nand.c
+++ b/drivers/mtd/devices/tegra_nand.c
@@ -1654,7 +1654,6 @@ static int __devinit tegra_nand_probe(struct platform_device *pdev)
if (plat->wp_gpio) {
gpio_request(plat->wp_gpio, "nand_wp");
- tegra_gpio_enable(plat->wp_gpio);
gpio_direction_output(plat->wp_gpio, 1);
}
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index bb5eef14a367..dbc68e0e87cb 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -60,4 +60,5 @@ obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o
obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o
obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o
obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o
+CFLAGS_tegra_nor.o = -Werror
obj-$(CONFIG_MTD_NOR_TEGRA) += tegra_nor.o
diff --git a/drivers/mtd/maps/tegra_nor.c b/drivers/mtd/maps/tegra_nor.c
index 505a2591f884..41adb1e40382 100644
--- a/drivers/mtd/maps/tegra_nor.c
+++ b/drivers/mtd/maps/tegra_nor.c
@@ -1,9 +1,5 @@
/*
- * drivers/mtd/maps/tegra_nor.c
- *
- * MTD mapping driver for the internal SNOR controller in Tegra SoCs
- *
- * Copyright (C) 2009 - 2012 NVIDIA Corporation
+ * Copyright (C) 2009-2012, NVIDIA Corporation. All rights reserved.
*
* Author:
* Raghavendra VK <rvk@nvidia.com>
@@ -21,6 +17,11 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * drivers/mtd/maps/tegra_nor.c
+ *
+ * MTD mapping driver for the internal SNOR controller in Tegra SoCs
+ *
*/
#include <linux/platform_device.h>
@@ -139,7 +140,7 @@ static inline void snor_tegra_writel(struct tegra_nor_info *tnor,
#define DRV_NAME "tegra-nor"
-static const char * const part_probes[] = { "cmdlinepart", NULL };
+static const char *part_probes[] = { "cmdlinepart", NULL };
static int wait_for_dma_completion(struct tegra_nor_info *info)
{
@@ -160,6 +161,7 @@ static void tegra_flash_dma(struct map_info *map,
u32 copy_to = (u32)to;
struct tegra_nor_info *c =
container_of(map, struct tegra_nor_info, map);
+ struct tegra_nor_chip_parms *chip_parm = &c->plat->chip_parms;
unsigned int bytes_remaining = len;
snor_config = c->init_config;
@@ -174,9 +176,52 @@ static void tegra_flash_dma(struct map_info *map,
* controller register only after all parameters are set.
*/
/* SNOR CONFIGURATION SETUP */
- snor_config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(1);
- /* 8 word page */
- snor_config |= TEGRA_SNOR_CONFIG_PAGE_SZ(2);
+ switch(chip_parm->ReadMode)
+ {
+ case NorReadMode_Async:
+ snor_config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(0);
+ break;
+
+ case NorReadMode_Page:
+ switch(chip_parm->PageLength)
+ {
+ case NorPageLength_Unsupported :
+ snor_config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(0);
+ break;
+
+ case NorPageLength_4Word :
+ snor_config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(1);
+ snor_config |= TEGRA_SNOR_CONFIG_PAGE_SZ(1);
+ break;
+
+ case NorPageLength_8Word :
+ snor_config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(1);
+ snor_config |= TEGRA_SNOR_CONFIG_PAGE_SZ(2);
+ break;
+ }
+ break;
+
+ case NorReadMode_Burst:
+ snor_config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(2);
+ switch(chip_parm->BurstLength)
+ {
+ case NorBurstLength_CntBurst :
+ snor_config |= TEGRA_SNOR_CONFIG_BURST_LEN(0);
+ break;
+ case NorBurstLength_8Word :
+ snor_config |= TEGRA_SNOR_CONFIG_BURST_LEN(1);
+ break;
+
+ case NorBurstLength_16Word :
+ snor_config |= TEGRA_SNOR_CONFIG_BURST_LEN(2);
+ break;
+
+ case NorBurstLength_32Word :
+ snor_config |= TEGRA_SNOR_CONFIG_BURST_LEN(3);
+ break;
+ }
+ break;
+ }
snor_config |= TEGRA_SNOR_CONFIG_MST_ENB;
/* SNOR DMA CONFIGURATION SETUP */
/* NOR -> AHB */
@@ -273,8 +318,28 @@ static int tegra_snor_controller_init(struct tegra_nor_info *info)
default:
return -EINVAL;
}
- config |= TEGRA_SNOR_CONFIG_BURST_LEN(0);
- config &= ~TEGRA_SNOR_CONFIG_MUX_MODE;
+ switch (chip_parm->MuxMode)
+ {
+ case NorMuxMode_ADNonMux:
+ config &= ~TEGRA_SNOR_CONFIG_MUX_MODE;
+ break;
+ case NorMuxMode_ADMux:
+ config |= TEGRA_SNOR_CONFIG_MUX_MODE;
+ break;
+ default:
+ return -EINVAL;
+ }
+ switch (chip_parm->ReadyActive)
+ {
+ case NorReadyActive_WithData:
+ config &= ~TEGRA_SNOR_CONFIG_RDY_ACTIVE;
+ break;
+ case NorReadyActive_BeforeData:
+ config |= TEGRA_SNOR_CONFIG_RDY_ACTIVE;
+ break;
+ default:
+ return -EINVAL;
+ }
snor_tegra_writel(info, config, TEGRA_SNOR_CONFIG_REG);
info->init_config = config;
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index f30752565b33..5f85fe79c595 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -15,5 +15,6 @@ obj-$(CONFIG_CAIF_SHM) += caif_shm.o
obj-$(CONFIG_CAIF_HSI) += caif_hsi.o
# Tegra specific SPI slave physical interfaces module
+CFLAGS_tegra_caif_sspi.o = -Werror
tegra_cfspi_slave-objs := tegra_caif_sspi.o
obj-$(CONFIG_TEGRA_SPI_CAIF) += tegra_cfspi_slave.o
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index c31b1185f492..14bda2ecabde 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -604,6 +604,14 @@ static const struct usb_device_id products [] = {
USB_DEVICE(0x0489,0xE03A),
.driver_info = (unsigned long)&rmnet_info,
},
+
+/* ZM5250 */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ USB_DEVICE(0x19D2,0x1554),
+ .driver_info = (unsigned long)&rmnet_info,
+},
/*
* WHITELIST!!!
*
diff --git a/drivers/net/usb/raw_ip_net.c b/drivers/net/usb/raw_ip_net.c
index 1b3b89b3c274..dc9b5e61fd9e 100644
--- a/drivers/net/usb/raw_ip_net.c
+++ b/drivers/net/usb/raw_ip_net.c
@@ -3,7 +3,7 @@
*
* USB network driver for RAW-IP modems.
*
- * Copyright (c) 2011, NVIDIA Corporation.
+ * Copyright (c) 2011-2012, NVIDIA Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -42,25 +42,24 @@
#endif /* USB_NET_BUFSIZ */
/* maximum interface number supported */
-#define MAX_INTFS 3
+#define MAX_INTFS 5
MODULE_LICENSE("GPL");
-int g_i;
+static int g_i;
-int max_intfs = MAX_INTFS;
-unsigned long usb_net_raw_ip_vid = 0x1519;
-unsigned long usb_net_raw_ip_pid = 0x0020;
-unsigned long usb_net_raw_ip_intf[MAX_INTFS] = { 0x03, 0x05, 0x07 };
+/* To support more rmnet interfaces, increase the default max_intfs or
+ * pass kernel module parameter.
+ * e.g. insmod raw_ip_net.ko max_intfs=5
+ */
+static int max_intfs = 2; /* default number of interfaces */
+
+static unsigned long usb_net_raw_ip_intf[MAX_INTFS] = { 3, 5, 9, 11, 13};
unsigned long usb_net_raw_ip_rx_debug;
unsigned long usb_net_raw_ip_tx_debug;
module_param(max_intfs, int, 0644);
MODULE_PARM_DESC(max_intfs, "usb net (raw-ip) - max. interfaces supported");
-module_param(usb_net_raw_ip_vid, ulong, 0644);
-MODULE_PARM_DESC(usb_net_raw_ip_vid, "usb net (raw-ip) - USB VID");
-module_param(usb_net_raw_ip_pid, ulong, 0644);
-MODULE_PARM_DESC(usb_net_raw_ip_pid, "usb net (raw-ip) - USB PID");
module_param(usb_net_raw_ip_rx_debug, ulong, 0644);
MODULE_PARM_DESC(usb_net_raw_ip_rx_debug, "usb net (raw-ip) - rx debug");
module_param(usb_net_raw_ip_tx_debug, ulong, 0644);
@@ -99,11 +98,10 @@ struct baseband_usb {
int susp_count;
};
-static struct baseband_usb *baseband_usb_net[MAX_INTFS] = { 0, 0, 0};
+static struct baseband_usb *baseband_usb_net[MAX_INTFS] = { 0, 0, 0, 0, 0};
-static struct net_device *usb_net_raw_ip_dev[MAX_INTFS] = { 0, 0, 0};
+static struct net_device *usb_net_raw_ip_dev[MAX_INTFS] = { 0, 0, 0, 0, 0};
-static unsigned int g_usb_interface_index[MAX_INTFS];
static struct usb_interface *g_usb_interface[MAX_INTFS];
static int usb_net_raw_ip_rx_urb_submit(struct baseband_usb *usb);
@@ -117,7 +115,7 @@ static void usb_net_raw_ip_tx_urb_comp(struct urb *urb);
static int baseband_usb_driver_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- int i = g_i;
+ int i = g_i, j;
pr_debug("%s(%d) { intf %p id %p\n", __func__, __LINE__, intf, id);
@@ -138,16 +136,18 @@ static int baseband_usb_driver_probe(struct usb_interface *intf,
pr_debug("intf->cur_altsetting->desc.iInterface %02x\n",
intf->cur_altsetting->desc.iInterface);
- if (g_usb_interface_index[i] !=
- intf->cur_altsetting->desc.bInterfaceNumber) {
- pr_debug("%s(%d) } -ENODEV\n", __func__, __LINE__);
- return -ENODEV;
- } else {
- g_usb_interface[i] = intf;
+ /* register interfaces that are assigned to raw-ip */
+ for (j = 0; j < max_intfs; j++) {
+ if (usb_net_raw_ip_intf[j] ==
+ intf->cur_altsetting->desc.bInterfaceNumber) {
+ pr_info("%s: raw_ip using interface %d\n", __func__,
+ intf->cur_altsetting->desc.bInterfaceNumber);
+ g_usb_interface[j] = intf;
+ return 0;
+ }
}
-
pr_debug("%s(%d) }\n", __func__, __LINE__);
- return 0;
+ return -ENODEV;
}
static void baseband_usb_driver_disconnect(struct usb_interface *intf)
@@ -350,49 +350,27 @@ static int baseband_usb_driver_reset_resume(struct usb_interface *intf)
}
#endif /* CONFIG_PM */
-static struct usb_device_id baseband_usb_driver_id_table[MAX_INTFS][2];
-
-static char baseband_usb_driver_name[MAX_INTFS][32];
+static struct usb_device_id baseband_usb_driver_id_table[] = {
+ /* xmm modem vid, pid */
+ { USB_DEVICE(0x1519, 0x0020), },
+ { },
+};
-static struct usb_driver baseband_usb_driver[MAX_INTFS] = {
- {
- .name = baseband_usb_driver_name[0],
- .probe = baseband_usb_driver_probe,
- .disconnect = baseband_usb_driver_disconnect,
- .id_table = baseband_usb_driver_id_table[0],
-#ifdef CONFIG_PM
- .suspend = baseband_usb_driver_suspend,
- .resume = baseband_usb_driver_resume,
- .reset_resume = baseband_usb_driver_reset_resume,
- .supports_autosuspend = 1,
-#endif
- },
- {
- .name = baseband_usb_driver_name[1],
+static struct usb_driver baseband_usb_driver = {
+ .name = "bb_raw_ip_net",
.probe = baseband_usb_driver_probe,
.disconnect = baseband_usb_driver_disconnect,
- .id_table = baseband_usb_driver_id_table[1],
+ .id_table = baseband_usb_driver_id_table,
#ifdef CONFIG_PM
.suspend = baseband_usb_driver_suspend,
.resume = baseband_usb_driver_resume,
.reset_resume = baseband_usb_driver_reset_resume,
.supports_autosuspend = 1,
#endif
- },
- {
- .name = baseband_usb_driver_name[2],
- .probe = baseband_usb_driver_probe,
- .disconnect = baseband_usb_driver_disconnect,
- .id_table = baseband_usb_driver_id_table[2],
-#ifdef CONFIG_PM
- .suspend = baseband_usb_driver_suspend,
- .resume = baseband_usb_driver_resume,
- .reset_resume = baseband_usb_driver_reset_resume,
- .supports_autosuspend = 1,
-#endif
- },
};
+MODULE_DEVICE_TABLE(usb, baseband_usb_driver_id_table);
+
static void find_usb_pipe(struct baseband_usb *usb)
{
struct usb_device *usbdev = usb->usb.device;
@@ -434,13 +412,10 @@ static void find_usb_pipe(struct baseband_usb *usb)
void baseband_usb_close(struct baseband_usb *usb);
-struct baseband_usb *baseband_usb_open(int index,
- unsigned int vid,
- unsigned int pid,
- unsigned int intf)
+struct baseband_usb *baseband_usb_open(int index, unsigned int intf)
{
struct baseband_usb *usb;
- int err;
+ int i;
pr_debug("baseband_usb_open {\n");
@@ -453,37 +428,25 @@ struct baseband_usb *baseband_usb_open(int index,
/* create semaphores */
sema_init(&usb->sem, 1);
- /* open usb driver */
- sprintf(baseband_usb_driver_name[index],
- "baseband_usb_%x_%x_%x",
- vid, pid, intf);
- baseband_usb_driver_id_table[index][0].match_flags =
- USB_DEVICE_ID_MATCH_DEVICE;
- baseband_usb_driver_id_table[index][0].idVendor = vid;
- baseband_usb_driver_id_table[index][0].idProduct = pid;
- g_usb_interface_index[index] = intf;
- g_usb_interface[index] = (struct usb_interface *) 0;
- err = usb_register(&baseband_usb_driver[index]);
- if (err < 0) {
- pr_err("cannot open usb driver - err %d\n", err);
- kfree(usb);
- return (struct baseband_usb *) 0;
- }
+ /* open usb interface */
usb->baseband_index = index;
- usb->usb.driver = &baseband_usb_driver[index];
+ usb->usb.driver = &baseband_usb_driver;
if (!g_usb_interface[index]) {
- pr_err("cannot open usb driver - !g_usb_interface[%d]\n",
- index);
- usb_deregister(usb->usb.driver);
- kfree(usb);
- return (struct baseband_usb *) 0;
+ /* wait for usb probe */
+ for (i = 0; i < 50; i++)
+ if (!g_usb_interface[index])
+ msleep(20);
+ if (!g_usb_interface[index]) {
+ pr_err("can't open usb: !g_usb_interface[%d]\n", index);
+ kfree(usb);
+ return NULL;
+ }
}
usb->usb.device = interface_to_usbdev(g_usb_interface[index]);
usb->usb.interface = g_usb_interface[index];
find_usb_pipe(usb);
usb->usb.rx_urb = (struct urb *) 0;
usb->usb.tx_urb = (struct urb *) 0;
- g_usb_interface_index[index] = ~0U;
g_usb_interface[index] = (struct usb_interface *) 0;
pr_debug("usb->usb.driver->name %s\n", usb->usb.driver->name);
pr_debug("usb->usb.device %p\n", usb->usb.device);
@@ -509,12 +472,7 @@ void baseband_usb_close(struct baseband_usb *usb)
return;
/* close usb driver */
- if (usb->usb.driver) {
- pr_debug("close usb driver {\n");
- usb_deregister(usb->usb.driver);
- usb->usb.driver = (struct usb_driver *) 0;
- pr_debug("close usb driver }\n");
- }
+ usb->usb.driver = (struct usb_driver *) 0;
/* destroy semaphores */
memset(&usb->sem, 0, sizeof(usb->sem));
@@ -746,10 +704,28 @@ static void usb_net_raw_ip_rx_urb_comp(struct urb *urb)
skb_reserve(skb, NET_IP_ALIGN);
dst = skb_put(skb, 14);
memcpy(dst, ethernet_header, 14);
+ if ((((unsigned char *) urb->transfer_buffer)[0]
+ & 0xf0) == 0x60) {
+ /* ipv6 ether type */
+ dst[12] = 0x86;
+ dst[13] = 0xdd;
+ }
dst = skb_put(skb, urb->actual_length);
memcpy(dst, urb->transfer_buffer, urb->actual_length);
skb->protocol = eth_type_trans(skb,
usb_net_raw_ip_dev[i]);
+ pr_debug("%s: ntohs(skb->protocol) %04x (%s)\n",
+ __func__, ntohs(skb->protocol),
+ (ntohs(skb->protocol) == 0x0800)
+ ? "IPv4"
+ : (ntohs(skb->protocol) == 0x86dd)
+ ? "IPv6"
+ : "unknown");
+ pr_debug("%s: %02x %02x %02x %02x\n", __func__,
+ ((unsigned char *)urb->transfer_buffer)[0],
+ ((unsigned char *)urb->transfer_buffer)[1],
+ ((unsigned char *)urb->transfer_buffer)[2],
+ ((unsigned char *)urb->transfer_buffer)[3]);
/* pass skb to network stack */
if (netif_rx(skb) < 0) {
pr_err("usb_net_raw_ip_rx_urb_comp_work - "
@@ -892,6 +868,18 @@ static int usb_net_raw_ip_tx_urb_submit(struct baseband_usb *usb,
usb_net_raw_ip_tx_urb_comp,
usb);
urb->transfer_flags = URB_ZERO_PACKET;
+ pr_debug("%s: ntohs(skb->protocol) %04x (%s)\n",
+ __func__, ntohs(skb->protocol),
+ (ntohs(skb->protocol) == 0x0800)
+ ? "IPv4"
+ : (ntohs(skb->protocol) == 0x86dd)
+ ? "IPv6"
+ : "unknown");
+ pr_debug("%s: %02x %02x %02x %02x\n", __func__,
+ ((unsigned char *)urb->transfer_buffer)[0],
+ ((unsigned char *)urb->transfer_buffer)[1],
+ ((unsigned char *)urb->transfer_buffer)[2],
+ ((unsigned char *)urb->transfer_buffer)[3]);
/* queue tx urb work */
usb_anchor_urb(urb, &usb->usb.tx_urb_deferred);
@@ -923,8 +911,8 @@ static void usb_net_raw_ip_tx_urb_work(struct work_struct *work)
/* check if usb interface disconnected */
if (!usb->usb.interface) {
- pr_err("%s: not submitting tx urb %p -interface disconnected\n",
- __func__, urb);
+ pr_err("%s: not submitting tx urb -interface disconnected\n",
+ __func__);
return;
}
@@ -1044,12 +1032,18 @@ static int usb_net_raw_ip_init(void)
pr_debug("usb_net_raw_ip_init {\n");
+ err = usb_register(&baseband_usb_driver);
+ if (err < 0) {
+ pr_err("cannot open usb driver - err %d\n", err);
+ return err;
+ }
+
/* create multiple raw-ip network devices */
for (i = 0; i < max_intfs; i++) {
/* open baseband usb */
g_i = i;
- baseband_usb_net[i] = baseband_usb_open(i, usb_net_raw_ip_vid,
- usb_net_raw_ip_pid, usb_net_raw_ip_intf[i]);
+ baseband_usb_net[i] = baseband_usb_open(i,
+ usb_net_raw_ip_intf[i]);
if (!baseband_usb_net[i]) {
pr_err("cannot open baseband usb net\n");
err = -1;
@@ -1138,6 +1132,7 @@ error_exit:
baseband_usb_net[i] = (struct baseband_usb *) 0;
}
}
+ usb_deregister(&baseband_usb_driver);
return err;
}
@@ -1183,6 +1178,10 @@ static void usb_net_raw_ip_exit(void)
}
}
+ pr_debug("close usb driver {\n");
+ usb_deregister(&baseband_usb_driver);
+ pr_debug("close usb driver }\n");
+
pr_debug("usb_net_raw_ip_exit }\n");
}
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 82965e20e076..930a4c1959d2 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -210,6 +210,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
} else {
usb_fill_int_urb(dev->interrupt, dev->udev, pipe,
buf, maxp, intr_complete, dev, period);
+ dev->interrupt->transfer_flags |= URB_FREE_BUFFER;
dev_dbg(&intf->dev,
"status ep%din, %d bytes period %d\n",
usb_pipeendpoint(pipe), maxp, period);
@@ -277,17 +278,32 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu)
}
EXPORT_SYMBOL_GPL(usbnet_change_mtu);
+/* The caller must hold list->lock */
+static void __usbnet_queue_skb(struct sk_buff_head *list,
+ struct sk_buff *newsk, enum skb_state state)
+{
+ struct skb_data *entry = (struct skb_data *) newsk->cb;
+
+ __skb_queue_tail(list, newsk);
+ entry->state = state;
+}
+
/*-------------------------------------------------------------------------*/
/* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from
* completion callbacks. 2.5 should have fixed those bugs...
*/
-static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list)
+static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
+ struct sk_buff_head *list, enum skb_state state)
{
unsigned long flags;
+ enum skb_state old_state;
+ struct skb_data *entry = (struct skb_data *) skb->cb;
spin_lock_irqsave(&list->lock, flags);
+ old_state = entry->state;
+ entry->state = state;
__skb_unlink(skb, list);
spin_unlock(&list->lock);
spin_lock(&dev->done.lock);
@@ -295,6 +311,7 @@ static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_hea
if (dev->done.qlen == 1)
tasklet_schedule(&dev->bh);
spin_unlock_irqrestore(&dev->done.lock, flags);
+ return old_state;
}
/* some work can't be done in tasklets, so we use keventd
@@ -324,18 +341,17 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
unsigned long lockflags;
size_t size = dev->rx_urb_size;
- if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) {
+ skb = __netdev_alloc_skb_ip_align(dev->net, size, flags);
+ if (!skb) {
netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
usb_free_urb (urb);
return -ENOMEM;
}
- skb_reserve (skb, NET_IP_ALIGN);
entry = (struct skb_data *) skb->cb;
entry->urb = urb;
entry->dev = dev;
- entry->state = rx_start;
entry->length = 0;
usb_fill_bulk_urb (urb, dev->udev, dev->in,
@@ -367,7 +383,7 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
tasklet_schedule (&dev->bh);
break;
case 0:
- __skb_queue_tail (&dev->rxq, skb);
+ __usbnet_queue_skb(&dev->rxq, skb, rx_start);
}
} else {
netif_dbg(dev, ifdown, dev->net, "rx: stopped\n");
@@ -418,16 +434,17 @@ static void rx_complete (struct urb *urb)
struct skb_data *entry = (struct skb_data *) skb->cb;
struct usbnet *dev = entry->dev;
int urb_status = urb->status;
+ enum skb_state state;
skb_put (skb, urb->actual_length);
- entry->state = rx_done;
+ state = rx_done;
entry->urb = NULL;
switch (urb_status) {
/* success */
case 0:
if (skb->len < dev->net->hard_header_len) {
- entry->state = rx_cleanup;
+ state = rx_cleanup;
dev->net->stats.rx_errors++;
dev->net->stats.rx_length_errors++;
netif_dbg(dev, rx_err, dev->net,
@@ -466,7 +483,7 @@ static void rx_complete (struct urb *urb)
"rx throttle %d\n", urb_status);
}
block:
- entry->state = rx_cleanup;
+ state = rx_cleanup;
entry->urb = urb;
urb = NULL;
break;
@@ -477,18 +494,20 @@ block:
// FALLTHROUGH
default:
- entry->state = rx_cleanup;
+ state = rx_cleanup;
dev->net->stats.rx_errors++;
netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status);
break;
}
- defer_bh(dev, skb, &dev->rxq);
+ state = defer_bh(dev, skb, &dev->rxq, state);
if (urb) {
if (netif_running (dev->net) &&
- !test_bit (EVENT_RX_HALT, &dev->flags)) {
+ !test_bit (EVENT_RX_HALT, &dev->flags) &&
+ state != unlink_start) {
rx_submit (dev, urb, GFP_ATOMIC);
+ usb_mark_last_busy(dev->udev);
return;
}
usb_free_urb (urb);
@@ -573,18 +592,34 @@ EXPORT_SYMBOL_GPL(usbnet_purge_paused_rxq);
static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
{
unsigned long flags;
- struct sk_buff *skb, *skbnext;
+ struct sk_buff *skb;
int count = 0;
spin_lock_irqsave (&q->lock, flags);
- skb_queue_walk_safe(q, skb, skbnext) {
+ while (!skb_queue_empty(q)) {
struct skb_data *entry;
struct urb *urb;
int retval;
- entry = (struct skb_data *) skb->cb;
+ skb_queue_walk(q, skb) {
+ entry = (struct skb_data *) skb->cb;
+ if (entry->state != unlink_start)
+ goto found;
+ }
+ break;
+found:
+ entry->state = unlink_start;
urb = entry->urb;
+ /*
+ * Get reference count of the URB to avoid it to be
+ * freed during usb_unlink_urb, which may trigger
+ * use-after-free problem inside usb_unlink_urb since
+ * usb_unlink_urb is always racing with .complete
+ * handler(include defer_bh).
+ */
+ usb_get_urb(urb);
+ spin_unlock_irqrestore(&q->lock, flags);
// during some PM-driven resume scenarios,
// these (async) unlinks complete immediately
retval = usb_unlink_urb (urb);
@@ -592,6 +627,8 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
netdev_dbg(dev->net, "unlink urb err, %d\n", retval);
else
count++;
+ usb_put_urb(urb);
+ spin_lock_irqsave(&q->lock, flags);
}
spin_unlock_irqrestore (&q->lock, flags);
return count;
@@ -1022,9 +1059,7 @@ static void tx_complete (struct urb *urb)
}
usb_autopm_put_interface_async(dev->intf);
- urb->dev = NULL;
- entry->state = tx_done;
- defer_bh(dev, skb, &dev->txq);
+ (void) defer_bh(dev, skb, &dev->txq, tx_done);
}
/*-------------------------------------------------------------------------*/
@@ -1077,7 +1112,6 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
entry = (struct skb_data *) skb->cb;
entry->urb = urb;
entry->dev = dev;
- entry->state = tx_start;
entry->length = length;
usb_fill_bulk_urb (urb, dev->udev, dev->out,
@@ -1136,7 +1170,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
break;
case 0:
net->trans_start = jiffies;
- __skb_queue_tail (&dev->txq, skb);
+ __usbnet_queue_skb(&dev->txq, skb, tx_start);
if (dev->txq.qlen >= TX_QLEN (dev))
netif_stop_queue (net);
}
@@ -1531,7 +1565,7 @@ int usbnet_resume (struct usb_interface *intf)
if (test_bit(EVENT_DEV_OPEN, &dev->flags)) {
if (!(dev->txq.qlen >= TX_QLEN(dev)))
- netif_start_queue(dev->net);
+ netif_tx_wake_all_queues(dev->net);
tasklet_schedule (&dev->bh);
}
}
diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig
index ef9ce5a00538..b02a173f98a5 100644
--- a/drivers/net/wireless/bcmdhd/Kconfig
+++ b/drivers/net/wireless/bcmdhd/Kconfig
@@ -26,6 +26,7 @@ config BCMDHD_NVRAM_DIR
config BCMDHD_WEXT
bool "Enable WEXT support"
+ depends on BCMDHD
select WIRELESS_EXT
select WEXT_PRIV
help
@@ -54,15 +55,11 @@ config DHD_ENABLE_P2P
config BCMDHD_CFG80211
bool "Enable CFG80211 support"
- depends on CFG80211
+ depends on BCMDHD && CFG80211
+ default n
help
Enables CFG80211 support
-config BCMDHD_NOAPI
- bool "No wireless API"
- help
- No wireless API is needed
-
config BCMDHD_WIFI_CONTROL_FUNC
bool "Use bcmdhd_wlan device"
depends on BCMDHD
diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
index 2851388cf194..4ec987da11f8 100644
--- a/drivers/net/wireless/bcmdhd/Makefile
+++ b/drivers/net/wireless/bcmdhd/Makefile
@@ -8,9 +8,15 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \
-DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \
-DKEEP_ALIVE -DPKT_FILTER_SUPPORT \
-DEMBEDDED_PLATFORM \
- -DSET_RANDOM_MAC_SOFTAP -DWL_CFG80211_STA_EVENT \
-Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include
+# Only for JB (disable on ICS)
+DHDCFLAGS += -DSET_RANDOM_MAC_SOFTAP -DWL_CFG80211_STA_EVENT
+
+# for WFD IE support
+DHDCFLAGS += -DWLWFDIE
+
+
ifeq ($(CONFIG_BCMDHD_WIFI_CONTROL_FUNC),y)
DHDCFLAGS += -DCONFIG_WIFI_CONTROL_FUNC
else
@@ -38,7 +44,7 @@ endif
DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o \
dhd_linux_sched.o bcmwifi.o dhd_sdio.o bcmevent.o dhd_bta.o hndpmu.o \
bcmsdh.o dhd_cdc.o bcmsdh_linux.o dhd_common.o linux_osl.o \
- bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o wldev_common.o wl_android.o dhd_cfg80211.o
+ bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o wldev_common.o wl_android.o
obj-$(CONFIG_BCMDHD) += bcmdhd.o
bcmdhd-objs += $(DHDOFILES)
@@ -48,17 +54,21 @@ bcmdhd-objs += wl_iw.o
DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT
endif
-ifneq ($(CONFIG_CFG80211),)
-bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o
+ifneq ($(CONFIG_BCMDHD_CFG80211),)
+bcmdhd-objs += wl_cfg80211.o dhd_cfg80211.o wl_cfgp2p.o wl_linux_mon.o
DHDCFLAGS += -DWL_CFG80211
endif
+
ifneq ($(CONFIG_DHD_USE_SCHED_SCAN),)
DHDCFLAGS += -DWL_SCHED_SCAN
endif
+
ifneq ($(CONFIG_DHD_ENABLE_P2P),)
DHDCFLAGS += -DWL_ENABLE_P2P_IF
endif
+
EXTRA_CFLAGS = $(DHDCFLAGS)
+
ifeq ($(CONFIG_BCMDHD),m)
EXTRA_LDFLAGS += --strip-debug
endif
diff --git a/drivers/net/wireless/bcmdhd/bcmevent.c b/drivers/net/wireless/bcmdhd/bcmevent.c
index 6a25d9a5a57f..84ab7564ad7d 100644
--- a/drivers/net/wireless/bcmdhd/bcmevent.c
+++ b/drivers/net/wireless/bcmdhd/bcmevent.c
@@ -54,7 +54,6 @@ const bcmevent_name_t bcmevent_names[] = {
{ WLC_E_MIC_ERROR, "MIC_ERROR" },
{ WLC_E_NDIS_LINK, "NDIS_LINK" },
{ WLC_E_ROAM, "ROAM" },
- { WLC_E_TXFAIL, "TXFAIL" },
{ WLC_E_PMKID_CACHE, "PMKID_CACHE" },
{ WLC_E_RETROGRADE_TSF, "RETROGRADE_TSF" },
{ WLC_E_PRUNE, "PRUNE" },
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
index e67eeca1f99c..ffcb49bda290 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
@@ -36,6 +36,7 @@
#include <linux/mmc/core.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
@@ -1326,7 +1327,7 @@ sdioh_start(sdioh_info_t *si, int stage)
2.6.27. The implementation prior to that is buggy, and needs broadcom's
patch for it
*/
- if ((ret = sdio_reset_comm(gInstance->func[0]->card))) {
+ if ((ret = mmc_power_restore_host((gInstance->func[0])->card->host))) {
sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret));
return ret;
}
@@ -1405,6 +1406,8 @@ sdioh_stop(sdioh_info_t *si)
#endif
bcmsdh_oob_intr_set(FALSE);
#endif /* !defined(OOB_INTR_ONLY) */
+ if (mmc_power_save_host((gInstance->func[0])->card->host))
+ sd_err(("%s card power save fail\n", __FUNCTION__));
}
else
sd_err(("%s Failed\n", __FUNCTION__));
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
index 656953939b71..6ca85311b4c4 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
@@ -34,6 +34,7 @@
#include <linux/mmc/core.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
@@ -131,6 +132,10 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func,
#endif
sd_trace(("F2 found, calling bcmsdh_probe_bcmdhd...\n"));
ret = bcmsdh_probe_bcmdhd(&func->dev);
+#ifndef DHDTHREAD
+ if (mmc_power_save_host(func->card->host))
+ sd_err(("%s: card power save fail", __FUNCTION__));
+#endif
}
return ret;
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
index 5ff5c218ddcf..871c2bfb51d2 100644
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -24,7 +24,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd.h 328934 2012-04-23 05:15:42Z $
+ * $Id: dhd.h 333052 2012-05-12 02:09:28Z $
*/
/****************
@@ -437,10 +437,14 @@ extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled);
extern int dhd_pno_clean(dhd_pub_t *dhd);
extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid,
ushort scan_fr, int pno_repeat, int pno_freq_expo_max);
+extern int dhd_pno_set_ex(dhd_pub_t *dhd, wl_pfn_t* ssidnet, int nssid,
+ ushort pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time);
extern int dhd_pno_get_status(dhd_pub_t *dhd);
extern int dhd_dev_pno_reset(struct net_device *dev);
extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local,
int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max);
+extern int dhd_dev_pno_set_ex(struct net_device *dev, wl_pfn_t* ssidnet, int nssid,
+ ushort pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time);
extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled);
extern int dhd_dev_get_pno_status(struct net_device *dev);
#endif /* PNO_SUPPORT */
diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c
index d9810ace1cb4..3ccc55d87d4b 100644
--- a/drivers/net/wireless/bcmdhd/dhd_common.c
+++ b/drivers/net/wireless/bcmdhd/dhd_common.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_common.c 329682 2012-04-26 09:20:38Z $
+ * $Id: dhd_common.c 331276 2012-05-04 08:05:57Z $
*/
#include <typedefs.h>
#include <osl.h>
@@ -1890,12 +1890,13 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
return ret;
}
- if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
- return (ret);
memset(iovbuf, 0, sizeof(iovbuf));
#ifndef WL_SCHED_SCAN
+ if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
+ return (ret);
+
if ((pfn_enabled) && (dhd_is_associated(dhd, NULL, NULL) == TRUE)) {
DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__));
return ret;
@@ -1939,9 +1940,10 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
err = -1;
return err;
}
-
+#ifndef WL_SCHED_SCAN
if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
return (err);
+#endif /* !WL_SCHED_SCAN */
/* Check for broadcast ssid */
for (k = 0; k < nssid; k++) {
@@ -2035,6 +2037,123 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
}
int
+dhd_pno_set_ex(dhd_pub_t *dhd, wl_pfn_t* ssidnet, int nssid, ushort pno_interval,
+ int pno_repeat, int pno_expo_max, int pno_lost_time)
+{
+ int err = -1;
+ char iovbuf[128];
+ int k, i;
+ wl_pfn_param_t pfn_param;
+ wl_pfn_t pfn_element;
+ uint len = 0;
+
+ DHD_TRACE(("%s nssid=%d pno_interval=%d\n", __FUNCTION__, nssid, pno_interval));
+
+ if ((!dhd) && (!ssidnet)) {
+ DHD_ERROR(("%s error exit\n", __FUNCTION__));
+ err = -1;
+ return err;
+ }
+
+ if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
+ return (err);
+
+ /* Check for broadcast ssid */
+ for (k = 0; k < nssid; k++) {
+ if (!ssidnet[k].ssid.SSID_len) {
+ DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO setting\n", k));
+ return err;
+ }
+ }
+/* #define PNO_DUMP 1 */
+#ifdef PNO_DUMP
+ {
+ int j;
+ for (j = 0; j < nssid; j++) {
+ DHD_ERROR(("%d: scan for %s size =%d\n", j,
+ ssidnet[j].ssid.SSID, ssidnet[j].ssid.SSID_len));
+ }
+ }
+#endif /* PNO_DUMP */
+
+ /* clean up everything */
+ if ((err = dhd_pno_clean(dhd)) < 0) {
+ DHD_ERROR(("%s failed error=%d\n", __FUNCTION__, err));
+ return err;
+ }
+ memset(iovbuf, 0, sizeof(iovbuf));
+ memset(&pfn_param, 0, sizeof(pfn_param));
+ memset(&pfn_element, 0, sizeof(pfn_element));
+
+ /* set pfn parameters */
+ pfn_param.version = htod32(PFN_VERSION);
+ pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT));
+
+ /* check and set extra pno params */
+ if ((pno_repeat != 0) || (pno_expo_max != 0)) {
+ pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT);
+ pfn_param.repeat = (uchar) (pno_repeat);
+ pfn_param.exp = (uchar) (pno_expo_max);
+ }
+
+ /* set up pno scan fr */
+ if (pno_interval != 0)
+ pfn_param.scan_freq = htod32(pno_interval);
+
+ if (pfn_param.scan_freq > PNO_SCAN_MAX_FW_SEC) {
+ DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW_SEC));
+ return err;
+ }
+ if (pfn_param.scan_freq < PNO_SCAN_MIN_FW_SEC) {
+ DHD_ERROR(("%s pno freq less %d sec\n", __FUNCTION__, PNO_SCAN_MIN_FW_SEC));
+ return err;
+ }
+
+ /* network lost time */
+ pfn_param.lost_network_timeout = htod32(pno_lost_time);
+
+ len = bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf, sizeof(iovbuf));
+ if ((err = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) {
+ DHD_ERROR(("%s pfn_set failed for error=%d\n",
+ __FUNCTION__, err));
+ return err;
+ } else {
+ DHD_TRACE(("%s pfn_set OK with PNO time=%d repeat=%d max_adjust=%d\n",
+ __FUNCTION__, pfn_param.scan_freq,
+ pfn_param.repeat, pfn_param.exp));
+ }
+
+ /* set all pfn ssid */
+ for (i = 0; i < nssid; i++) {
+ pfn_element.flags = htod32(ssidnet[i].flags);
+ pfn_element.infra = htod32(ssidnet[i].infra);
+ pfn_element.auth = htod32(ssidnet[i].auth);
+ pfn_element.wpa_auth = htod32(ssidnet[i].wpa_auth);
+ pfn_element.wsec = htod32(ssidnet[i].wsec);
+
+ memcpy((char *)pfn_element.ssid.SSID, ssidnet[i].ssid.SSID, ssidnet[i].ssid.SSID_len);
+ pfn_element.ssid.SSID_len = htod32(ssidnet[i].ssid.SSID_len);
+
+ if ((len =
+ bcm_mkiovar("pfn_add", (char *)&pfn_element,
+ sizeof(pfn_element), iovbuf, sizeof(iovbuf))) > 0) {
+ if ((err =
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) {
+ DHD_ERROR(("%s pfn_add failed with ssidnet[%d] error=%d\n",
+ __FUNCTION__, i, err));
+ return err;
+ } else {
+ DHD_TRACE(("%s pfn_add OK with ssidnet[%d]\n", __FUNCTION__, i));
+ }
+ } else {
+ DHD_ERROR(("%s bcm_mkiovar failed with ssidnet[%d]\n", __FUNCTION__, i));
+ }
+ }
+
+ return err;
+}
+
+int
dhd_pno_get_status(dhd_pub_t *dhd)
{
int ret = -1;
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 6ba7df1cac32..44879e4a1170 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_linux.c 329682 2012-04-26 09:20:38Z $
+ * $Id: dhd_linux.c 333885 2012-05-18 00:39:03Z $
*/
#include <typedefs.h>
@@ -42,7 +42,6 @@
#include <linux/ethtool.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
-#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
@@ -1526,9 +1525,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
tout_ctrl = DHD_PACKET_TIMEOUT_MS;
if (event.event_type == WLC_E_BTA_HCI_EVENT) {
dhd_bta_doevt(dhdp, data, event.datalen);
- } else if (event.event_type == WLC_E_PFN_NET_FOUND) {
+ }
+#ifdef PNO_SUPPORT
+ if (event.event_type == WLC_E_PFN_NET_FOUND) {
tout_ctrl *= 2;
}
+#endif /* PNO_SUPPORT */
} else {
tout_rx = DHD_PACKET_TIMEOUT_MS;
}
@@ -2603,7 +2605,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen, void *dev)
}
dhd_state |= DHD_ATTACH_STATE_NET_ALLOC;
- SET_NETDEV_DEV(net, (struct device *)dev);
/* Allocate primary dhd_info */
if (!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) {
DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__));
@@ -2941,16 +2942,20 @@ dhd_concurrent_fw(dhd_pub_t *dhd)
bcm_mkiovar("p2p", 0, 0, buf, sizeof(buf));
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
FALSE, 0)) < 0) {
- DHD_TRACE(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret));
+ DHD_ERROR(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret));
} else if (buf[0] == 1) {
DHD_TRACE(("%s: P2P is supported\n", __FUNCTION__));
return 1;
}
}
- return 0;
+ return ret;
}
#endif
+/*
+ * dhd_preinit_ioctls makes special pre-setting in the firmware before radio turns on
+ * returns : 0 if all settings passed or negative value if anything failed
+*/
int
dhd_preinit_ioctls(dhd_pub_t *dhd)
{
@@ -2959,7 +2964,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
#if !defined(WL_CFG80211)
uint up = 0;
-#endif
+#endif /* defined(WL_CFG80211) */
uint power_mode = PM_FAST;
uint32 dongle_align = DHD_SDALIGN;
uint32 glom = 0;
@@ -3043,19 +3048,31 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#endif /* SET_RANDOM_MAC_SOFTAP */
DHD_TRACE(("Firmware = %s\n", fw_path));
+
#if !defined(AP) && defined(WLP2P)
/* Check if firmware with WFD support used */
+#if defined(WL_ENABLE_P2P_IF)
+ if ((ret = dhd_concurrent_fw(dhd)) < 0) {
+ DHD_ERROR(("%s error : firmware can't support p2p mode\n", __FUNCTION__));
+ goto done;
+ }
+#endif /* (WL_ENABLE_P2P_IF) */
+
if ((!op_mode && strstr(fw_path, "_p2p") != NULL)
#if defined(WL_ENABLE_P2P_IF)
- || (op_mode == 0x04) ||(dhd_concurrent_fw(dhd))
+ || (op_mode == WFD_MASK) || (dhd_concurrent_fw(dhd) == 1)
#endif
) {
bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
- DHD_ERROR(("%s APSTA for WFD failed ret= %d\n", __FUNCTION__, ret));
+ DHD_ERROR(("%s APSTA setting failed ret= %d\n", __FUNCTION__, ret));
} else {
dhd->op_mode |= WFD_MASK;
+#if !defined(WL_ENABLE_P2P_IF)
+ /* ICS back capability : disable any packet filtering for p2p only mode */
+ dhd_pkt_filter_enable = FALSE;
+#endif /*!defined(WL_ENABLE_P2P_IF) */
}
}
#endif
@@ -3100,16 +3117,20 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#if defined(ARP_OFFLOAD_SUPPORT)
arpoe = 0;
#endif /* (ARP_OFFLOAD_SUPPORT) */
+ /* disable any filtering for SoftAP mode */
dhd_pkt_filter_enable = FALSE;
}
}
#endif
+#if !defined(WL_ENABLE_P2P_IF)
+ /* ICS mode setting for sta */
if ((dhd->op_mode != WFD_MASK) && (dhd->op_mode != HOSTAPD_MASK)) {
/* STA only operation mode */
dhd->op_mode |= STA_MASK;
dhd_pkt_filter_enable = TRUE;
}
+#endif /* !defined(WL_ENABLE_P2P_IF) */
DHD_ERROR(("Firmware up: fw_path=%s op_mode=%d, "
"Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
@@ -3262,6 +3283,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
dhd->pktfilter[1] = NULL;
dhd->pktfilter[2] = NULL;
dhd->pktfilter[3] = NULL;
+ /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */
dhd->pktfilter[4] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB";
#if defined(SOFTAP)
if (ap_fw_loaded) {
@@ -4448,6 +4470,17 @@ dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid,
return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr, pno_repeat, pno_freq_expo_max));
}
+/* Linux wrapper to call common dhd_pno_set_ex */
+int
+dhd_dev_pno_set_ex(struct net_device *dev, wl_pfn_t* ssidnet, int nssid,
+ ushort pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ return (dhd_pno_set_ex(&dhd->pub, ssidnet, nssid,
+ pno_interval, pno_repeat, pno_expo_max, pno_lost_time));
+}
+
/* Linux wrapper to get pno status */
int
dhd_dev_get_pno_status(struct net_device *dev)
@@ -4466,9 +4499,9 @@ static void dhd_hang_process(struct work_struct *work)
struct net_device *dev;
dhd = (dhd_info_t *)container_of(work, dhd_info_t, work_hang);
- dev = dhd->iflist[0]->net;
+ dev = dhd->iflist[0]->net;
- if (dev) {
+ if (dev) {
rtnl_lock();
dev_close(dev);
rtnl_unlock();
@@ -4478,7 +4511,7 @@ static void dhd_hang_process(struct work_struct *work)
#if defined(WL_CFG80211)
wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED);
#endif
- }
+ }
}
int net_os_send_hang_message(struct net_device *dev)
diff --git a/drivers/net/wireless/bcmdhd/include/bcmdevs.h b/drivers/net/wireless/bcmdhd/include/bcmdevs.h
index 287f1c65fc9a..4d2f5763a3d9 100644
--- a/drivers/net/wireless/bcmdhd/include/bcmdevs.h
+++ b/drivers/net/wireless/bcmdhd/include/bcmdevs.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmdevs.h 295140 2011-11-09 17:22:01Z $
+ * $Id: bcmdevs.h 332966 2012-05-11 22:40:21Z $
*/
@@ -373,6 +373,7 @@
#define BFL2_EXTLNA_TX 0x08000000
#define BFL2_4313_RADIOREG 0x10000000
+#define BFL2_SECI_LOPWR_DIS 0x20000000
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
index 3bff73e2a6bc..5df25c16b7d9 100644
--- a/drivers/net/wireless/bcmdhd/include/epivers.h
+++ b/drivers/net/wireless/bcmdhd/include/epivers.h
@@ -23,6 +23,7 @@
*
*/
+
#ifndef _epivers_h_
#define _epivers_h_
@@ -32,17 +33,17 @@
#define EPI_RC_NUMBER 195
-#define EPI_INCREMENTAL_NUMBER 61
+#define EPI_INCREMENTAL_NUMBER 75
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 5, 90, 195, 61
+#define EPI_VERSION 5, 90, 195, 75
-#define EPI_VERSION_NUM 0x055ac33d
+#define EPI_VERSION_NUM 0x055ac34b
#define EPI_VERSION_DEV 5.90.195
-#define EPI_VERSION_STR "5.90.195.61"
+#define EPI_VERSION_STR "5.90.195.75"
#endif
diff --git a/drivers/net/wireless/bcmdhd/include/hndpmu.h b/drivers/net/wireless/bcmdhd/include/hndpmu.h
index 69a834c6b7eb..9bfc8c9275a9 100644
--- a/drivers/net/wireless/bcmdhd/include/hndpmu.h
+++ b/drivers/net/wireless/bcmdhd/include/hndpmu.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: hndpmu.h 277737 2011-08-16 17:54:59Z $
+ * $Id: hndpmu.h 335486 2012-05-28 09:47:55Z $
*/
#ifndef _hndpmu_h_
@@ -31,4 +31,7 @@
extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on);
extern void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength);
+extern void si_pmu_set_otp_wr_volts(si_t *sih);
+extern void si_pmu_set_otp_rd_volts(si_t *sih);
+
#endif /* _hndpmu_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/sbchipc.h b/drivers/net/wireless/bcmdhd/include/sbchipc.h
index 8f757509b95d..53bd2a1d5580 100644
--- a/drivers/net/wireless/bcmdhd/include/sbchipc.h
+++ b/drivers/net/wireless/bcmdhd/include/sbchipc.h
@@ -5,7 +5,7 @@
* JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer,
* GPIO interface, extbus, and support for serial and parallel flashes.
*
- * $Id: sbchipc.h 311371 2012-01-28 05:47:25Z $
+ * $Id: sbchipc.h 333924 2012-05-18 04:48:52Z $
*
* Copyright (C) 1999-2011, Broadcom Corporation
*
@@ -1441,18 +1441,18 @@ typedef volatile struct {
#define CCTRL4331_EXT_LNA_G (1<<2)
#define CCTRL4331_SPROM_GPIO13_15 (1<<3)
#define CCTRL4331_EXTPA_EN (1<<4)
-#define CCTRL4331_GPIOCLK_ON_SPROMCS <1<<5)
+#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5)
#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6)
#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7)
#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8)
#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9)
-#define CCTRL4331_PCIE_AUXCLKEN <1<<10)
-#define CCTRL4331_PCIE_PIPE_PLLDOWN <1<<11)
-#define CCTRL4331_EXTPA_EN2 (1<<12)
-#define CCTRL4331_EXT_LNA_A (1<<13)
-#define CCTRL4331_BT_SHD0_ON_GPIO4 <1<<16)
-#define CCTRL4331_BT_SHD1_ON_GPIO5 <1<<17)
-#define CCTRL4331_EXTPA_ANA_EN (1<<24)
+#define CCTRL4331_PCIE_AUXCLKEN (1<<10)
+#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11)
+#define CCTRL4331_EXTPA_EN2 (1<<12)
+#define CCTRL4331_EXT_LNA_A (1<<13)
+#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16)
+#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17)
+#define CCTRL4331_EXTPA_ANA_EN (1<<24)
#define CST4331_XTAL_FREQ 0x00000001
diff --git a/drivers/net/wireless/bcmdhd/include/siutils.h b/drivers/net/wireless/bcmdhd/include/siutils.h
index 6a7b93c7b977..4e7aeb71cb02 100644
--- a/drivers/net/wireless/bcmdhd/include/siutils.h
+++ b/drivers/net/wireless/bcmdhd/include/siutils.h
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: siutils.h 285387 2011-09-21 18:38:37Z $
+ * $Id: siutils.h 335486 2012-05-28 09:47:55Z $
*/
@@ -222,6 +222,8 @@ static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;}
extern bool si_is_otp_disabled(si_t *sih);
extern bool si_is_otp_powered(si_t *sih);
extern void si_otp_power(si_t *sih, bool on);
+extern void si_set_otp_wr_volts(si_t *sih);
+extern void si_set_otp_rd_volts(si_t *sih);
extern bool si_is_sprom_available(si_t *sih);
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h
index 91274a0c680b..5ec0c9ade197 100644
--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h
+++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h
@@ -24,7 +24,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wlioctl.h 312596 2012-02-03 02:53:30Z $
+ * $Id: wlioctl.h 331292 2012-05-04 09:04:23Z $
*/
@@ -1460,6 +1460,14 @@ typedef struct wl_sampledata {
} wl_sampledata_t;
+#define WL_CHAN_VALID_HW (1 << 0)
+#define WL_CHAN_VALID_SW (1 << 1)
+#define WL_CHAN_BAND_5G (1 << 2)
+#define WL_CHAN_RADAR (1 << 3)
+#define WL_CHAN_INACTIVE (1 << 4)
+#define WL_CHAN_PASSIVE (1 << 5)
+#define WL_CHAN_RESTRICTED (1 << 6)
+
#define WL_ERROR_VAL 0x00000001
#define WL_TRACE_VAL 0x00000002
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index f728c14622a1..2c4e9a63dd9e 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -84,17 +84,15 @@ u32 wl_dbg_level = WL_DBG_ERR;
* All the chnages in world regulatory domain are to be done here.
*/
static const struct ieee80211_regdomain brcm_regdom = {
- .n_reg_rules = 5,
+ .n_reg_rules = 4,
.alpha2 = "99",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..11 */
- REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
+ REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
/* IEEE 802.11b/g, channels 12..13. No HT40
* channel fits here.
*/
- REG_RULE(2467-10, 2472+10, 20, 6, 20,
- NL80211_RRF_PASSIVE_SCAN |
- NL80211_RRF_NO_IBSS),
+ /* If any */
/*
* IEEE 802.11 channel 14 - is for JP only,
* we need cfg80211 to allow it (reg_flags = 0); so that
@@ -231,6 +229,8 @@ static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
const wl_event_msg_t *e, void *data);
static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
const wl_event_msg_t *e, void *data, bool completed);
+static s32 wl_ibss_join_done(struct wl_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data, bool completed);
static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
const wl_event_msg_t *e, void *data);
static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
@@ -296,6 +296,7 @@ static void wl_free_wdev(struct wl_priv *wl);
static s32 wl_inform_bss(struct wl_priv *wl);
static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
+static s32 wl_inform_ibss(struct wl_priv *wl, const u8 *bssid);
static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev);
static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
@@ -335,7 +336,6 @@ static void wl_link_up(struct wl_priv *wl);
static void wl_link_down(struct wl_priv *wl);
static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype);
static void wl_init_conf(struct wl_conf *conf);
-static s32 wl_update_wiphybands(struct wl_priv *wl);
/*
* iscan handler
@@ -704,7 +704,7 @@ static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
*(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf,
- sizeof(WL_EXTRA_BUF_MAX), false))) {
+ WL_EXTRA_BUF_MAX, false))) {
WL_ERR(("Failed to get associated bss info, use temp channel \n"));
chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN);
}
@@ -925,6 +925,11 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
if (wl->p2p_supported) {
memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN);
+
+ /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
+ */
+ WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
+ wl_clr_p2p_status(wl, GO_NEG_PHASE);
if (wl->p2p->vif_created) {
if (wl_get_drv_status(wl, SCANNING, dev)) {
wl_notify_escan_complete(wl, dev, true, true);
@@ -1004,6 +1009,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
default:
return -EINVAL;
}
+ WL_DBG(("%s : ap (%d), infra (%d), iftype: (%d)\n", ndev->name, ap, infra, type));
if (ap) {
wl_set_mode_by_netdev(wl, ndev, mode);
@@ -1019,7 +1025,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
*/
chspec = wl_cfg80211_get_shared_freq(wiphy);
- wlif_type = ap ? WL_P2P_IF_GO : WL_P2P_IF_CLIENT;
+ wlif_type = WL_P2P_IF_GO;
WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n",
ndev->name, ap, infra, type));
wl_set_p2p_status(wl, IF_CHANGING);
@@ -1043,6 +1049,14 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
return -EINVAL;
}
+ } else {
+ infra = htod32(infra);
+ err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
+ if (err) {
+ WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
+ return -EAGAIN;
+ }
+ wl_set_mode_by_netdev(wl, ndev, mode);
}
ndev->ieee80211_ptr->iftype = type;
@@ -1587,6 +1601,8 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
wl_cfgp2p_generate_bss_mac(&primary_mac,
&wl->p2p->dev_addr, &wl->p2p->int_addr);
}
+ wl_clr_p2p_status(wl, GO_NEG_PHASE);
+ WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
p2p_scan(wl) = true;
}
} else {
@@ -1625,10 +1641,13 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
} else {
wpsie_len = 0;
}
- err = wl_cfgp2p_set_management_ie(wl, ndev, -1,
- VNDR_IE_PRBREQ_FLAG, wpsie, wpsie_len);
- if (unlikely(err)) {
- goto scan_out;
+ if (wpsie_len > 0) {
+ err = wl_cfgp2p_set_management_ie(wl,
+ ndev, -1, VNDR_IE_PRBREQ_FLAG,
+ wpsie, wpsie_len);
+ if (unlikely(err)) {
+ goto scan_out;
+ }
}
}
}
@@ -1808,86 +1827,192 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params)
{
struct wl_priv *wl = wiphy_priv(wiphy);
- struct cfg80211_bss *bss;
- struct ieee80211_channel *chan;
struct wl_join_params join_params;
- struct cfg80211_ssid ssid;
- s32 scan_retry = 0;
+ struct wlc_ssid ssid;
+ struct ether_addr bssid;
+ size_t join_params_size = 0;
+ s32 wsec = 0;
+ s32 bcnprd;
s32 err = 0;
- bool rollback_lock = false;
WL_TRACE(("In\n"));
CHECK_SYS_UP(wl);
- if (params->bssid) {
- WL_ERR(("Invalid bssid\n"));
- return -EOPNOTSUPP;
- }
- bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
- if (!bss) {
- memcpy(ssid.ssid, params->ssid, params->ssid_len);
- ssid.ssid_len = params->ssid_len;
- do {
- if (unlikely
- (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
- -EBUSY)) {
- wl_delay(150);
- } else {
- break;
- }
- } while (++scan_retry < WL_SCAN_RETRY_MAX);
- /* to allow scan_inform to propagate to cfg80211 plane */
- if (rtnl_is_locked()) {
- rtnl_unlock();
- rollback_lock = true;
- }
-
- /* wait 4 secons till scan done.... */
- schedule_timeout_interruptible(4 * HZ);
- if (rollback_lock)
- rtnl_lock();
- bss = cfg80211_get_ibss(wiphy, NULL,
- params->ssid, params->ssid_len);
- }
- if (bss) {
- wl->ibss_starter = false;
- WL_DBG(("Found IBSS\n"));
- } else {
- wl->ibss_starter = true;
- }
- chan = params->channel;
- if (chan)
- wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
+
/*
- * Join with specific BSSID and cached SSID
- * If SSID is zero join based on BSSID only
+ * Cancel ongoing scan to sync up with sme state machine of cfg80211.
*/
- memset(&join_params, 0, sizeof(join_params));
- memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
- params->ssid_len);
- join_params.ssid.SSID_len = htod32(params->ssid_len);
+ if (wl->scan_request) {
+ wl_notify_escan_complete(wl, dev, true, true);
+ }
+ /* Clean BSSID */
+ bzero(&bssid, sizeof(bssid));
+ wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
+
+ if (params->ssid)
+ WL_INFO(("SSID: %s\n", params->ssid));
+ else {
+ WL_ERR(("SSID: NULL, Not supported\n"));
+ err = -EOPNOTSUPP;
+ goto CleanUp;
+ }
+
if (params->bssid)
- memcpy(&join_params.params.bssid, params->bssid,
- ETHER_ADDR_LEN);
+ WL_INFO(("BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ params->bssid[0], params->bssid[1], params->bssid[2],
+ params->bssid[3], params->bssid[4], params->bssid[5]));
+
+ if (params->channel)
+ WL_INFO(("channel: %d\n", params->channel->center_freq));
+
+ if (params->channel_fixed)
+ WL_INFO(("fixed channel required\n"));
+
+ if (params->ie && params->ie_len)
+ WL_INFO(("ie len: %d\n", params->ie_len));
+
+ if (params->beacon_interval)
+ WL_INFO(("beacon interval: %d\n", params->beacon_interval));
+
+ if (params->basic_rates)
+ WL_INFO(("basic rates: %08X\n", params->basic_rates));
+
+ if (params->privacy)
+ WL_INFO(("privacy required\n"));
+
+ wl_set_drv_status(wl, CONNECTING, dev);
+
+ /* Configure Privacy for starter */
+ if (params->privacy)
+ wsec |= WEP_ENABLED;
+
+ err = wldev_iovar_setint(dev, "wsec", wsec);
+ if (err) {
+ WL_ERR(("wsec failed (%d)\n", err));
+ goto CleanUp;
+ }
+
+ err = wldev_iovar_setint(dev, "auth", WL_AUTH_OPEN_SYSTEM);
+ if (err) {
+ WL_ERR(("auth failed (%d)\n", err));
+ goto CleanUp;
+ }
+
+ err = wldev_iovar_setint(dev, "wpa_auth", 0);
+ if (err) {
+ WL_ERR(("wpa_auth failed (%d)\n", err));
+ goto CleanUp;
+ }
+
+ /* Configure Beacon Interval for starter */
+ if (params->beacon_interval)
+ bcnprd = params->beacon_interval;
else
- memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
+ bcnprd = 100;
- err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
- sizeof(join_params), false);
- if (unlikely(err)) {
- WL_ERR(("Error (%d)\n", err));
- return err;
+ bcnprd = htod32(bcnprd);
+ err = wldev_ioctl(dev, WLC_SET_BCNPRD, &bcnprd, sizeof(bcnprd), true);
+ if (err) {
+ WL_ERR(("WLC_SET_BCNPRD failed (%d)\n", err));
+ goto CleanUp;
+ }
+
+ /* Configure required join parameter */
+ memset(&join_params, 0, sizeof(struct wl_join_params));
+
+ /* SSID */
+ memset(&ssid, 0, sizeof(struct wlc_ssid));
+ ssid.SSID_len = MIN(params->ssid_len, 32);
+ join_params.ssid.SSID_len = htod32(ssid.SSID_len);
+ memcpy(ssid.SSID, params->ssid, ssid.SSID_len);
+ memcpy(join_params.ssid.SSID, params->ssid, ssid.SSID_len);
+ join_params_size = sizeof(join_params.ssid);
+
+ wl_update_prof(wl, dev, NULL, &ssid, WL_PROF_SSID);
+
+ /* BSSID */
+ if (params->bssid) {
+ memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
+ join_params_size = sizeof(join_params.ssid) +
+ WL_ASSOC_PARAMS_FIXED_SIZE;
+
+ wl_update_prof(wl, dev, NULL, params->bssid, WL_PROF_BSSID);
+ } else {
+ memcpy(&join_params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
}
+
+ /* Channel */
+ if (params->channel) {
+ u32 target_channel;
+
+ target_channel = ieee80211_frequency_to_channel(
+ params->channel->center_freq);
+ if (params->channel_fixed) {
+ /* adding chanspec */
+ wl_ch_to_chanspec(target_channel,
+ &join_params, &join_params_size);
+ }
+
+ /* set channel for starter */
+ target_channel = htod32(target_channel);
+ err = wldev_ioctl(dev, WLC_SET_CHANNEL,
+ &target_channel, sizeof(target_channel), true);
+ if (err) {
+ WL_ERR(("WLC_SET_CHANNEL failed (%d)\n", err));
+ goto CleanUp;
+ }
+ }
+
+ wl->ibss_starter = false;
+
+ err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
+ if (err) {
+ WL_ERR(("WLC_SET_SSID failed (%d)\n", err));
+ goto CleanUp;
+ }
+
+CleanUp:
+
+ if (err)
+ wl_clr_drv_status(wl, CONNECTING, dev);
+
+ WL_TRACE(("Exit\n"));
return err;
}
static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
{
struct wl_priv *wl = wiphy_priv(wiphy);
+ scb_val_t scbval;
+ bool act = false;
s32 err = 0;
+ u8 *curbssid;
+
+ WL_TRACE(("Enter\n"));
CHECK_SYS_UP(wl);
- wl_link_down(wl);
+ act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT);
+ curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
+ if (act) {
+ /*
+ * Cancel ongoing scan to sync up with sme state machine of cfg80211.
+ */
+ if (wl->scan_request) {
+ wl_notify_escan_complete(wl, dev, true, true);
+ }
+ wl_set_drv_status(wl, DISCONNECTING, dev);
+ scbval.val = DOT11_RC_DISASSOC_LEAVING;
+ memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
+ scbval.val = htod32(scbval.val);
+ err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
+ sizeof(scb_val_t), true);
+ if (unlikely(err)) {
+ wl_clr_drv_status(wl, DISCONNECTING, dev);
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ }
+ WL_TRACE(("Exit\n"));
return err;
}
@@ -2216,8 +2341,9 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
*/
WL_DBG(("ASSOC2 p2p index : %d sme->ie_len %d\n",
wl_cfgp2p_find_idx(wl, dev), sme->ie_len));
- wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
- VNDR_IE_PRBREQ_FLAG, sme->ie, sme->ie_len);
+ wl_cfgp2p_set_management_ie(wl, dev,
+ wl_cfgp2p_find_idx(wl, dev), VNDR_IE_PRBREQ_FLAG,
+ sme->ie, sme->ie_len);
wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
}
@@ -3328,8 +3454,8 @@ wl_cfg80211_send_at_common_channel(struct wl_priv *wl,
if (wl->afx_hdl->peer_chan != WL_INVALID)
wl_cfg80211_send_pending_tx_act_frm(wl);
else {
- WL_ERR(("Couldn't find the peer after %d retries\n",
- wl->afx_hdl->retry));
+ WL_ERR(("Couldn't find the peer " MACSTR " after %d retries\n",
+ MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), wl->afx_hdl->retry));
}
wl->afx_hdl->dev = NULL;
wl->afx_hdl->bssidx = WL_INVALID;
@@ -3355,7 +3481,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
wl_af_params_t *af_params;
wifi_p2p_ie_t *p2p_ie;
wpa_ie_fixed_t *wps_ie;
+#ifdef WLWFDIE
wifi_wfd_ie_t *wfd_ie;
+#endif /* WLWFDIE */
scb_val_t scb_val;
const struct ieee80211_mgmt *mgmt;
struct wl_priv *wl = wiphy_priv(wiphy);
@@ -3364,7 +3492,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
s32 bssidx = 0;
u32 p2pie_len = 0;
u32 wpsie_len = 0;
+#ifdef WLWFDIE
u32 wfdie_len = 0;
+#endif /* WLWFDIE */
u32 id;
u32 retry = 0;
bool ack = false;
@@ -3414,11 +3544,13 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
/* Total length of P2P Information Element */
p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
}
+#ifdef WLWFDIE
if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)(buf + ie_offset), ie_len))
!= NULL) {
/* Total length of WFD Information Element */
wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
}
+#endif /* WLWFDIE */
if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len))
!= NULL) {
/* Order of Vendor IE is 1) WPS IE +
@@ -3430,7 +3562,11 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
sizeof(wps_ie->tag);
wl_cfgp2p_set_management_ie(wl, dev, bssidx,
VNDR_IE_PRBRSP_FLAG,
+#ifdef WLWFDIE
(u8 *)wps_ie, wpsie_len + p2pie_len + wfdie_len);
+#else
+ (u8 *)wps_ie, wpsie_len + p2pie_len);
+#endif /* WLWFDIE */
}
cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
goto exit;
@@ -3443,8 +3579,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
WL_DBG(("Disconnect STA : %s scb_val.val %d\n",
bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
scb_val.val));
- /* Wait for the deauth event to come, supplicant will do the delete iface immediately
- * and we will have problem in sending deauth frame if we delete the bss in firmware
+ /* Wait for the deauth event to come, supplicant will do the
+ * delete iface immediately and we will have problem in sending
+ * deauth frame if we delete the bss in firmware
*/
wl_delay(400);
cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
@@ -3513,6 +3650,36 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
WL_DBG(("P2P PUB action_frame->len: %d chan %d category %d subtype %d\n",
action_frame->len, af_params->channel,
act_frm->category, act_frm->subtype));
+ if (act_frm && ((act_frm->subtype == P2P_PAF_GON_REQ) ||
+ (act_frm->subtype == P2P_PAF_GON_RSP) ||
+ (act_frm->subtype == P2P_PAF_GON_CONF) ||
+ (act_frm->subtype == P2P_PAF_PROVDIS_REQ))) {
+ wldev_iovar_setint(dev, "mpc", 0);
+ }
+
+ if (act_frm->subtype == P2P_PAF_GON_REQ) {
+ WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
+ wl_set_p2p_status(wl, GO_NEG_PHASE);
+ } else if (act_frm->subtype == P2P_PAF_GON_CONF) {
+ /* If we reached till GO Neg confirmation
+ * reset the filter
+ */
+ WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
+ wl_clr_p2p_status(wl, GO_NEG_PHASE);
+ }
+
+ if (act_frm->subtype == P2P_PAF_GON_RSP)
+ retry_cnt = 1;
+ else retry_cnt = WL_ACT_FRAME_RETRY;
+
+ if (act_frm && act_frm->subtype == P2P_PAF_DEVDIS_REQ) {
+ af_params->dwell_time = WL_LONG_DWELL_TIME;
+ } else if (act_frm &&
+ (act_frm->subtype == P2P_PAF_PROVDIS_REQ ||
+ act_frm->subtype == P2P_PAF_PROVDIS_RSP ||
+ act_frm->subtype == P2P_PAF_GON_RSP)) {
+ af_params->dwell_time = WL_MED_DWELL_TIME;
+ }
} else if (wl_cfgp2p_is_p2p_action(action_frame->data, action_frame->len)) {
p2p_act_frm = (wifi_p2p_action_frame_t *) (action_frame->data);
WL_DBG(("P2P action_frame->len: %d chan %d category %d subtype %d\n",
@@ -3523,32 +3690,13 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
WL_DBG(("Service Discovery action_frame->len: %d chan %d category %d action %d\n",
action_frame->len, af_params->channel,
sd_act_frm->category, sd_act_frm->action));
-
+ af_params->dwell_time = WL_MED_DWELL_TIME;
+ retry_cnt = WL_ACT_FRAME_RETRY;
}
wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len);
/*
* To make sure to send successfully action frame, we have to turn off mpc
*/
-
- if (act_frm && ((act_frm->subtype == P2P_PAF_GON_REQ) ||
- (act_frm->subtype == P2P_PAF_GON_RSP) ||
- (act_frm->subtype == P2P_PAF_GON_CONF) ||
- (act_frm->subtype == P2P_PAF_PROVDIS_REQ))) {
- wldev_iovar_setint(dev, "mpc", 0);
- }
- if (act_frm->subtype == P2P_PAF_GON_RSP)
- retry_cnt = 1;
- else retry_cnt = WL_ACT_FRAME_RETRY;
-
- if (act_frm && act_frm->subtype == P2P_PAF_DEVDIS_REQ) {
- af_params->dwell_time = WL_LONG_DWELL_TIME;
- } else if (act_frm &&
- (act_frm->subtype == P2P_PAF_PROVDIS_REQ ||
- act_frm->subtype == P2P_PAF_PROVDIS_RSP ||
- act_frm->subtype == P2P_PAF_GON_RSP)) {
- af_params->dwell_time = WL_MED_DWELL_TIME;
- }
-
if (IS_P2P_SOCIAL(af_params->channel) &&
(IS_P2P_PUB_ACT_REQ(act_frm, &act_frm->elts[0], action_frame->len) ||
IS_GAS_REQ(sd_act_frm, action_frame->len)) &&
@@ -3560,6 +3708,18 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
/* channel offload for action request frame */
ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params);
+ /* We need to retry Service discovery frames as they don't get retried immediately by supplicant*/
+ if ((!ack) && (IS_GAS_REQ(sd_act_frm, action_frame->len))) {
+ for (retry = 1; retry < retry_cnt; retry++) {
+ WL_DBG(("Service Discovery action_frame retry %d len: %d chan %d category %d action %d\n",
+ retry, action_frame->len, af_params->channel,
+ sd_act_frm->category, sd_act_frm->action));
+ ack = (wl_cfgp2p_tx_action_frame(wl, dev,
+ af_params, bssidx)) ? false : true;
+ if (ack)
+ break;
+ }
+ }
} else {
ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true;
if (!ack) {
@@ -3915,13 +4075,17 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
wpa_ie_fixed_t *wpa_ie;
bcm_tlv_t *wpa2_ie;
wifi_p2p_ie_t *p2p_ie;
+#ifdef WLWFDIE
wifi_wfd_ie_t *wfd_ie;
+#endif /* WLWFDIE */
bool is_bssup = false;
bool update_bss = false;
bool pbc = false;
u16 wpsie_len = 0;
u16 p2pie_len = 0;
+#ifdef WLWFDIE
u32 wfdie_len = 0;
+#endif /* WLWFDIE */
u8 beacon_ie[IE_MAX_LEN];
s32 ie_offset = 0;
s32 bssidx = 0;
@@ -3979,24 +4143,30 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
} else {
WL_ERR(("No P2PIE in beacon \n"));
}
+#ifdef WLWFDIE
/* find the WFD IEs */
if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)info->tail, info->tail_len)) != NULL) {
- /* Total length of P2P Information Element */
- wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
- if ((wpsie_len + p2pie_len + wfdie_len) < IE_MAX_LEN) {
- memcpy(&beacon_ie[wpsie_len + p2pie_len], wfd_ie, wfdie_len);
- } else {
+ /* Total length of P2P Information Element */
+ wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
+ if ((wpsie_len + p2pie_len + wfdie_len) < IE_MAX_LEN) {
+ memcpy(&beacon_ie[wpsie_len + p2pie_len], wfd_ie, wfdie_len);
+ } else {
WL_ERR(("Found WFD IE but there is no space, (%d)(%d)(%d)\n",
- wpsie_len, p2pie_len, wfdie_len));
+ wpsie_len, p2pie_len, wfdie_len));
wfdie_len = 0;
}
} else {
WL_ERR(("No WFDIE in beacon \n"));
}
+#endif /* WLWFDIE */
/* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
+#ifdef WLWFDIE
beacon_ie, wpsie_len + p2pie_len + wfdie_len);
+#else
+ beacon_ie, wpsie_len + p2pie_len);
+#endif /* WLWFDIE */
/* find the RSN_IE */
if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
@@ -4268,7 +4438,7 @@ exit:
#ifdef WL_SCHED_SCAN
#define PNO_TIME 30
#define PNO_REPEAT 4
-#define PNO_FREQ_EXPO_MAX 3
+#define PNO_FREQ_EXPO_MAX 2
int wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_sched_scan_request *request)
@@ -4523,7 +4693,7 @@ static s32 wl_inform_bss(struct wl_priv *wl)
static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
{
- struct wiphy *wiphy = wiphy_from_scan(wl);
+ struct wiphy *wiphy = wl_to_wiphy(wl);
struct ieee80211_mgmt *mgmt;
struct ieee80211_channel *channel;
struct ieee80211_supported_band *band;
@@ -4615,8 +4785,13 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
kfree(notif_bss_info);
return err;
}
+ else if( wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_INFO) == NULL)
+ {
+ WL_DBG(("Couldn't find P2P_SEID_DEV_INFO in probe response/beacon\n"));
+ kfree(notif_bss_info);
+ return err;
+ }
}
-
if (!mgmt->u.probe_resp.timestamp) {
struct timeval tv;
@@ -4639,6 +4814,114 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
return err;
}
+static s32 wl_inform_ibss(struct wl_priv *wl, const u8 *bssid)
+{
+ struct net_device *ndev = wl_to_prmry_ndev(wl);
+ struct wiphy *wiphy = wl_to_wiphy(wl);
+ struct wl_bss_info *bi = NULL;
+ struct ieee80211_channel *notify_channel;
+ struct ieee80211_supported_band *band;
+ struct cfg80211_bss *bss;
+ s32 err = 0;
+ u16 channel;
+ u32 freq;
+ u32 wsec = 0;
+ u16 notify_capability;
+ u16 notify_interval;
+ u8 *notify_ie;
+ size_t notify_ielen;
+ s32 notify_signal;
+
+ WL_TRACE(("Enter\n"));
+
+ if (wl->scan_request) {
+ wl_notify_escan_complete(wl, ndev, true, true);
+ }
+
+ mutex_lock(&wl->usr_sync);
+
+ *(u32 *)wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
+ err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, wl->extra_buf,
+ WL_EXTRA_BUF_MAX, false);
+ if (err) {
+ WL_ERR(("Failed to get bss info for IBSS\n"));
+ err = -EIO;
+ goto CleanUp;
+ }
+ bi = (struct wl_bss_info *)(wl->extra_buf + 4);
+
+ if (memcmp(bssid, &bi->BSSID, ETHER_ADDR_LEN)) {
+ WL_ERR(("BSSID mismatch: Inform %02x:%02x:%02x:%02x:%02x:%02x,"
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5],
+ bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2],
+ bi->BSSID.octet[3], bi->BSSID.octet[4],
+ bi->BSSID.octet[5]));
+ err = -EINVAL;
+ goto CleanUp;
+ }
+
+ err = wldev_iovar_getint(ndev, "wsec", &wsec);
+ if (err) {
+ WL_ERR(("wsec failed: %d\n", err));
+ err = -EIO;
+ goto CleanUp;
+ }
+
+ channel = bi->ctl_ch ? bi->ctl_ch :
+ CHSPEC_CHANNEL(dtohchanspec(bi->chanspec));
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
+ freq = ieee80211_channel_to_frequency(channel);
+ (void)band->band;
+#else
+ freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif
+ notify_channel = ieee80211_get_channel(wiphy, freq);
+
+ notify_capability = dtoh16(bi->capability);
+ notify_interval = dtoh16(bi->beacon_period);
+ notify_ie = (u8 *)bi + dtoh16(bi->ie_offset);
+ notify_ielen = dtoh32(bi->ie_length);
+ notify_signal = (int16)dtoh16(bi->RSSI) * 100;
+
+ if (wl->p2p_supported) {
+ notify_capability |= DOT11_CAP_IBSS;
+ if (wsec)
+ notify_capability |= DOT11_CAP_PRIVACY;
+ }
+
+ WL_DBG(("BSSID %02x:%02x:%02x:%02x:%02x:%02x",
+ bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]));
+ WL_INFO(("channel: %d(%d)\n", channel, freq));
+ WL_INFO(("capability: %X\n", notify_capability));
+ WL_INFO(("beacon interval: %d ms\n", notify_interval));
+ WL_INFO(("signal: %d dBm\n", notify_signal));
+ WL_INFO(("ie_len: %d\n", notify_ielen));
+ bss = cfg80211_inform_bss(wiphy, notify_channel, bssid, 0,
+ notify_capability, notify_interval,
+ notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
+ if (!bss) {
+ WL_ERR(("cfg80211_inform_bss() Failed\n"));
+ err = -ENOMEM;
+ goto CleanUp;
+ }
+
+ cfg80211_put_bss(bss);
+ err = 0;
+
+CleanUp:
+
+ mutex_unlock(&wl->usr_sync);
+
+ WL_TRACE(("Exit\n"));
+ return err;
+}
+
static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev)
{
u32 event = ntoh32(e->event_type);
@@ -4648,12 +4931,12 @@ static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net
WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
if (event == WLC_E_SET_SSID) {
if (status == WLC_E_STATUS_SUCCESS) {
- if (!wl_is_ibssmode(wl, ndev))
- return true;
+ return true;
}
} else if (event == WLC_E_LINK) {
if (flags & WLC_EVENT_MSG_LINK)
- return true;
+ if (!wl_is_ibssmode(wl, ndev))
+ return true;
}
WL_DBG(("wl_is_linkup false\n"));
@@ -4834,7 +5117,9 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
if((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DISASSOC_IND)) {
reason = ntoh32(e->reason);
wl->deauth_reason = reason;
- WL_ERR(("Received %s event with reason code: %d\n", (event == WLC_E_DEAUTH_IND)? "WLC_E_DEAUTH_IND":"WLC_E_DISASSOC_IND", reason));
+ WL_ERR(("Received %s event with reason code: %d\n",
+ (event == WLC_E_DEAUTH_IND)?
+ "WLC_E_DEAUTH_IND":"WLC_E_DISASSOC_IND", reason));
}
if (wl_is_linkup(wl, e, ndev)) {
wl_link_up(wl);
@@ -4843,10 +5128,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
wl->deauth_reason = 0;
if (wl_is_ibssmode(wl, ndev)) {
- printk("cfg80211_ibss_joined\n");
- cfg80211_ibss_joined(ndev, (s8 *)&e->addr,
- GFP_KERNEL);
- WL_DBG(("joined in IBSS network\n"));
+ wl_ibss_join_done(wl, ndev, e, data, true);
+ WL_DBG(("wl_ibss_join_done succeeded\n"));
} else {
if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) {
printk("wl_bss_connect_done succeeded\n");
@@ -4856,7 +5139,6 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID));
}
}
-
} else if (wl_is_linkdown(wl, e)) {
if (wl->scan_request) {
if (wl->escan_on) {
@@ -4880,15 +5162,21 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
scbval.val = htod32(scbval.val);
wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
sizeof(scb_val_t), true);
- WL_ERR(("link down, calling cfg80211_disconnected with deauth_reason:%d\n", wl->deauth_reason));
- cfg80211_disconnected(ndev, wl->deauth_reason , NULL, 0, GFP_KERNEL);
+ WL_ERR(("link down, calling cfg80211_disconnected"
+ " with deauth_reason:%d\n", wl->deauth_reason));
+ if (!wl_is_ibssmode(wl, ndev))
+ cfg80211_disconnected(ndev, wl->deauth_reason,
+ NULL, 0, GFP_KERNEL);
wl_link_down(wl);
wl_init_prof(wl, ndev);
}
}
else if (wl_get_drv_status(wl, CONNECTING, ndev)) {
printk("link down, during connecting\n");
- wl_bss_connect_done(wl, ndev, e, data, false);
+ if (wl_is_ibssmode(wl, ndev))
+ wl_ibss_join_done(wl, ndev, e, data, false);
+ else
+ wl_bss_connect_done(wl, ndev, e, data, false);
}
wl_clr_drv_status(wl, DISCONNECTING, ndev);
@@ -5184,6 +5472,35 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
}
static s32
+wl_ibss_join_done(struct wl_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data, bool completed)
+{
+ s32 err = 0;
+
+ WL_TRACE(("Enter\n"));
+
+ if (wl->scan_request) {
+ wl_notify_escan_complete(wl, ndev, true, true);
+ }
+ if (wl_get_drv_status(wl, CONNECTING, ndev)) {
+ wl_clr_drv_status(wl, CONNECTING, ndev);
+ if (completed) {
+ err = wl_inform_ibss(wl, (u8 *)&e->addr);
+ if (err) {
+ WL_ERR(("wl_inform_ibss() failed: %d\n", err));
+ }
+ wl_set_drv_status(wl, CONNECTED, ndev);
+
+ cfg80211_ibss_joined(ndev, (u8 *)&e->addr, GFP_KERNEL);
+ WL_DBG(("cfg80211_ibss_joined() called with valid BSSID\n"));
+ }
+ }
+
+ WL_TRACE(("Exit\n"));
+ return err;
+}
+
+static s32
wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
const wl_event_msg_t *e, void *data)
{
@@ -5365,6 +5682,13 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
WL_ERR(("No valid band"));
return -EINVAL;
}
+
+ if ((event == WLC_E_P2P_PROBREQ_MSG) &&
+ wl->p2p && wl_get_p2p_status(wl, GO_NEG_PHASE)) {
+ WL_DBG(("Filtering P2P probe_req while being in GO-Neg state\n"));
+ goto exit;
+ }
+
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
freq = ieee80211_channel_to_frequency(channel);
#else
@@ -5409,6 +5733,11 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
(act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
wldev_iovar_setint(dev, "mpc", 1);
}
+
+ if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
+ WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
+ wl_clr_p2p_status(wl, GO_NEG_PHASE);
+ }
} else {
mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
}
@@ -6044,7 +6373,7 @@ static s32 wl_escan_handler(struct wl_priv *wl,
wl_scan_results_t *list;
u32 bi_length;
u32 i;
-
+ u8 *p2p_dev_addr = NULL;
WL_DBG((" enter event type : %d, status : %d \n",
ntoh32(e->event_type), ntoh32(e->status)));
/* P2P SCAN is coming from primary interface */
@@ -6086,16 +6415,18 @@ static s32 wl_escan_handler(struct wl_priv *wl,
if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
- WL_ERR(("Ignoring IBSS result\n"));
+ WL_DBG(("Ignoring IBSS result\n"));
goto exit;
}
}
if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
- if (!memcmp(bi->BSSID.octet,
+ p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
+ if (p2p_dev_addr && !memcmp(p2p_dev_addr,
wl->afx_hdl->pending_tx_dst_addr.octet, ETHER_ADDR_LEN)) {
s32 channel = CHSPEC_CHANNEL(dtohchanspec(bi->chanspec));
- WL_DBG(("ACTION FRAME SCAN : Peer found, channel : %d\n", channel));
+ WL_DBG(("ACTION FRAME SCAN : Peer " MACSTR " found, channel : %d\n",
+ MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), channel));
wl_clr_p2p_status(wl, SCANNING);
wl->afx_hdl->peer_chan = channel;
complete(&wl->act_frm_scan);
@@ -6721,20 +7052,148 @@ eventmsg_out:
}
+static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap)
+{
+ struct net_device *dev = wl_to_prmry_ndev(wl);
+ struct ieee80211_channel *band_chan_arr = NULL;
+ wl_uint32_list_t *list;
+ u32 i, j, index, n_2g, n_5g, band, channel, array_size;
+ u32 *n_cnt = NULL;
+ chanspec_t c = 0;
+ s32 err = BCME_OK;
+ bool update;
+ bool ht40_allowed;
+ u8 *pbuf = NULL;
+
+#define LOCAL_BUF_LEN 1024
+ pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
+ if (pbuf == NULL) {
+ WL_ERR(("failed to allocate local buf\n"));
+ return -ENOMEM;
+ }
+
+ list = (wl_uint32_list_t *)(void *)pbuf;
+ list->count = htod32(WL_NUMCHANSPECS);
+
+ err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
+ 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync);
+ if (err != 0) {
+ WL_ERR(("get chanspecs failed with %d\n", err));
+ kfree(pbuf);
+ return err;
+ }
+#undef LOCAL_BUF_LEN
+
+ band = array_size = n_2g = n_5g = 0;
+ for (i = 0; i < dtoh32(list->count); i++) {
+ index = 0;
+ update = FALSE;
+ ht40_allowed = FALSE;
+ c = (chanspec_t)dtoh32(list->element[i]);
+ channel = CHSPEC_CHANNEL(c);
+ if (CHSPEC_IS40(c)) {
+ if (CHSPEC_SB_UPPER(c))
+ channel += CH_10MHZ_APART;
+ else
+ channel -= CH_10MHZ_APART;
+ }
+
+ if (CHSPEC_IS2G(c) && channel <= CH_MAX_2G_CHANNEL) {
+ band_chan_arr = __wl_2ghz_channels;
+ array_size = ARRAYSIZE(__wl_2ghz_channels);
+ n_cnt = &n_2g;
+ band = IEEE80211_BAND_2GHZ;
+ ht40_allowed = (bw_cap == WLC_N_BW_40ALL) ? TRUE : FALSE;
+ } else if (CHSPEC_IS5G(c) && channel > CH_MAX_2G_CHANNEL) {
+ band_chan_arr = __wl_5ghz_a_channels;
+ array_size = ARRAYSIZE(__wl_5ghz_a_channels);
+ n_cnt = &n_5g;
+ band = IEEE80211_BAND_5GHZ;
+ ht40_allowed = (bw_cap == WLC_N_BW_20ALL) ? FALSE : TRUE;
+ }
+
+ for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
+ if (band_chan_arr[j].hw_value == channel) {
+ update = TRUE;
+ break;
+ }
+ }
+
+ if (update)
+ index = j;
+ else
+ index = *n_cnt;
+
+ if (index < array_size) {
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
+ band_chan_arr[index].center_freq =
+ ieee80211_channel_to_frequency(channel);
+#else
+ band_chan_arr[index].center_freq =
+ ieee80211_channel_to_frequency(channel, band);
+#endif
+ band_chan_arr[index].hw_value = channel;
+
+ if (CHSPEC_IS40(c) && ht40_allowed) {
+ u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
+ if (CHSPEC_SB_UPPER(c)) {
+ if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+ band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
+ band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
+ } else {
+ band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
+ if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+ band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40MINUS;
+ }
+ } else {
+ band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
+ if (band == IEEE80211_BAND_2GHZ)
+ channel |= WL_CHANSPEC_BAND_2G;
+ else
+ channel |= WL_CHANSPEC_BAND_5G;
+ err = wldev_iovar_getint(dev, "per_chan_info", &channel);
+ if (!err) {
+ if (channel & WL_CHAN_RADAR) {
+ band_chan_arr[index].flags |= IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS;
+ }
+ if (channel & WL_CHAN_PASSIVE) {
+ band_chan_arr[index].flags |= IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS;
+ }
+ }
+ }
+
+ if (!update)
+ (*n_cnt)++;
+ }
+ }
+
+ __wl_band_2ghz.n_channels = n_2g;
+ __wl_band_5ghz_a.n_channels = n_5g;
+
+ kfree(pbuf);
+ return err;
+}
+
s32 wl_update_wiphybands(struct wl_priv *wl)
{
struct wiphy *wiphy;
+ struct net_device *dev;
u32 bandlist[3];
u32 nband = 0;
u32 i = 0;
s32 err = 0;
int nmode = 0;
- int bw_40 = 0;
+ int bw_cap = 0;
int index = 0;
WL_DBG(("Entry"));
+
+ if (wl == NULL)
+ wl = wlcfg_drv_priv;
+ dev = wl_to_prmry_ndev(wl);
+
memset(bandlist, 0, sizeof(bandlist));
- err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BANDLIST, bandlist,
+ err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
sizeof(bandlist), false);
if (unlikely(err)) {
WL_ERR(("error read bandlist (%d)\n", err));
@@ -6745,41 +7204,44 @@ s32 wl_update_wiphybands(struct wl_priv *wl)
wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
- err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "nmode", &nmode);
+ err = wldev_iovar_getint(dev, "nmode", &nmode);
if (unlikely(err)) {
WL_ERR(("error reading nmode (%d)\n", err));
- }
- else {
+ } else {
/* For nmodeonly check bw cap */
- err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "mimo_bw_cap", &bw_40);
+ err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
if (unlikely(err)) {
WL_ERR(("error get mimo_bw_cap (%d)\n", err));
}
}
+ err = wl_construct_reginfo(wl, bw_cap);
+ if (err) {
+ WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
+ return err;
+ }
for (i = 1; i <= nband && i < sizeof(bandlist)/sizeof(u32); i++) {
index = -1;
- if (bandlist[i] == WLC_BAND_5G) {
+ if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
wiphy->bands[IEEE80211_BAND_5GHZ] =
&__wl_band_5ghz_a;
- index = IEEE80211_BAND_5GHZ;
- } else if (bandlist[i] == WLC_BAND_2G) {
+ index = IEEE80211_BAND_5GHZ;
+ if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G)
+ wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+ } else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
wiphy->bands[IEEE80211_BAND_2GHZ] =
&__wl_band_2ghz;
- index = IEEE80211_BAND_2GHZ;
+ index = IEEE80211_BAND_2GHZ;
+ if (bandlist[i] == WLC_BAND_2G && bw_cap == WLC_N_BW_40ALL)
+ wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
}
if ((index >= 0) && nmode) {
- wiphy->bands[index]->ht_cap.cap =
- IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 |
- IEEE80211_HT_CAP_MAX_AMSDU;
+ wiphy->bands[index]->ht_cap.cap |=
+ IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40;
wiphy->bands[index]->ht_cap.ht_supported = TRUE;
wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
}
-
- if ((index >= 0) && bw_40) {
- wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
- }
}
wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
@@ -7106,8 +7568,7 @@ static void wl_init_eq_lock(struct wl_priv *wl)
static void wl_delay(u32 ms)
{
- if (ms < 1000 / HZ) {
- cond_resched();
+ if (in_atomic() || ms < 1000 / HZ) {
mdelay(ms);
} else {
msleep(ms);
@@ -7162,17 +7623,44 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
{
struct wl_priv *wl;
struct net_device *ndev = NULL;
+ struct ether_addr primary_mac;
s32 ret = 0;
s32 bssidx = 0;
s32 pktflag = 0;
wl = wlcfg_drv_priv;
- if (wl->p2p && wl->p2p->vif_created) {
- ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
- bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
- } else if (wl_get_drv_status(wl, AP_CREATING, net) ||
+
+ if (wl_get_drv_status(wl, AP_CREATING, net) ||
wl_get_drv_status(wl, AP_CREATED, net)) {
ndev = net;
bssidx = 0;
+ } else if (wl->p2p) {
+ if (net == wl->p2p_net) {
+ net = wl_to_prmry_ndev(wl);
+ }
+
+ if (!wl->p2p->on) {
+ get_primary_mac(wl, &primary_mac);
+ wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr,
+ &wl->p2p->int_addr);
+ /* In case of p2p_listen command, supplicant send remain_on_channel
+ * without turning on P2P
+ */
+ p2p_on(wl) = true;
+ ret = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0);
+
+ if (unlikely(ret)) {
+ goto exit;
+ }
+ }
+ if (net != wl_to_prmry_ndev(wl)) {
+ if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) {
+ ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
+ bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
+ }
+ } else {
+ ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
+ bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
+ }
}
if (ndev != NULL) {
switch (type) {
@@ -7189,7 +7677,7 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
if (pktflag)
ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
}
-
+exit:
return ret;
}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index fba853149c35..21446dc10708 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -136,6 +136,12 @@ do { \
#define WL_INVALID -1
+
+/* Bring down SCB Timeout to 20secs from 60secs default */
+#ifndef WL_SCB_TIMEOUT
+#define WL_SCB_TIMEOUT 20
+#endif
+
/* driver status */
enum wl_status {
WL_STATUS_READY = 0,
@@ -606,7 +612,6 @@ wl_get_profile_by_netdev(struct wl_priv *wl, struct net_device *ndev)
#define iscan_to_wl(i) ((struct wl_priv *)(i->data))
#define wl_to_iscan(w) (w->iscan)
#define wl_to_conn(w) (&w->conn_info)
-#define wiphy_from_scan(w) (w->escan_info.wiphy)
#define wl_get_drv_status_all(wl, stat) \
(wl_get_status_all(wl, WL_STATUS_ ## stat))
#define wl_get_drv_status(wl, stat, ndev) \
@@ -662,5 +667,6 @@ extern int wl_cfg80211_hang(struct net_device *dev, u16 reason);
extern s32 wl_mode_to_nl80211_iftype(s32 mode);
int wl_cfg80211_do_driver_init(struct net_device *net);
void wl_cfg80211_enable_trace(int level);
+extern s32 wl_update_wiphybands(struct wl_priv *wl);
extern s32 wl_cfg80211_if_is_group_owner(void);
#endif /* _wl_cfg80211_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index a34c4ad17c25..318e122004e7 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -59,6 +59,8 @@ static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev);
static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd);
static int wl_cfgp2p_if_open(struct net_device *net);
static int wl_cfgp2p_if_stop(struct net_device *net);
+static s32 wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev,
+ bool notify);
static const struct net_device_ops wl_cfgp2p_if_ops = {
.ndo_open = wl_cfgp2p_if_open,
@@ -338,6 +340,7 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
wl_p2p_if_t ifreq;
s32 err;
struct net_device *ndev = wl_to_prmry_ndev(wl);
+ u32 scb_timeout = WL_SCB_TIMEOUT;
ifreq.type = if_type;
ifreq.chspec = chspec;
@@ -351,6 +354,15 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
+
+ if (unlikely(err < 0)) {
+ printk("'wl p2p_ifadd' error %d\n", err);
+ } else if (if_type == WL_P2P_IF_GO) {
+ err = wldev_ioctl(ndev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
+ if (unlikely(err < 0))
+ printk("'wl scb_timeout' error %d\n", err);
+ }
+
return err;
}
@@ -387,6 +399,7 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
{
wl_p2p_if_t ifreq;
s32 err;
+ u32 scb_timeout = WL_SCB_TIMEOUT;
struct net_device *netdev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
ifreq.type = if_type;
@@ -404,6 +417,10 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
if (unlikely(err < 0)) {
printk("'wl p2p_ifupd' error %d\n", err);
+ } else if (if_type == WL_P2P_IF_GO) {
+ err = wldev_ioctl(netdev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
+ if (unlikely(err < 0))
+ printk("'wl scb_timeout' error %d\n", err);
}
return err;
}
@@ -829,10 +846,12 @@ exit:
/* Check whether the given IE looks like WFA P2P IE. */
#define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
-/* Check whether the given IE looks like WFA WFDisplay IE. */
-#define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */
-#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
- (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
+#ifdef WLWFDIE
+ /* Check whether the given IE looks like WFA WFDisplay IE. */
+#define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */
+#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
+ (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
+#endif /* WLWFDIE */
/* Delete and Set a management vndr ie to firmware
* Parameters:
* @wl : wl_private data
@@ -957,8 +976,12 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
ie_len = ie_buf[pos++];
if ((ie_id == DOT11_MNG_VS_ID) &&
(wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
+#ifdef WLWFDIE
wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) ||
wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) {
+#else
+ wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+#endif /* WLWFDIE */
CFGP2P_INFO(("DELELED ID : %d, Len : %d , OUI :"
"%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
ie_buf[pos+1], ie_buf[pos+2]));
@@ -984,8 +1007,12 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
ie_len = ie_buf[pos++];
if ((ie_id == DOT11_MNG_VS_ID) &&
(wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
+#ifdef WLWFDIE
wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) ||
wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) {
+#else
+ wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+#endif /* WLWFDIE */
CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :"
"%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
ie_buf[pos+1], ie_buf[pos+2]));
@@ -1095,18 +1122,21 @@ wl_cfgp2p_find_p2pie(u8 *parse, u32 len)
}
return NULL;
}
+
+#ifdef WLWFDIE
wifi_wfd_ie_t *
wl_cfgp2p_find_wfdie(u8 *parse, u32 len)
{
bcm_tlv_t *ie;
while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
- if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
+ if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
return (wifi_wfd_ie_t *)ie;
}
}
return NULL;
}
+#endif /* WLWFDIE */
static s32
wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag,
@@ -1230,6 +1260,7 @@ wl_cfgp2p_listen_expired(unsigned long data)
struct wl_priv *wl = (struct wl_priv *) data;
CFGP2P_DBG((" Enter\n"));
+ memset(&msg, 0, sizeof(wl_event_msg_t));
msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
wl_cfg80211_event(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL);
}
@@ -1237,7 +1268,7 @@ wl_cfgp2p_listen_expired(unsigned long data)
/*
* Routine for cancelling the P2P LISTEN
*/
-s32
+static s32
wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev,
bool notify)
{
@@ -1402,13 +1433,12 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
if (ret < 0) {
-
CFGP2P_ERR((" sending action frame is failed\n"));
goto exit;
}
timeout = wait_event_interruptible_timeout(wl->netif_change_event,
- (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)),
- msecs_to_jiffies(MAX_WAIT_TIME));
+ (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)),
+ msecs_to_jiffies(MAX_WAIT_TIME));
if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) {
CFGP2P_INFO(("tx action frame operation is completed\n"));
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
index 668198d31a2e..40d9e5463fe0 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
@@ -30,7 +30,11 @@
struct wl_priv;
extern u32 wl_dbg_level;
+
+#ifdef WLWFDIE
typedef struct wifi_p2p_ie wifi_wfd_ie_t;
+#endif /* WLWFDIE */
+
/* Enumeration of the usages of the BSSCFGs used by the P2P Library. Do not
* confuse this with a bsscfg index. This value is an index into the
* saved_ie[] array of structures which in turn contains a bsscfg index field.
@@ -42,7 +46,7 @@ typedef enum {
P2PAPI_BSSCFG_MAX
} p2p_bsscfg_type_t;
-#define IE_MAX_LEN 300
+#define IE_MAX_LEN 512
/* Structure to hold all saved P2P and WPS IEs for a BSSCFG */
struct p2p_saved_ie {
u8 p2p_probe_req_ie[IE_MAX_LEN];
@@ -91,7 +95,8 @@ enum wl_cfgp2p_status {
WLP2P_STATUS_LISTEN_EXPIRED,
WLP2P_STATUS_ACTION_TX_COMPLETED,
WLP2P_STATUS_ACTION_TX_NOACK,
- WLP2P_STATUS_SCANNING
+ WLP2P_STATUS_SCANNING,
+ WLP2P_STATUS_GO_NEG_PHASE
};
@@ -191,8 +196,10 @@ wl_cfgp2p_find_wpsie(u8 *parse, u32 len);
extern wifi_p2p_ie_t *
wl_cfgp2p_find_p2pie(u8 *parse, u32 len);
+#ifdef WLWFDIE
extern wifi_wfd_ie_t *
wl_cfgp2p_find_wfdie(u8 *parse, u32 len);
+#endif /* WLWFDIE */
extern s32
wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx,
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c
index 059929340354..6bb07650b27e 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.c
+++ b/drivers/net/wireless/bcmdhd/wl_iw.c
@@ -6341,6 +6341,7 @@ wl_iw_set_cscan(
else {
WL_ERROR(("%s Ignoring CSCAN : First Scan is not done yet %d\n",
__FUNCTION__, g_first_counter_scans));
+ res = -EBUSY;
goto exit_proc;
}
}
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b7ceb3f858c6..35dfc506b984 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -43,4 +43,5 @@ obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
obj-$(CONFIG_MAX8907C_CHARGER) += max8907c-charger.o
+CFLAGS_tegra_bpc_mgmt.o = -Werror
obj-$(CONFIG_TEGRA_BPC_MGMT) += tegra_bpc_mgmt.o
diff --git a/drivers/power/max17048_battery.c b/drivers/power/max17048_battery.c
index c65855f72dba..ba3d6440ab3d 100644
--- a/drivers/power/max17048_battery.c
+++ b/drivers/power/max17048_battery.c
@@ -221,10 +221,11 @@ static void max17048_work(struct work_struct *work)
if (chip->vcell != chip->lasttime_vcell ||
chip->soc != chip->lasttime_soc ||
- chip->status != chip->lasttime_status) {
+ chip->status != chip->lasttime_status) {
chip->lasttime_vcell = chip->vcell;
chip->lasttime_soc = chip->soc;
+ chip->lasttime_status = chip->status;
power_supply_changed(&chip->battery);
}
@@ -239,14 +240,13 @@ static void max17048_battery_status(enum charging_states status,
chip->ac_online = 0;
chip->usb_online = 0;
- if (chrg_type == AC)
- chip->ac_online = 1;
- else if (chrg_type == USB)
- chip->usb_online = 1;
-
- if (status == progress)
+ if (status == progress) {
chip->status = POWER_SUPPLY_STATUS_CHARGING;
- else
+ if (chrg_type == AC)
+ chip->ac_online = 1;
+ else if (chrg_type == USB)
+ chip->usb_online = 1;
+ } else
chip->status = POWER_SUPPLY_STATUS_DISCHARGING;
@@ -592,7 +592,9 @@ static int max17048_resume(struct i2c_client *client)
return ret;
}
- schedule_delayed_work(&chip->work, MAX17048_DELAY);
+ update_charger_status();
+
+ schedule_work(&chip->work);
return 0;
}
diff --git a/drivers/power/smb349-charger.c b/drivers/power/smb349-charger.c
index 134b8154a2b9..c6dc43158b82 100644
--- a/drivers/power/smb349-charger.c
+++ b/drivers/power/smb349-charger.c
@@ -406,6 +406,19 @@ static int smb349_enable_charging(struct regulator_dev *rdev,
int ret;
if (!max_uA) {
+ /* Wait for SMB349 to debounce and get reset to POR when cable is unpluged */
+ msleep(50);
+
+ ret = smb349_read(client, SMB349_STS_REG_C);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s(): Failed in reading register"
+ "0x%02x\n", __func__, SMB349_STS_REG_C);
+ return ret;
+ }
+
+ if (ret & CHARGING)
+ return 0;
+
charger->state = stopped;
charger->chrg_type = NONE;
} else {
diff --git a/drivers/power/tps80031-charger.c b/drivers/power/tps80031-charger.c
index 93b283e0b04f..9190b7201fd6 100644
--- a/drivers/power/tps80031-charger.c
+++ b/drivers/power/tps80031-charger.c
@@ -3,7 +3,7 @@
*
* Battery charger driver for TI's tps80031
*
- * Copyright (c) 2011, NVIDIA Corporation.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -65,18 +65,41 @@ struct tps80031_charger {
};
static struct tps80031_charger *charger_data;
-static uint8_t charging_current_val_code[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0x27,
- 0x37, 0x28, 0x38, 0x29, 0x39, 0x2A, 0x3A, 0x2B, 0x3B, 0x2C,
- 0x3C, 0x2D, 0x3D, 0x2E,
+
+static uint8_t tps80031_get_vbus_input_current_limit_code(int max_uA)
+{
+ const uint8_t current_to_code[] = {
+ 0x0, /* 0 - 50 mA */
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, /* 50, 100, ..., 300mA */
+ 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, /* 350, 400, ..., 600mA */
+ 0xC, 0xD, 0xE, 0x27, 0x37, 0x28, /* 650, 700, ..., 900mA */
+ 0x38, 0x29, 0x39, 0x2A, 0x3A, 0x2B, /* 950, 700, ..., 1200mA */
+ 0x3B, 0x2C, 0x3C, 0x2D, 0x3D, 0x2E, /* 1200,1250, ..., 1500mA */
+ };
+ int charge_mA;
+ uint8_t code;
+
+ charge_mA = max_uA / 1000;
+ if (charge_mA < 0)
+ BUG();
+ else if (charge_mA < 1800)
+ code = current_to_code[charge_mA / 50];
+ else if (charge_mA < 2100)
+ code = 0x20; /* use 1800mA code */
+ else if (charge_mA < 2250)
+ code = 0x21; /* use 2100mA code */
+ else
+ code = 0x22; /* use 2250mA code */
+
+ return code;
};
static int set_charge_current_limit(struct regulator_dev *rdev,
int min_uA, int max_uA)
{
struct tps80031_charger *charger = rdev_get_drvdata(rdev);
- int max_vbus_current = 1500;
int max_charge_current = 1500;
+ uint8_t code;
int ret;
dev_info(charger->dev, "%s(): Min curr %dmA and max current %dmA\n",
@@ -101,13 +124,9 @@ static int set_charge_current_limit(struct regulator_dev *rdev,
return ret;
}
- max_vbus_current = min(max_uA/1000, max_vbus_current);
- max_vbus_current = max_vbus_current/50;
- if (max_vbus_current)
- max_vbus_current--;
+ code = tps80031_get_vbus_input_current_limit_code(max_uA);
ret = tps80031_update(charger->dev->parent, SLAVE_ID2,
- CHARGERUSB_CINLIMIT,
- charging_current_val_code[max_vbus_current], 0x3F);
+ CHARGERUSB_CINLIMIT, code, 0x3F);
if (ret < 0) {
dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
__func__, CHARGERUSB_CINLIMIT);
@@ -250,7 +269,8 @@ static int configure_charging_parameter(struct tps80031_charger *charger)
}
/* set Pre Charge current to 400mA */
- ret = tps80031_write(charger->dev->parent, SLAVE_ID2, 0xDE, 0x3);
+ ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
+ CHARGERUSB_VICHRG_PC, 0x3);
if (ret < 0) {
dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
__func__, 0xDD);
@@ -274,27 +294,41 @@ static int configure_charging_parameter(struct tps80031_charger *charger)
return 0;
}
-static irqreturn_t linch_status_isr(int irq, void *dev_id)
+static bool tps80031_check_charging_completed(struct tps80031_charger *charger)
{
- struct tps80031_charger *charger = dev_id;
- uint8_t linch_status;
int ret;
- dev_info(charger->dev, "%s() got called\n", __func__);
+ uint8_t linch_status;
ret = tps80031_read(charger->dev->parent, SLAVE_ID2,
LINEAR_CHRG_STS, &linch_status);
if (ret < 0) {
dev_err(charger->dev, "%s(): Failed in reading register 0x%02x\n",
__func__, LINEAR_CHRG_STS);
+ return false;
+ }
+
+ if (linch_status & 0x20) {
+ charger->state = charging_state_charging_completed;
+ ret = true;
} else {
- dev_info(charger->dev, "%s():The status of LINEAR_CHRG_STS is 0x%02x\n",
- __func__, linch_status);
- if (linch_status & 0x20) {
- charger->state = charging_state_charging_completed;
- if (charger->charger_cb)
- charger->charger_cb(charger->state,
+ charger->state = charging_state_charging_in_progress;
+ ret = false;
+ }
+
+ return ret;
+}
+
+static irqreturn_t linch_status_isr(int irq, void *dev_id)
+{
+ struct tps80031_charger *charger = dev_id;
+
+ dev_info(charger->dev, "%s() got called\n", __func__);
+
+ if (tps80031_check_charging_completed(charger)) {
+ charger->state = charging_state_charging_completed;
+ if (charger->charger_cb)
+ charger->charger_cb(charger->state,
charger->charger_cb_data);
- }
}
return IRQ_HANDLED;
@@ -306,8 +340,22 @@ static irqreturn_t watchdog_expire_isr(int irq, void *dev_id)
int ret;
dev_info(charger->dev, "%s()\n", __func__);
- if (charger->state != charging_state_charging_in_progress)
- return IRQ_HANDLED;
+ if (charger->state != charging_state_charging_in_progress) {
+ /*
+ * After the charge completed, the chip can enable the
+ * charging again if battery voltage is 120mV below the
+ * charging voltage (defined by VOREG register).
+ */
+ if (tps80031_check_charging_completed(charger)) {
+ return IRQ_HANDLED;
+ } else {
+ /* "recharging" after charging completed happened */
+ charger->state = charging_state_charging_in_progress;
+ if (charger->charger_cb)
+ charger->charger_cb(charger->state,
+ charger->charger_cb_data);
+ }
+ }
/* Enable watchdog timer again*/
ret = tps80031_write(charger->dev->parent, SLAVE_ID2, CONTROLLER_WDG,
@@ -333,10 +381,18 @@ static int tps80031_charger_probe(struct platform_device *pdev)
int ret = 0;
struct device *dev = &pdev->dev;
struct tps80031_charger *charger;
- struct tps80031_charger_platform_data *pdata = pdev->dev.platform_data;
+ struct tps80031_platform_data *tps80031_pdata;
+ struct tps80031_charger_platform_data *pdata;
dev_info(dev, "%s()\n", __func__);
+ tps80031_pdata = dev_get_platdata(pdev->dev.parent);
+ if (!tps80031_pdata) {
+ dev_err(&pdev->dev, "no tps80031 platform_data specified\n");
+ return -EINVAL;
+ }
+
+ pdata = tps80031_pdata->battery_charger_pdata;
if (!pdata) {
dev_err(dev, "%s() No platform data, exiting..\n", __func__);
return -ENODEV;
diff --git a/drivers/power/tps80031_battery_gauge.c b/drivers/power/tps80031_battery_gauge.c
index 9ccfaad41441..f339b41cf039 100644
--- a/drivers/power/tps80031_battery_gauge.c
+++ b/drivers/power/tps80031_battery_gauge.c
@@ -433,6 +433,8 @@ void tps80031_battery_status(enum charging_states status, void *data)
di->usb_status = POWER_SUPPLY_STATUS_DISCHARGING;
di->ac_online = 0;
di->usb_online = 0;
+ } else if (status == charging_state_charging_completed) {
+ di->usb_status = POWER_SUPPLY_STATUS_FULL;
}
power_supply_changed(&di->usb);
power_supply_changed(&di->bat);
@@ -453,7 +455,20 @@ static int tps80031_battery_probe(struct platform_device *pdev)
uint8_t retval;
struct device *dev = &pdev->dev;
struct tps80031_device_info *di;
- struct tps80031_bg_platform_data *pdata = pdev->dev.platform_data;
+ struct tps80031_platform_data *tps80031_pdata;
+ struct tps80031_bg_platform_data *pdata;
+
+ tps80031_pdata = dev_get_platdata(pdev->dev.parent);
+ if (!tps80031_pdata) {
+ dev_err(&pdev->dev, "no tps80031 platform_data specified\n");
+ return -EINVAL;
+ }
+
+ pdata = tps80031_pdata->bg_pdata;
+ if (!pdata) {
+ dev_err(&pdev->dev, "no battery_gauge platform data\n");
+ return -EINVAL;
+ }
di = devm_kzalloc(&pdev->dev, sizeof *di, GFP_KERNEL);
if (!di) {
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 28c58a1c19b1..88d36153ec70 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -332,12 +332,28 @@ config REGULATOR_DB8500_PRCMU
This driver supports the voltage domain regulators controlled by the
DB8500 PRCMU
+config REGULATOR_TPS51632
+ tristate "TI TPS51632 Power Regulator"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ This driver supports TPS51632 voltage regulator chip.
+ The TPS52632 is 3-2-1 Phase D-Cap+ Step Down Driverless Controller
+ with Serial VID control and DVFS.
+
config REGULATOR_TPS6586X
tristate "TI TPS6586X Power regulators"
depends on MFD_TPS6586X
help
This driver supports TPS6586X voltage regulator chips.
+config REGULATOR_TPS65090
+ tristate "TI TPS65090 Power regulator"
+ depends on MFD_TPS65090
+ help
+ This driver provides support for the voltage regulators on the
+ TI TPS65090 PMIC.
+
config REGULATOR_TPS6524X
tristate "TI TPS6524X Power regulators"
depends on SPI
@@ -388,12 +404,6 @@ config REGULATOR_TPS6591X
help
This driver supports TPS6591X voltage regulator chips.
-config REGULATOR_TPS65090
- tristate "TI TPS65090 Power regulators"
- depends on MFD_TPS65090
- help
- This driver supports TPS65090 voltage regulator chips.
-
config REGULATOR_TPS80031
tristate "TI TPS80031 Power regulators"
depends on MFD_TPS80031
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index a25ff34afcbc..4265ea06992c 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
+obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index cbe36b93639b..26f8776f8eee 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2654,6 +2654,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
static atomic_t regulator_no = ATOMIC_INIT(0);
struct regulator_dev *rdev;
int ret, i;
+ const char *supply = NULL;
if (regulator_desc == NULL)
return ERR_PTR(-EINVAL);
@@ -2728,21 +2729,24 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
if (ret < 0)
goto scrub;
- if (init_data->supply_regulator) {
+ if (init_data->supply_regulator)
+ supply = init_data->supply_regulator;
+ else if (regulator_desc->supply_name)
+ supply = regulator_desc->supply_name;
+
+ if (supply) {
struct regulator_dev *r;
int found = 0;
list_for_each_entry(r, &regulator_list, list) {
- if (strcmp(rdev_get_name(r),
- init_data->supply_regulator) == 0) {
+ if (strcmp(rdev_get_name(r), supply) == 0) {
found = 1;
break;
}
}
if (!found) {
- dev_err(dev, "Failed to find supply %s\n",
- init_data->supply_regulator);
+ dev_err(dev, "Failed to find supply %s\n", supply);
ret = -ENODEV;
goto scrub;
}
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
new file mode 100644
index 000000000000..420362b5f116
--- /dev/null
+++ b/drivers/regulator/tps51632-regulator.c
@@ -0,0 +1,307 @@
+/*
+ * tps51632-regulator.c -- Maxim tps51632
+ *
+ * Regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down Driverless
+ * Controller with serial VID control and DVFS.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/tps51632-regulator.h>
+#include <linux/slab.h>
+
+/* Register definitions */
+#define TPS51632_VOLTAGE_SELECT_REG 0x0
+#define TPS51632_VOLTAGE_BASE_REG 0x1
+#define TPS51632_OFFSET_REG 0x2
+#define TPS51632_IMON_REG 0x3
+#define TPS51632_VMAX_REG 0x4
+#define TPS51632_DVFS_CONTROL_REG 0x5
+#define TPS51632_POWER_STATE_REG 0x6
+#define TPS51632_SLEW_REGS 0x7
+#define TPS51632_FAULT_REG 0x14
+
+#define TPS51632_MAX_REG 0x15
+
+#define TPS51632_VOUT_MASK 0x7F
+#define TPS51632_VOUT_OFFSET_MASK 0x1F
+#define TPS51632_VMAX_MASK 0x7F
+#define TPS51632_VMAX_LOCK 0x80
+
+/* TPS51632_DVFS_CONTROL_REG */
+#define TPS51632_DVFS_PWMEN 0x1
+#define TPS51632_DVFS_STEP_20 0x2
+#define TPS51632_DVFS_VMAX_PG 0x4
+#define TPS51632_DVFS_PWMRST 0x8
+#define TPS51632_DVFS_OCA_EN 0x10
+#define TPS51632_DVFS_FCCM 0x20
+
+/* TPS51632_POWER_STATE_REG */
+#define TPS51632_POWER_STATE_MASK 0x03
+#define TPS51632_POWER_STATE_MULTI_PHASE_CCM 0x0
+#define TPS51632_POWER_STATE_SINGLE_PHASE_CCM 0x1
+#define TPS51632_POWER_STATE_SINGLE_PHASE_DCM 0x2
+
+#define TPS51632_MIN_VOLATGE 500000
+#define TPS51632_MAX_VOLATGE 1520000
+#define TPS51632_VOLATGE_STEP 10000
+#define TPS51632_MAX_SEL 0x7F
+
+/* TPS51632 chip information */
+struct tps51632_chip {
+ struct device *dev;
+ struct regulator_desc desc;
+ struct regulator_dev *rdev;
+ struct regmap *regmap;
+
+ bool pwm_enabled;
+ unsigned int change_uv_per_us;
+};
+
+static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+ unsigned int data;
+ int ret;
+ unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+
+ if (tps->pwm_enabled)
+ reg = TPS51632_VOLTAGE_BASE_REG;
+ ret = regmap_read(tps->regmap, reg, &data);
+ if (ret < 0) {
+ dev_err(tps->dev, "reg read failed, err %d\n", ret);
+ return ret;
+ }
+ return data & TPS51632_VOUT_MASK;
+}
+
+static int tps51632_dcdc_set_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV, unsigned *selector)
+{
+ struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+ int vsel;
+ int ret;
+
+ if ((max_uV < min_uV) || (max_uV < TPS51632_MIN_VOLATGE) ||
+ (min_uV > TPS51632_MAX_VOLATGE))
+ return -EINVAL;
+
+ vsel = DIV_ROUND_UP(min_uV - TPS51632_MIN_VOLATGE,
+ TPS51632_VOLATGE_STEP) + 0x19;
+ if (selector)
+ *selector = (vsel & TPS51632_VOUT_MASK);
+
+ ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_SELECT_REG, vsel);
+ if (ret < 0)
+ dev_err(tps->dev, "reg write failed, err %d\n", ret);
+ return ret;
+}
+
+static int tps51632_dcdc_list_voltage(struct regulator_dev *rdev,
+ unsigned selector)
+{
+ if (selector > TPS51632_MAX_SEL)
+ return -EINVAL;
+
+ return TPS51632_MIN_VOLATGE + (selector - 0x19) * TPS51632_VOLATGE_STEP;
+}
+
+static int tps51632_dcdc_set_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector, unsigned int new_selector)
+{
+ struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+ int old_uV, new_uV;
+
+ old_uV = tps51632_dcdc_list_voltage(rdev, old_selector);
+ if (old_uV < 0)
+ return old_uV;
+
+ new_uV = tps51632_dcdc_list_voltage(rdev, new_selector);
+ if (new_uV < 0)
+ return new_uV;
+
+ return DIV_ROUND_UP(abs(old_uV - new_uV), tps->change_uv_per_us);
+}
+
+static struct regulator_ops tps51632_dcdc_ops = {
+ .get_voltage_sel = tps51632_dcdc_get_voltage_sel,
+ .set_voltage = tps51632_dcdc_set_voltage,
+ .list_voltage = tps51632_dcdc_list_voltage,
+ .set_voltage_time_sel = tps51632_dcdc_set_voltage_time_sel,
+};
+
+static int __devinit tps51632_init_dcdc(struct tps51632_chip *tps,
+ struct tps51632_regulator_platform_data *pdata)
+{
+ int ret;
+ uint8_t control = 0;
+ int vsel;
+
+ if (pdata->enable_pwm) {
+ control = TPS51632_DVFS_PWMEN;
+ tps->pwm_enabled = pdata->enable_pwm;
+ vsel = DIV_ROUND_UP(pdata->base_voltage_uV -
+ TPS51632_MIN_VOLATGE, TPS51632_VOLATGE_STEP) + 0x19;
+ ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG,
+ vsel);
+ if (ret < 0) {
+ dev_err(tps->dev, "BASE reg write failed, err %d\n",
+ ret);
+ return ret;
+ }
+ }
+ if (pdata->dvfs_step_20mV)
+ control = TPS51632_DVFS_STEP_20;
+ if (pdata->enable_vmax_alarm)
+ control = TPS51632_DVFS_VMAX_PG;
+ if (pdata->enable_overcurrent_alram)
+ control = TPS51632_DVFS_OCA_EN;
+ if (pdata->max_voltage_uV) {
+ vsel = DIV_ROUND_UP(pdata->max_voltage_uV -
+ TPS51632_MIN_VOLATGE, TPS51632_VOLATGE_STEP) + 0x19;
+ ret = regmap_write(tps->regmap, TPS51632_VMAX_REG, vsel);
+ if (ret < 0) {
+ dev_err(tps->dev, "VMAX write failed, err %d\n", ret);
+ return ret;
+ }
+ }
+ ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control);
+ if (ret < 0) {
+ dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret);
+ return ret;
+ }
+
+ tps->change_uv_per_us = max(6000u, pdata->slew_rate_uv_per_us);
+
+ vsel = BIT(tps->change_uv_per_us/6000 - 1);
+
+ ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, vsel);
+ if (ret < 0)
+ dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);
+ return ret;
+}
+
+static const struct regmap_config tps51632_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = TPS51632_MAX_REG - 1,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit tps51632_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tps51632_regulator_platform_data *pdata;
+ struct regulator_dev *rdev;
+ struct tps51632_chip *tps;
+ int ret;
+
+ pdata = client->dev.platform_data;
+ if (!pdata) {
+ dev_err(&client->dev, "No Platform data\n");
+ return -EINVAL;
+ }
+
+ tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+ if (!tps) {
+ dev_err(&client->dev, "Memory allocation failed\n");
+ return -ENOMEM;
+ }
+
+ tps->dev = &client->dev;
+ tps->desc.name = id->name;
+ tps->desc.id = 0;
+ tps->desc.ops = &tps51632_dcdc_ops;
+ tps->desc.type = REGULATOR_VOLTAGE;
+ tps->desc.owner = THIS_MODULE;
+ tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config);
+ if (IS_ERR(tps->regmap)) {
+ ret = PTR_ERR(tps->regmap);
+ dev_err(&client->dev, "regmap init failed, err %d\n", ret);
+ return ret;
+ }
+ i2c_set_clientdata(client, tps);
+
+ ret = tps51632_init_dcdc(tps, pdata);
+ if (ret < 0) {
+ dev_err(tps->dev, "Init failed, err = %d\n", ret);
+ return ret;
+ }
+
+ /* Register the regulators */
+ rdev = regulator_register(&tps->desc, &client->dev,
+ pdata->reg_init_data, tps);
+ if (IS_ERR(rdev)) {
+ dev_err(tps->dev, "regulator register failed\n");
+ return PTR_ERR(rdev);
+ }
+
+ tps->rdev = rdev;
+ return 0;
+}
+
+static int __devexit tps51632_remove(struct i2c_client *client)
+{
+ struct tps51632_chip *tps = i2c_get_clientdata(client);
+
+ regulator_unregister(tps->rdev);
+ return 0;
+}
+
+static const struct i2c_device_id tps51632_id[] = {
+ {.name = "tps51632",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, tps51632_id);
+
+static struct i2c_driver tps51632_i2c_driver = {
+ .driver = {
+ .name = "tps51632",
+ .owner = THIS_MODULE,
+ },
+ .probe = tps51632_probe,
+ .remove = __devexit_p(tps51632_remove),
+ .id_table = tps51632_id,
+};
+
+static int __init tps51632_init(void)
+{
+ return i2c_add_driver(&tps51632_i2c_driver);
+}
+subsys_initcall(tps51632_init);
+
+static void __exit tps51632_cleanup(void)
+{
+ i2c_del_driver(&tps51632_i2c_driver);
+}
+module_exit(tps51632_cleanup);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("TPS51632 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
index 7db148202436..095104f73b57 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -323,9 +323,15 @@ static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
return ret;
}
+static bool is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return false;
+}
+
static const struct regmap_config tps62360_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
+ .volatile_reg = is_volatile_reg,
.max_register = REG_CHIPID,
.cache_type = REGCACHE_RBTREE,
};
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index 8249a4b7ded2..aca2f56aa172 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -1,29 +1,25 @@
/*
- * drivers/regulator/tps65090-regulator.c
- *
* Regulator driver for tps65090 power management chip.
*
- * Copyright (C) 2012 NVIDIA Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+
+ * This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/platform_device.h>
@@ -32,7 +28,7 @@
#include <linux/mfd/tps65090.h>
#include <linux/regulator/tps65090-regulator.h>
-struct tps65090_regulator {
+struct tps65090_regulator_info {
int id;
/* Regulator register address.*/
u8 reg_en_reg;
@@ -40,30 +36,51 @@ struct tps65090_regulator {
/* used by regulator core */
struct regulator_desc desc;
-
- /* Device */
- struct device *dev;
};
+struct tps65090_regulator {
+ struct tps65090_regulator_info *rinfo;
+ struct device *dev;
+ struct regulator_dev *rdev;
+ bool enable_ext_control;
+ int gpio;
+ int gpio_state;
+};
static inline struct device *to_tps65090_dev(struct regulator_dev *rdev)
{
return rdev_get_dev(rdev)->parent->parent;
}
+
+static inline bool is_dcdc(int id)
+{
+ if ((id == TPS65090_REGULATOR_DCDC1) ||
+ (id == TPS65090_REGULATOR_DCDC2) ||
+ (id == TPS65090_REGULATOR_DCDC2))
+ return true;
+ return false;
+}
+
static int tps65090_reg_is_enabled(struct regulator_dev *rdev)
{
struct tps65090_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps65090_dev(rdev);
- uint8_t control;
+ uint8_t control = 0;
int ret;
- ret = tps65090_read(parent, ri->reg_en_reg, &control);
+ if (is_dcdc(ri->rinfo->desc.id) && ri->enable_ext_control) {
+ if (gpio_is_valid(ri->gpio))
+ return ri->gpio_state;
+ return 1;
+ }
+
+ ret = tps65090_read(parent, ri->rinfo->reg_en_reg, &control);
if (ret < 0) {
dev_err(&rdev->dev, "Error in reading reg 0x%x\n",
- ri->reg_en_reg);
+ ri->rinfo->reg_en_reg);
return ret;
}
- return (((control >> ri->en_bit) & 1) == 1);
+ return (((control >> ri->rinfo->en_bit) & 1) == 1);
}
static int tps65090_reg_enable(struct regulator_dev *rdev)
@@ -72,10 +89,19 @@ static int tps65090_reg_enable(struct regulator_dev *rdev)
struct device *parent = to_tps65090_dev(rdev);
int ret;
- ret = tps65090_set_bits(parent, ri->reg_en_reg, ri->en_bit);
+ if (is_dcdc(ri->rinfo->desc.id) && ri->enable_ext_control) {
+ if (gpio_is_valid(ri->gpio)) {
+ gpio_set_value(ri->gpio, 1);
+ ri->gpio_state = 1;
+ }
+ return 0;
+ }
+
+ ret = tps65090_set_bits(parent, ri->rinfo->reg_en_reg,
+ ri->rinfo->en_bit);
if (ret < 0)
dev_err(&rdev->dev, "Error in updating reg 0x%x\n",
- ri->reg_en_reg);
+ ri->rinfo->reg_en_reg);
return ret;
}
@@ -85,10 +111,19 @@ static int tps65090_reg_disable(struct regulator_dev *rdev)
struct device *parent = to_tps65090_dev(rdev);
int ret;
- ret = tps65090_clr_bits(parent, ri->reg_en_reg, ri->en_bit);
+ if (is_dcdc(ri->rinfo->desc.id) && ri->enable_ext_control) {
+ if (gpio_is_valid(ri->gpio)) {
+ gpio_set_value(ri->gpio, 0);
+ ri->gpio_state = 0;
+ }
+ return 0;
+ }
+
+ ret = tps65090_clr_bits(parent, ri->rinfo->reg_en_reg,
+ ri->rinfo->en_bit);
if (ret < 0)
dev_err(&rdev->dev, "Error in updating reg 0x%x\n",
- ri->reg_en_reg);
+ ri->rinfo->reg_en_reg);
return ret;
}
@@ -99,84 +134,209 @@ static struct regulator_ops tps65090_ops = {
.is_enabled = tps65090_reg_is_enabled,
};
-#define tps65090_REG(_id, _en_reg, _en_bit, _ops) \
+static struct regulator_ops tps65090_ldo_ops = {
+};
+
+#define tps65090_REG(_id, _sname, _en_reg, _en_bit, _ops) \
{ \
.reg_en_reg = _en_reg, \
.en_bit = _en_bit, \
- .id = TPS65090_ID_##_id, \
+ .id = TPS65090_REGULATOR_##_id, \
.desc = { \
.name = tps65090_rails(_id), \
- .id = TPS65090_ID_##_id, \
+ .supply_name = _sname, \
+ .id = TPS65090_REGULATOR_##_id, \
.ops = &_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}, \
}
-static struct tps65090_regulator TPS65090_regulator[] = {
- tps65090_REG(DCDC1, 12, 0, tps65090_ops),
- tps65090_REG(DCDC2, 13, 0, tps65090_ops),
- tps65090_REG(DCDC3, 14, 0, tps65090_ops),
- tps65090_REG(FET1, 15, 0, tps65090_ops),
- tps65090_REG(FET2, 16, 0, tps65090_ops),
- tps65090_REG(FET3, 17, 0, tps65090_ops),
- tps65090_REG(FET4, 18, 0, tps65090_ops),
- tps65090_REG(FET5, 19, 0, tps65090_ops),
- tps65090_REG(FET6, 20, 0, tps65090_ops),
- tps65090_REG(FET7, 21, 0, tps65090_ops),
+static struct tps65090_regulator_info TPS65090_regulator_info[] = {
+ tps65090_REG(DCDC1, "VSYS1", 12, 0, tps65090_ops),
+ tps65090_REG(DCDC2, "VSYS2", 13, 0, tps65090_ops),
+ tps65090_REG(DCDC3, "VSYS3", 14, 0, tps65090_ops),
+ tps65090_REG(LDO1, "VSYS_L1", 0, 0, tps65090_ldo_ops),
+ tps65090_REG(LDO2, "VSYS_L2", 0, 0, tps65090_ldo_ops),
+ tps65090_REG(FET1, "INFET1", 15, 0, tps65090_ops),
+ tps65090_REG(FET2, "INFET2", 16, 0, tps65090_ops),
+ tps65090_REG(FET3, "INFET3", 17, 0, tps65090_ops),
+ tps65090_REG(FET4, "INFET4", 18, 0, tps65090_ops),
+ tps65090_REG(FET5, "INFET5", 19, 0, tps65090_ops),
+ tps65090_REG(FET6, "INFET6", 20, 0, tps65090_ops),
+ tps65090_REG(FET7, "INFET7", 21, 0, tps65090_ops),
};
-static inline struct tps65090_regulator *find_regulator_info(int id)
+
+static inline struct tps65090_regulator_info *find_regulator_info(int id)
{
- struct tps65090_regulator *ri;
+ struct tps65090_regulator_info *rinfo;
int i;
- for (i = 0; i < ARRAY_SIZE(TPS65090_regulator); i++) {
- ri = &TPS65090_regulator[i];
- if (ri->desc.id == id)
- return ri;
+ for (i = 0; i < ARRAY_SIZE(TPS65090_regulator_info); i++) {
+ rinfo = &TPS65090_regulator_info[i];
+ if (rinfo->desc.id == id)
+ return rinfo;
}
return NULL;
}
+
+static int __devinit tps65090_regulator_preinit(int id,
+ struct tps65090_regulator *ri,
+ struct tps65090_regulator_platform_data *tps_pdata)
+{
+ int ret = 0;
+ struct device *parent = ri->dev->parent;
+
+ if (!tps_pdata->enable_ext_control) {
+ ret = tps65090_clr_bits(parent,
+ ri->rinfo->reg_en_reg, 1);
+ if (ret < 0) {
+ dev_err(ri->dev, "Error in clr reg 0x%x\n",
+ ri->rinfo->reg_en_reg);
+ return ret;
+ }
+ }
+
+ if (gpio_is_valid(tps_pdata->gpio)) {
+ int gpio_flag = GPIOF_OUT_INIT_LOW;
+ const char *sname;
+
+ sname = tps_pdata->reg_init_data->constraints.name;
+ if (!sname)
+ sname = ri->rinfo->desc.name;
+ ri->gpio_state = 0;
+ if (tps_pdata->reg_init_data->constraints.always_on ||
+ tps_pdata->reg_init_data->constraints.boot_on) {
+ gpio_flag = GPIOF_OUT_INIT_HIGH;
+ ri->gpio_state = 1;
+ }
+
+ ret = gpio_request_one(tps_pdata->gpio, gpio_flag, sname);
+ if (ret < 0) {
+ dev_err(ri->dev, "gpio request failed, e %d\n", ret);
+ return ret;
+ }
+ }
+ ret = tps65090_set_bits(parent, ri->rinfo->reg_en_reg, 1);
+ if (ret < 0) {
+ dev_err(ri->dev, "Error in setting reg 0x%x\n",
+ ri->rinfo->reg_en_reg);
+ return ret;
+ }
+ ri->enable_ext_control = true;
+ ri->gpio = tps_pdata->gpio;
+ return ret;
+}
+
static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
{
- struct tps65090_regulator *ri = NULL;
+ struct tps65090_regulator_info *rinfo = NULL;
+ struct tps65090_regulator *ri;
+ struct tps65090_regulator *pmic;
struct regulator_dev *rdev;
struct tps65090_regulator_platform_data *tps_pdata;
- int id = pdev->id;
+ struct tps65090_platform_data *tps65090_pdata;
+ int id;
+ int num;
+ int ret;
- dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+ dev_dbg(&pdev->dev, "Probing regulator\n");
- ri = find_regulator_info(id);
- if (ri == NULL) {
- dev_err(&pdev->dev, "invalid regulator ID specified\n");
+ tps65090_pdata = dev_get_platdata(pdev->dev.parent);
+ if (!tps65090_pdata || !tps65090_pdata->num_reg_pdata) {
+ dev_err(&pdev->dev, "Proper platform data missing\n");
return -EINVAL;
}
- tps_pdata = pdev->dev.platform_data;
- ri->dev = &pdev->dev;
-
- rdev = regulator_register(&ri->desc, &pdev->dev,
- &tps_pdata->regulator, ri);
- if (IS_ERR_OR_NULL(rdev)) {
- dev_err(&pdev->dev, "failed to register regulator %s\n",
- ri->desc.name);
- return PTR_ERR(rdev);
+
+ pmic = devm_kzalloc(&pdev->dev,
+ tps65090_pdata->num_reg_pdata * sizeof(*pmic),
+ GFP_KERNEL);
+ if (!pmic) {
+ dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+ return -ENOMEM;
+ }
+
+ for (num = 0; num < tps65090_pdata->num_reg_pdata; ++num) {
+ tps_pdata = tps65090_pdata->reg_pdata[num];
+ if (!tps_pdata || !tps_pdata->reg_init_data) {
+ dev_err(&pdev->dev,
+ "Null platform data for regultor %d\n", num);
+ ret = -EINVAL;
+ goto scrub;
+ }
+
+ id = tps_pdata->id;
+ rinfo = find_regulator_info(id);
+ if (!rinfo) {
+ dev_err(&pdev->dev,
+ "invalid regulator ID %d specified\n", id);
+ ret = -EINVAL;
+ goto scrub;
+ }
+
+ ri = &pmic[num];
+ ri->dev = &pdev->dev;
+ ri->rinfo = rinfo;
+
+ if (is_dcdc(id)) {
+ ret = tps65090_regulator_preinit(id, ri, tps_pdata);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "failed to preinit regulator %d\n", id);
+ goto scrub;
+ }
+ }
+ rdev = regulator_register(&ri->rinfo->desc, &pdev->dev,
+ tps_pdata->reg_init_data, ri);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register regulator %s\n",
+ ri->rinfo->desc.name);
+ ret = PTR_ERR(rdev);
+ goto scrub;
+ }
+ ri->rdev = rdev;
}
- platform_set_drvdata(pdev, rdev);
+ platform_set_drvdata(pdev, pmic);
return 0;
+
+scrub:
+ while (--num >= 0) {
+ ri = &pmic[num];
+ regulator_unregister(ri->rdev);
+ if (is_dcdc(ri->rinfo->desc.id) && (ri->enable_ext_control)) {
+ if (gpio_is_valid(ri->gpio))
+ gpio_free(ri->gpio);
+ }
+ }
+ return ret;
}
static int __devexit tps65090_regulator_remove(struct platform_device *pdev)
{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
+ struct tps65090_platform_data *tps65090_pdata;
+ struct tps65090_regulator *ri;
+ int num;
+
+ tps65090_pdata = dev_get_platdata(pdev->dev.parent);
+ if (!tps65090_pdata || !tps65090_pdata->num_reg_pdata)
+ return 0;
- regulator_unregister(rdev);
+ for (num = 0; num < tps65090_pdata->num_reg_pdata; ++num) {
+ ri = &pmic[num];
+ regulator_unregister(ri->rdev);
+ if (is_dcdc(ri->rinfo->desc.id) && (ri->enable_ext_control)) {
+ if (gpio_is_valid(ri->gpio))
+ gpio_free(ri->gpio);
+ }
+ }
return 0;
}
static struct platform_driver tps65090_regulator_driver = {
.driver = {
- .name = "tps65090-regulator",
+ .name = "tps65090-pmic",
.owner = THIS_MODULE,
},
.probe = tps65090_regulator_probe,
@@ -196,5 +356,5 @@ static void __exit tps65090_regulator_exit(void)
module_exit(tps65090_regulator_exit);
MODULE_DESCRIPTION("tps65090 regulator driver");
-MODULE_ALIAS("platform:tps65090-regulator");
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
index efc608c936ea..39b5f452692a 100644
--- a/drivers/regulator/tps80031-regulator.c
+++ b/drivers/regulator/tps80031-regulator.c
@@ -81,44 +81,48 @@
#define EXT_PWR_REQ (PWR_REQ_INPUT_PREQ1 | PWR_REQ_INPUT_PREQ2 | \
PWR_REQ_INPUT_PREQ3)
-struct tps80031_regulator {
-
+struct tps80031_regulator_info {
/* Regulator register address.*/
u8 trans_reg;
u8 state_reg;
u8 force_reg;
u8 volt_reg;
u8 volt_id;
- uint8_t trans_reg_cache;
- uint8_t state_reg_cache;
- uint8_t force_reg_cache;
- uint8_t volt_reg_cache;
-
- /* twl resource ID, for resource control state machine */
- u8 id;
/* chip constraints on regulator behavior */
u16 min_mV;
u16 max_mV;
- unsigned int tolerance_uv;
- /* regulator specific turn-on delay */
+ /* regulator specific turn-on delay as per datasheet*/
int delay;
- u8 flags;
- unsigned int platform_flags;
- unsigned int ext_ctrl_flag;
-
/* used by regulator core */
struct regulator_desc desc;
- /* Device */
- struct device *dev;
-
/*Power request bits */
int preq_bit;
};
+struct tps80031_regulator {
+ struct device *dev;
+ struct regulator_dev *rdev;
+ struct tps80031_regulator_info *rinfo;
+ unsigned int tolerance_uv;
+
+ /* Regulator specific turn-on delay if board file provided */
+ int delay;
+
+ u8 flags;
+ unsigned int platform_flags;
+ unsigned int ext_ctrl_flag;
+
+ /* Cached register */
+ uint8_t trans_reg_cache;
+ uint8_t state_reg_cache;
+ uint8_t force_reg_cache;
+ uint8_t volt_reg_cache;
+};
+
static inline struct device *to_tps80031_dev(struct regulator_dev *rdev)
{
return rdev_get_dev(rdev)->parent->parent;
@@ -178,7 +182,7 @@ static int tps80031_reg_enable(struct regulator_dev *rdev)
reg_val = (ri->state_reg_cache & ~STATE_MASK) |
(STATE_ON & STATE_MASK);
- ret = tps80031_write(parent, SLAVE_ID1, ri->state_reg, reg_val);
+ ret = tps80031_write(parent, SLAVE_ID1, ri->rinfo->state_reg, reg_val);
if (ret < 0) {
dev_err(&rdev->dev, "Error in writing the STATE register\n");
return ret;
@@ -200,7 +204,7 @@ static int tps80031_reg_disable(struct regulator_dev *rdev)
reg_val = (ri->state_reg_cache & ~STATE_MASK) |
(STATE_OFF & STATE_MASK);
- ret = tps80031_write(parent, SLAVE_ID1, ri->state_reg, reg_val);
+ ret = tps80031_write(parent, SLAVE_ID1, ri->rinfo->state_reg, reg_val);
if (ret < 0)
dev_err(&rdev->dev, "Error in writing the STATE register\n");
else
@@ -297,10 +301,11 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
int vsel = 0;
int ret;
- min_uV = min_uV - ri->tolerance_uv;
-
switch (ri->flags) {
case 0:
+ if (min_uV >= (607700 + ri->tolerance_uv))
+ min_uV = min_uV - ri->tolerance_uv;
+
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 607700) && (min_uV <= 1300000)) {
@@ -328,6 +333,8 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
break;
case DCDC_OFFSET_EN:
+ if (min_uV >= (700000 + ri->tolerance_uv))
+ min_uV = min_uV - ri->tolerance_uv;
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 700000) && (min_uV <= 1420000)) {
@@ -355,6 +362,8 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
break;
case DCDC_EXTENDED_EN:
+ if (min_uV >= (1852000 + ri->tolerance_uv))
+ min_uV = min_uV - ri->tolerance_uv;
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
@@ -366,6 +375,8 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
break;
case DCDC_OFFSET_EN|DCDC_EXTENDED_EN:
+ if (min_uV >= (2161000 + ri->tolerance_uv))
+ min_uV = min_uV - ri->tolerance_uv;
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
@@ -381,10 +392,10 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
if (selector)
*selector = vsel;
- if (ri->force_reg) {
+ if (ri->rinfo->force_reg) {
if (((ri->force_reg_cache >> 6) & 0x3) == 0) {
- ret = tps80031_write(parent, ri->volt_id,
- ri->force_reg, vsel);
+ ret = tps80031_write(parent, ri->rinfo->volt_id,
+ ri->rinfo->force_reg, vsel);
if (ret < 0)
dev_err(ri->dev, "Error in writing the "
"force register\n");
@@ -393,7 +404,8 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
return ret;
}
}
- ret = tps80031_write(parent, ri->volt_id, ri->volt_reg, vsel);
+ ret = tps80031_write(parent, ri->rinfo->volt_id,
+ ri->rinfo->volt_reg, vsel);
if (ret < 0)
dev_err(ri->dev, "Error in writing the Voltage register\n");
else
@@ -416,7 +428,7 @@ static int tps80031dcdc_get_voltage(struct regulator_dev *rdev)
uint8_t vsel = 0;
int voltage = 0;
- if (ri->force_reg) {
+ if (ri->rinfo->force_reg) {
vsel = ri->force_reg_cache;
if ((vsel & SMPS_CMD_MASK) == 0)
goto decode;
@@ -507,11 +519,11 @@ static int tps80031ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
if (index == 0)
return 0;
- if ((ri->desc.id == TPS80031_ID_LDO2) &&
+ if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
(ri->flags & TRACK_MODE_ENABLE))
- return (ri->min_mV + (((index - 1) * 125))/10) * 1000;
+ return (ri->rinfo->min_mV + (((index - 1) * 125))/10) * 1000;
- return (ri->min_mV + ((index - 1) * 100)) * 1000;
+ return (ri->rinfo->min_mV + ((index - 1) * 100)) * 1000;
}
static int __tps80031_ldo2_set_voltage_track_mode(struct device *parent,
@@ -545,7 +557,8 @@ static int __tps80031_ldo2_set_voltage_track_mode(struct device *parent,
}
}
- ret = tps80031_write(parent, ri->volt_id, ri->volt_reg, vsel);
+ ret = tps80031_write(parent, ri->rinfo->volt_id,
+ ri->rinfo->volt_reg, vsel);
if (ret < 0)
dev_err(ri->dev, "Error in writing the Voltage register\n");
else
@@ -562,10 +575,11 @@ static int __tps80031_ldo_set_voltage(struct device *parent,
int vsel;
int ret;
- if ((min_uV/1000 < ri->min_mV) || (max_uV/1000 > ri->max_mV))
+ if ((min_uV/1000 < ri->rinfo->min_mV) ||
+ (max_uV/1000 > ri->rinfo->max_mV))
return -EDOM;
- if ((ri->desc.id == TPS80031_ID_LDO2) &&
+ if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
(ri->flags & TRACK_MODE_ENABLE))
return __tps80031_ldo2_set_voltage_track_mode(parent, ri,
min_uV, max_uV);
@@ -577,7 +591,8 @@ static int __tps80031_ldo_set_voltage(struct device *parent,
vsel = (min_uV/1000 - 1000)/100 + 1;
if (selector)
*selector = vsel;
- ret = tps80031_write(parent, ri->volt_id, ri->volt_reg, vsel);
+ ret = tps80031_write(parent, ri->rinfo->volt_id,
+ ri->rinfo->volt_reg, vsel);
if (ret < 0)
dev_err(ri->dev, "Error in writing the Voltage register\n");
else
@@ -601,10 +616,10 @@ static int tps80031ldo_get_voltage(struct regulator_dev *rdev)
uint8_t vsel;
- if ((ri->desc.id == TPS80031_ID_LDO2) &&
+ if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
(ri->flags & TRACK_MODE_ENABLE)) {
vsel = ri->volt_reg_cache & 0x3F;
- return (ri->min_mV + (((vsel - 1) * 125))/10) * 1000;
+ return (ri->rinfo->min_mV + (((vsel - 1) * 125))/10) * 1000;
}
vsel = ri->volt_reg_cache & LDO_VSEL_MASK;
@@ -712,6 +727,22 @@ static int tps80031vbus_get_voltage(struct regulator_dev *rdev)
return ret;
}
+static int tps80031_extreg_enable_time(struct regulator_dev *rdev)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ return ri->delay;
+}
+
+static int tps80031_extreg_get_voltage(struct regulator_dev *rdev)
+{
+ struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+ int ret;
+ ret = tps80031_reg_is_enabled(rdev);
+ if (ret > 0)
+ return ri->rinfo->max_mV * 1000;
+ return 0;
+}
+
static struct regulator_ops tps80031dcdc_ops = {
.list_voltage = tps80031dcdc_list_voltage,
.set_voltage = tps80031dcdc_set_voltage,
@@ -740,6 +771,16 @@ static struct regulator_ops tps80031vbus_ops = {
.enable_time = tps80031_vbus_enable_time,
};
+static struct regulator_ops tps80031_ext_reg_ops = {
+ .enable = tps80031_reg_enable,
+ .disable = tps80031_reg_disable,
+ .is_enabled = tps80031_reg_is_enabled,
+ .enable_time = tps80031_extreg_enable_time,
+ .get_voltage = tps80031_extreg_get_voltage,
+};
+
+
+
#define TPS80031_REG(_id, _trans_reg, _state_reg, _force_reg, _volt_reg, \
_volt_id, min_mVolts, max_mVolts, _ops, _n_volt, _delay, \
_preq_bit) \
@@ -749,12 +790,11 @@ static struct regulator_ops tps80031vbus_ops = {
.force_reg = _force_reg, \
.volt_reg = _volt_reg, \
.volt_id = _volt_id, \
- .id = TPS80031_ID_##_id, \
.min_mV = min_mVolts, \
.max_mV = max_mVolts, \
.desc = { \
.name = tps80031_rails(_id), \
- .id = TPS80031_ID_##_id, \
+ .id = TPS80031_REGULATOR_##_id, \
.n_voltages = _n_volt, \
.ops = &_ops, \
.type = REGULATOR_VOLTAGE, \
@@ -764,7 +804,7 @@ static struct regulator_ops tps80031vbus_ops = {
.preq_bit = _preq_bit, \
}
-static struct tps80031_regulator tps80031_regulator[] = {
+static struct tps80031_regulator_info tps80031_regulator_info[] = {
TPS80031_REG(VIO, 0x47, 0x48, 0x49, 0x4A, SLAVE_ID0, 600, 2100,
tps80031dcdc_ops, 63, 500, 4),
TPS80031_REG(SMPS1, 0x53, 0x54, 0x55, 0x56, SLAVE_ID0, 600, 2100,
@@ -798,6 +838,12 @@ static struct tps80031_regulator tps80031_regulator[] = {
tps80031ldo_ops, 25, 500, -1),
TPS80031_REG(VBUS, 0x0, 0x0, 0x00, 0x0, SLAVE_ID1, 0, 5000,
tps80031vbus_ops, 2, 200000, -1),
+ TPS80031_REG(REGEN1, 0xAE, 0xAF, 0x00, 0x0, SLAVE_ID1, 0, 3300,
+ tps80031_ext_reg_ops, 2, 500, 16),
+ TPS80031_REG(REGEN2, 0xB1, 0xB2, 0x00, 0x0, SLAVE_ID1, 0, 3300,
+ tps80031_ext_reg_ops, 2, 500, 17),
+ TPS80031_REG(SYSEN, 0xB4, 0xB5, 0x00, 0x0, SLAVE_ID1, 0, 3300,
+ tps80031_ext_reg_ops, 2, 500, 18),
};
static int tps80031_power_req_config(struct device *parent,
@@ -807,17 +853,18 @@ static int tps80031_power_req_config(struct device *parent,
int ret = 0;
uint8_t reg_val;
- if (ri->preq_bit < 0)
+ if (ri->rinfo->preq_bit < 0)
goto skip_pwr_req_config;
ret = tps80031_ext_power_req_config(parent, ri->ext_ctrl_flag,
- ri->preq_bit, ri->state_reg, ri->trans_reg);
+ ri->rinfo->preq_bit, ri->rinfo->state_reg,
+ ri->rinfo->trans_reg);
if (!ret)
- ret = tps80031_read(parent, SLAVE_ID1, ri->trans_reg,
+ ret = tps80031_read(parent, SLAVE_ID1, ri->rinfo->trans_reg,
&ri->trans_reg_cache);
- if (!ret && ri->state_reg)
- ret = tps80031_read(parent, SLAVE_ID1, ri->state_reg,
+ if (!ret && ri->rinfo->state_reg)
+ ret = tps80031_read(parent, SLAVE_ID1, ri->rinfo->state_reg,
&ri->state_reg_cache);
if (ret < 0) {
dev_err(ri->dev, "%s() fails\n", __func__);
@@ -831,11 +878,11 @@ skip_pwr_req_config:
if (tps80031_pdata->ext_ctrl_flag & PWR_ON_ON_SLEEP)
reg_val |= 0x4;
- ret = tps80031_write(parent, SLAVE_ID1, ri->trans_reg,
+ ret = tps80031_write(parent, SLAVE_ID1, ri->rinfo->trans_reg,
reg_val);
if (ret < 0)
dev_err(ri->dev, "Not able to write reg 0x%02x\n",
- ri->trans_reg);
+ ri->rinfo->trans_reg);
else
ri->trans_reg_cache = reg_val;
}
@@ -849,7 +896,7 @@ static int tps80031_regulator_preinit(struct device *parent,
int ret = 0;
uint8_t reg_val;
- if (ri->desc.id == TPS80031_ID_LDOUSB) {
+ if (ri->rinfo->desc.id == TPS80031_REGULATOR_LDOUSB) {
if (ri->platform_flags & USBLDO_INPUT_VSYS)
ret = tps80031_update(parent, SLAVE_ID1,
TPS80031_MISC2_ADD,
@@ -865,7 +912,7 @@ static int tps80031_regulator_preinit(struct device *parent,
}
}
- if (ri->desc.id == TPS80031_ID_LDO3) {
+ if (ri->rinfo->desc.id == TPS80031_REGULATOR_LDO3) {
if (ri->platform_flags & LDO3_OUTPUT_VIB)
ret = tps80031_update(parent, SLAVE_ID1,
TPS80031_MISC2_ADD,
@@ -878,31 +925,59 @@ static int tps80031_regulator_preinit(struct device *parent,
}
}
+ switch (ri->rinfo->desc.id) {
+ case TPS80031_REGULATOR_REGEN1:
+ case TPS80031_REGULATOR_REGEN2:
+ case TPS80031_REGULATOR_SYSEN:
+ if (tps80031_pdata->reg_init_data->constraints.always_on ||
+ tps80031_pdata->reg_init_data->constraints.boot_on)
+ ret = tps80031_update(parent, SLAVE_ID1,
+ ri->rinfo->state_reg, STATE_ON, STATE_MASK);
+ else
+ ret = tps80031_update(parent, SLAVE_ID1,
+ ri->rinfo->state_reg, STATE_OFF, STATE_MASK);
+ if (ret < 0) {
+ dev_err(ri->dev,
+ "state reg update failed, e %d\n", ret);
+ return ret;
+ }
+ ret = tps80031_update(parent, SLAVE_ID1,
+ ri->rinfo->trans_reg, 1, 0x3);
+ if (ret < 0) {
+ dev_err(ri->dev,
+ "trans reg update failed, e %d\n", ret);
+ return ret;
+ }
+ break;
+ default:
+ break;
+ }
+
if (!tps80031_pdata->init_apply)
return 0;
if (tps80031_pdata->init_uV >= 0) {
- switch (ri->desc.id) {
- case TPS80031_ID_VIO:
- case TPS80031_ID_SMPS1:
- case TPS80031_ID_SMPS2:
- case TPS80031_ID_SMPS3:
- case TPS80031_ID_SMPS4:
+ switch (ri->rinfo->desc.id) {
+ case TPS80031_REGULATOR_VIO:
+ case TPS80031_REGULATOR_SMPS1:
+ case TPS80031_REGULATOR_SMPS2:
+ case TPS80031_REGULATOR_SMPS3:
+ case TPS80031_REGULATOR_SMPS4:
ret = __tps80031_dcdc_set_voltage(parent, ri,
tps80031_pdata->init_uV,
tps80031_pdata->init_uV, 0);
break;
- case TPS80031_ID_LDO1:
- case TPS80031_ID_LDO2:
- case TPS80031_ID_LDO3:
- case TPS80031_ID_LDO4:
- case TPS80031_ID_LDO5:
- case TPS80031_ID_LDO6:
- case TPS80031_ID_LDO7:
- case TPS80031_ID_LDOUSB:
- case TPS80031_ID_LDOLN:
- case TPS80031_ID_VANA:
+ case TPS80031_REGULATOR_LDO1:
+ case TPS80031_REGULATOR_LDO2:
+ case TPS80031_REGULATOR_LDO3:
+ case TPS80031_REGULATOR_LDO4:
+ case TPS80031_REGULATOR_LDO5:
+ case TPS80031_REGULATOR_LDO6:
+ case TPS80031_REGULATOR_LDO7:
+ case TPS80031_REGULATOR_LDOUSB:
+ case TPS80031_REGULATOR_LDOLN:
+ case TPS80031_REGULATOR_VANA:
ret = __tps80031_ldo_set_voltage(parent, ri,
tps80031_pdata->init_uV,
tps80031_pdata->init_uV, 0);
@@ -915,7 +990,7 @@ static int tps80031_regulator_preinit(struct device *parent,
if (ret < 0) {
dev_err(ri->dev, "Not able to initialize voltage %d "
"for rail %d err %d\n", tps80031_pdata->init_uV,
- ri->desc.id, ret);
+ ri->rinfo->desc.id, ret);
return ret;
}
}
@@ -927,25 +1002,25 @@ static int tps80031_regulator_preinit(struct device *parent,
reg_val = (ri->state_reg_cache & ~STATE_MASK) |
(STATE_OFF & STATE_MASK);
- ret = tps80031_write(parent, SLAVE_ID1, ri->state_reg, reg_val);
+ ret = tps80031_write(parent, SLAVE_ID1, ri->rinfo->state_reg, reg_val);
if (ret < 0)
dev_err(ri->dev, "Not able to %s rail %d err %d\n",
(tps80031_pdata->init_enable) ? "enable" : "disable",
- ri->desc.id, ret);
+ ri->rinfo->desc.id, ret);
else
ri->state_reg_cache = reg_val;
return ret;
}
-static inline struct tps80031_regulator *find_regulator_info(int id)
+static inline struct tps80031_regulator_info *find_regulator_info(int id)
{
- struct tps80031_regulator *ri;
+ struct tps80031_regulator_info *rinfo;
int i;
- for (i = 0; i < ARRAY_SIZE(tps80031_regulator); i++) {
- ri = &tps80031_regulator[i];
- if (ri->desc.id == id)
- return ri;
+ for (i = 0; i < ARRAY_SIZE(tps80031_regulator_info); i++) {
+ rinfo = &tps80031_regulator_info[i];
+ if (rinfo->desc.id == id)
+ return rinfo;
}
return NULL;
}
@@ -953,30 +1028,30 @@ static void check_smps_mode_mult(struct device *parent,
struct tps80031_regulator *ri)
{
int mult_offset;
- switch (ri->desc.id) {
- case TPS80031_ID_VIO:
+ switch (ri->rinfo->desc.id) {
+ case TPS80031_REGULATOR_VIO:
mult_offset = SMPS_MULTOFFSET_VIO;
break;
- case TPS80031_ID_SMPS1:
+ case TPS80031_REGULATOR_SMPS1:
mult_offset = SMPS_MULTOFFSET_SMPS1;
break;
- case TPS80031_ID_SMPS2:
+ case TPS80031_REGULATOR_SMPS2:
mult_offset = SMPS_MULTOFFSET_SMPS2;
break;
- case TPS80031_ID_SMPS3:
+ case TPS80031_REGULATOR_SMPS3:
mult_offset = SMPS_MULTOFFSET_SMPS3;
break;
- case TPS80031_ID_SMPS4:
+ case TPS80031_REGULATOR_SMPS4:
mult_offset = SMPS_MULTOFFSET_SMPS4;
break;
- case TPS80031_ID_LDO2:
+ case TPS80031_REGULATOR_LDO2:
ri->flags = (tps80031_get_smps_mult(parent) & (1 << 5)) ?
TRACK_MODE_ENABLE : 0;
/* TRACK mode the ldo2 varies from 600mV to 1300mV */
if (ri->flags & TRACK_MODE_ENABLE) {
- ri->min_mV = 600;
- ri->max_mV = 1300;
- ri->desc.n_voltages = 57;
+ ri->rinfo->min_mV = 600;
+ ri->rinfo->max_mV = 1300;
+ ri->rinfo->desc.n_voltages = 57;
}
return;
default:
@@ -995,82 +1070,136 @@ static inline int tps80031_cache_regulator_register(struct device *parent,
{
int ret;
- ret = tps80031_read(parent, SLAVE_ID1, ri->trans_reg,
+ ret = tps80031_read(parent, SLAVE_ID1, ri->rinfo->trans_reg,
&ri->trans_reg_cache);
- if (!ret && ri->state_reg)
- ret = tps80031_read(parent, SLAVE_ID1, ri->state_reg,
+ if (!ret && ri->rinfo->state_reg)
+ ret = tps80031_read(parent, SLAVE_ID1, ri->rinfo->state_reg,
&ri->state_reg_cache);
- if (!ret && ri->force_reg)
- ret = tps80031_read(parent, ri->volt_id, ri->force_reg,
- &ri->force_reg_cache);
- if (!ret && ri->volt_reg)
- ret = tps80031_read(parent, ri->volt_id, ri->volt_reg,
- &ri->volt_reg_cache);
+ if (!ret && ri->rinfo->force_reg)
+ ret = tps80031_read(parent, ri->rinfo->volt_id,
+ ri->rinfo->force_reg, &ri->force_reg_cache);
+ if (!ret && ri->rinfo->volt_reg)
+ ret = tps80031_read(parent, ri->rinfo->volt_id,
+ ri->rinfo->volt_reg, &ri->volt_reg_cache);
return ret;
}
static int __devinit tps80031_regulator_probe(struct platform_device *pdev)
{
- struct tps80031_regulator *ri = NULL;
- struct regulator_dev *rdev;
+ struct tps80031_platform_data *pdata = dev_get_platdata(pdev->dev.parent);
struct tps80031_regulator_platform_data *tps_pdata;
- int id = pdev->id;
- int err;
-
- dev_dbg(&pdev->dev, "Probing reulator %d\n", id);
+ struct tps80031_regulator_info *rinfo;
+ struct tps80031_regulator *ri;
+ struct tps80031_regulator *pmic;
+ struct regulator_dev *rdev;
+ int id;
+ int ret;
+ int num;
- ri = find_regulator_info(id);
- if (ri == NULL) {
- dev_err(&pdev->dev, "invalid regulator ID specified\n");
+ if (!pdata || !pdata->num_regulator_pdata) {
+ dev_err(&pdev->dev, "Number of regulator is 0\n");
return -EINVAL;
}
- tps_pdata = pdev->dev.platform_data;
- ri->dev = &pdev->dev;
- if (tps_pdata->delay_us > 0)
- ri->delay = tps_pdata->delay_us;
- ri->tolerance_uv = tps_pdata->tolerance_uv;
-
- check_smps_mode_mult(pdev->dev.parent, ri);
- ri->platform_flags = tps_pdata->flags;
- ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag;
-
- err = tps80031_cache_regulator_register(pdev->dev.parent, ri);
- if (err) {
- dev_err(&pdev->dev, "Register access for caching is failed\n");
- return err;
- }
- err = tps80031_regulator_preinit(pdev->dev.parent, ri, tps_pdata);
- if (err)
- return err;
-
- err = tps80031_power_req_config(pdev->dev.parent, ri, tps_pdata);
- if (err)
- return err;
-
- rdev = regulator_register(&ri->desc, &pdev->dev,
- &tps_pdata->regulator, ri);
- if (IS_ERR_OR_NULL(rdev)) {
- dev_err(&pdev->dev, "failed to register regulator %s\n",
- ri->desc.name);
- return PTR_ERR(rdev);
+
+ pmic = devm_kzalloc(&pdev->dev,
+ pdata->num_regulator_pdata * sizeof(*pmic), GFP_KERNEL);
+ if (!pmic) {
+ dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+ return -ENOMEM;
}
- platform_set_drvdata(pdev, rdev);
+ for (num = 0; num < pdata->num_regulator_pdata; ++num) {
+ tps_pdata = pdata->regulator_pdata[num];
+ if (!tps_pdata->reg_init_data) {
+ dev_err(&pdev->dev,
+ "No regulator init data for index %d\n", num);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ id = tps_pdata->regulator_id;
+ rinfo = find_regulator_info(id);
+ if (!rinfo) {
+ dev_err(&pdev->dev, "invalid regulator ID specified\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ri = &pmic[num];
+ ri->rinfo = rinfo;
+ ri->dev = &pdev->dev;
+ if (tps_pdata->delay_us)
+ ri->delay = tps_pdata->delay_us;
+ else
+ ri->delay = rinfo->delay;
+ ri->tolerance_uv = tps_pdata->tolerance_uv;
+
+ check_smps_mode_mult(pdev->dev.parent, ri);
+ ri->platform_flags = tps_pdata->flags;
+ ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag;
+
+ ret = tps80031_cache_regulator_register(pdev->dev.parent, ri);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "Register cache failed, err %d\n", ret);
+ goto fail;
+ }
+ ret = tps80031_regulator_preinit(pdev->dev.parent, ri, tps_pdata);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "regulator preinit failed, err %d\n", ret);
+ goto fail;
+ }
+
+ ret = tps80031_power_req_config(pdev->dev.parent, ri, tps_pdata);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "power req config failed, err %d\n", ret);
+ goto fail;
+ }
+
+ rdev = regulator_register(&ri->rinfo->desc, &pdev->dev,
+ tps_pdata->reg_init_data, ri);
+ if (IS_ERR_OR_NULL(rdev)) {
+ dev_err(&pdev->dev,
+ "register regulator failed %s\n",
+ ri->rinfo->desc.name);
+ ret = PTR_ERR(rdev);
+ goto fail;
+ }
+ ri->rdev = rdev;
+ }
+ platform_set_drvdata(pdev, pmic);
return 0;
+fail:
+ while(--num >= 0) {
+ ri = &pmic[num];
+ regulator_unregister(ri->rdev);
+ }
+ return ret;
}
static int __devexit tps80031_regulator_remove(struct platform_device *pdev)
{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ struct tps80031_platform_data *pdata = pdev->dev.parent->platform_data;
+ struct tps80031_regulator *pmic = platform_get_drvdata(pdev);
+ struct tps80031_regulator *ri = NULL;
+ int num;
- regulator_unregister(rdev);
+ if (!pdata || !pdata->num_regulator_pdata)
+ return 0;
+
+ for (num = 0; num < pdata->num_regulator_pdata; ++num) {
+ ri = &pmic[num];
+ regulator_unregister(ri->rdev);
+ }
return 0;
}
static struct platform_driver tps80031_regulator_driver = {
.driver = {
- .name = "tps80031-regulator",
+ .name = "tps80031-regulators",
.owner = THIS_MODULE,
},
.probe = tps80031_regulator_probe,
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index be5b16284db0..249c25d2df88 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -102,6 +102,7 @@ obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o
obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
+CFLAGS_rtc-tegra.o = -Werror
obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o
obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o
diff --git a/drivers/rtc/alarm.c b/drivers/rtc/alarm.c
index 28b0df836a30..12e6f3c8acfb 100644
--- a/drivers/rtc/alarm.c
+++ b/drivers/rtc/alarm.c
@@ -33,6 +33,7 @@
#define ANDROID_ALARM_PRINT_FLOW (1U << 6)
static int debug_mask = ANDROID_ALARM_PRINT_ERROR | \
+ ANDROID_ALARM_PRINT_SUSPEND | \
ANDROID_ALARM_PRINT_INIT_STATUS;
module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
diff --git a/drivers/rtc/rtc-max77663.c b/drivers/rtc/rtc-max77663.c
index 13d8062e1def..d6dac76944d6 100644
--- a/drivers/rtc/rtc-max77663.c
+++ b/drivers/rtc/rtc-max77663.c
@@ -227,9 +227,10 @@ static inline int max77663_rtc_tm_to_reg(struct max77663_rtc *rtc, u8 *buf,
/* The wday is configured only when disabled alarm. */
if (!alarm)
buf[RTC_WEEKDAY] = (1 << tm->tm_wday);
- else
- buf[RTC_WEEKDAY] = 0;
-
+ else {
+ /* Configure its default reset value 0x01, and not enable it. */
+ buf[RTC_WEEKDAY] = 0x01;
+ }
return 0;
}
@@ -431,9 +432,9 @@ static int max77663_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->time.tm_wday);
if (rtc->irq_mask & RTC_IRQ_ALARM1_MASK)
- alrm->enabled = 1;
- else
alrm->enabled = 0;
+ else
+ alrm->enabled = 1;
return 0;
}
diff --git a/drivers/rtc/rtc-tps6591x.c b/drivers/rtc/rtc-tps6591x.c
index ebc46b4cf46e..9644dc4afb42 100644
--- a/drivers/rtc/rtc-tps6591x.c
+++ b/drivers/rtc/rtc-tps6591x.c
@@ -106,6 +106,7 @@ static int tps6591x_write_regs(struct device *dev, int reg, int len,
static int tps6591x_rtc_valid_tm(struct rtc_time *tm)
{
if (tm->tm_year >= (RTC_YEAR_OFFSET + 99)
+ || tm->tm_year < (RTC_YEAR_OFFSET)
|| tm->tm_mon >= 12
|| tm->tm_mday < 1
|| tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + OS_REF_YEAR)
@@ -245,6 +246,12 @@ static int tps6591x_rtc_set_time(struct device *dev, struct rtc_time *tm)
u8 buff[7];
int err;
+ err = tps6591x_rtc_valid_tm(tm);
+ if (err < 0) {
+ dev_err(dev->parent, "\n Invalid Time\n");
+ return err;
+ }
+
buff[0] = tm->tm_sec;
buff[1] = tm->tm_min;
buff[2] = tm->tm_hour;
@@ -323,6 +330,12 @@ static int tps6591x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (rtc->irq == -1)
return -EIO;
+ err = tps6591x_rtc_valid_tm(&alrm->time);
+ if (err < 0) {
+ dev_err(dev->parent, "\n Invalid alarm time\n");
+ return err;
+ }
+
dev_info(dev->parent, "\n setting alarm to requested time::\n");
print_time(dev->parent, &alrm->time);
rtc_tm_to_time(&alrm->time, &seconds);
@@ -461,13 +474,20 @@ static int __devinit tps6591x_rtc_probe(struct platform_device *pdev)
return -EBUSY;
}
+ err = tps6591x_rtc_start(&pdev->dev);
+ if (err) {
+ dev_err(&pdev->dev, "unable to start RTC\n");
+ return -EBUSY;
+ }
+
tps6591x_rtc_read_time(&pdev->dev, &tm);
- if ((tm.tm_year < RTC_YEAR_OFFSET || tm.tm_year > (RTC_YEAR_OFFSET + 99))){
- if (pdata->time.tm_year < 2000 || pdata->time.tm_year > 2100) {
+
+ if (tps6591x_rtc_valid_tm(&tm) < 0) {
+ if (pdata->time.tm_year < 2000 || pdata->time.tm_year >= 2100) {
memset(&pdata->time, 0, sizeof(pdata->time));
- pdata->time.tm_year = RTC_YEAR_OFFSET;
+ pdata->time.tm_year = 2000;
pdata->time.tm_mday = 1;
- } else
+ }
pdata->time.tm_year -= OS_REF_YEAR;
tps6591x_rtc_set_time(&pdev->dev, &pdata->time);
}
diff --git a/drivers/rtc/rtc-tps80031.c b/drivers/rtc/rtc-tps80031.c
index b2b9d04171c5..44013e13fe43 100644
--- a/drivers/rtc/rtc-tps80031.c
+++ b/drivers/rtc/rtc-tps80031.c
@@ -349,12 +349,20 @@ static irqreturn_t tps80031_rtc_irq(int irq, void *data)
static int __devinit tps80031_rtc_probe(struct platform_device *pdev)
{
- struct tps80031_rtc_platform_data *pdata = pdev->dev.platform_data;
+ struct tps80031_platform_data *tps80031_pdata;
+ struct tps80031_rtc_platform_data *pdata;
struct tps80031_rtc *rtc;
struct rtc_time tm;
int err;
u8 reg;
+ tps80031_pdata = dev_get_platdata(pdev->dev.parent);
+ if (!tps80031_pdata) {
+ dev_err(&pdev->dev, "no tps80031 platform_data specified\n");
+ return -EINVAL;
+ }
+
+ pdata = tps80031_pdata->rtc_pdata;
if (!pdata) {
dev_err(&pdev->dev, "no platform_data specified\n");
return -EINVAL;
@@ -469,7 +477,7 @@ static int __devexit tps80031_rtc_remove(struct platform_device *pdev)
static struct platform_driver tps80031_rtc_driver = {
.driver = {
- .name = "rtc_tps80031",
+ .name = "tps80031-rtc",
.owner = THIS_MODULE,
},
.probe = tps80031_rtc_probe,
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 430f8200108a..831e6eabee64 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -53,7 +53,9 @@ obj-$(CONFIG_SPI_SH) += spi-sh.o
obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
obj-$(CONFIG_SPI_STMP3XXX) += spi-stmp.o
+CFLAGS_spi-tegra.o = -Werror
obj-$(CONFIG_SPI_TEGRA) += spi-tegra.o
+CFLAGS_spi_slave_tegra.o = -Werror
obj-$(CONFIG_SPI_SLAVE_TEGRA) += spi_slave_tegra.o
obj-$(CONFIG_SPI_TI_SSP) += spi-ti-ssp.o
obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o
diff --git a/drivers/spi/spi-tegra.c b/drivers/spi/spi-tegra.c
index cf1b7bf40c62..5fca5e62706c 100644
--- a/drivers/spi/spi-tegra.c
+++ b/drivers/spi/spi-tegra.c
@@ -42,8 +42,6 @@
#include <mach/dma.h>
#include <mach/clk.h>
-#define SPI_PM_RUNTIME_ENABLE 0
-
#define SLINK_COMMAND 0x000
#define SLINK_BIT_LENGTH(x) (((x) & 0x1f) << 0)
#define SLINK_WORD_SIZE(x) (((x) & 0x1f) << 5)
@@ -249,9 +247,6 @@ struct spi_tegra_data {
struct work_struct spi_transfer_work;
};
-static int tegra_spi_runtime_idle(struct device *dev);
-static int tegra_spi_runtime_resume(struct device *dev);
-
static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi,
unsigned long reg)
{
@@ -308,22 +303,6 @@ static int tegra_spi_clk_enable(struct spi_tegra_data *tspi)
return 0;
}
-#if SPI_PM_RUNTIME_ENABLE
-#define spi_pm_runtime_get_sync(dev) pm_runtime_get_sync(dev)
-#define spi_pm_runtime_put_sync(dev) pm_runtime_put_sync(dev)
-#define spi_pm_runtime_enable(dev) pm_runtime_enable(dev)
-#define spi_pm_runtime_disable(dev) pm_runtime_disable(dev)
-#define spi_pm_runtime_enabled(dev) pm_runtime_enabled(dev)
-#define spi_pm_runtime_status_suspended(dev) pm_runtime_status_suspended(dev)
-#else
-#define spi_pm_runtime_get_sync(dev) tegra_spi_runtime_resume(dev)
-#define spi_pm_runtime_put_sync(dev) tegra_spi_runtime_idle(dev)
-#define spi_pm_runtime_enable(dev) do { } while(0)
-#define spi_pm_runtime_disable(dev) do { } while(0)
-#define spi_pm_runtime_enabled(dev) true
-#define spi_pm_runtime_status_suspended(dev) true
-#endif
-
static void cancel_dma(struct tegra_dma_channel *dma_chan,
struct tegra_dma_req *req)
{
@@ -794,12 +773,8 @@ static void spi_tegra_start_transfer(struct spi_device *spi,
command2 = tspi->def_command2_reg;
if (is_first_of_msg) {
- if ((ret = spi_pm_runtime_get_sync(&tspi->pdev->dev)) < 0) {
- dev_err(&tspi->pdev->dev,
- "%s: spi_pm_runtime_get_sync() returns %d\n",
- __func__, ret);
- return;
- }
+ pm_runtime_get_sync(&tspi->pdev->dev);
+ tegra_spi_clk_enable(tspi);
spi_tegra_clear_status(tspi);
@@ -911,7 +886,8 @@ static int spi_tegra_setup(struct spi_device *spi)
return -EINVAL;
}
- spi_pm_runtime_get_sync(&tspi->pdev->dev);
+ pm_runtime_get_sync(&tspi->pdev->dev);
+ tegra_spi_clk_enable(tspi);
spin_lock_irqsave(&tspi->lock, flags);
val = tspi->def_command_reg;
@@ -923,7 +899,8 @@ static int spi_tegra_setup(struct spi_device *spi)
spi_tegra_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
spin_unlock_irqrestore(&tspi->lock, flags);
- spi_pm_runtime_put_sync(&tspi->pdev->dev);
+ tegra_spi_clk_disable(tspi);
+ pm_runtime_put_sync(&tspi->pdev->dev);
return 0;
}
@@ -1073,7 +1050,8 @@ static void spi_tegra_curr_transfer_complete(struct spi_tegra_data *tspi,
/* Provide delay to stablize the signal state */
spin_unlock_irqrestore(&tspi->lock, *irq_flags);
udelay(10);
- spi_pm_runtime_put_sync(&tspi->pdev->dev);
+ tegra_spi_clk_disable(tspi);
+ pm_runtime_put_sync(&tspi->pdev->dev);
spin_lock_irqsave(&tspi->lock, *irq_flags);
tspi->is_transfer_in_progress = false;
/* Check if any new request has come between
@@ -1479,51 +1457,40 @@ static int __init spi_tegra_probe(struct platform_device *pdev)
tspi->def_command2_reg = SLINK_CS_ACTIVE_BETWEEN;
skip_dma_alloc:
- spi_pm_runtime_enable(&pdev->dev);
- if (!spi_pm_runtime_enabled(&pdev->dev)) {
- ret = tegra_spi_runtime_resume(&pdev->dev);
- if (ret) {
- dev_err(&pdev->dev, "runtime resume failed %d", ret);
- goto exit_pm_disable;
- }
- }
+ pm_runtime_enable(&pdev->dev);
/* Enable clock if it is require to be enable always */
if (tspi->is_clkon_always)
- spi_pm_runtime_get_sync(&pdev->dev);
-
- master->dev.of_node = pdev->dev.of_node;
- ret = spi_register_master(master);
- if (ret < 0) {
- dev_err(&pdev->dev, "can not register to master err %d\n", ret);
- goto exit_pm_suspend;
- }
+ tegra_spi_clk_enable(tspi);
- /* create the workqueue for the kbc path */
+ /* create the workqueue for the spi transfer */
snprintf(spi_wq_name, sizeof(spi_wq_name), "spi_tegra-%d", pdev->id);
tspi->spi_workqueue = create_singlethread_workqueue(spi_wq_name);
if (!tspi->spi_workqueue) {
dev_err(&pdev->dev, "Failed to create work queue\n");
ret = -ENODEV;
- goto exit_master_unregister;
+ goto exit_fail_wq;
}
INIT_WORK(&tspi->spi_transfer_work, tegra_spi_transfer_work);
+ master->dev.of_node = pdev->dev.of_node;
+ ret = spi_register_master(master);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can not register to master err %d\n", ret);
+ goto exit_destry_wq;
+ }
+
return ret;
-exit_master_unregister:
- spi_unregister_master(master);
+exit_destry_wq:
+ destroy_workqueue(tspi->spi_workqueue);
+exit_fail_wq:
if (tspi->is_clkon_always)
- spi_pm_runtime_put_sync(&pdev->dev);
-
-exit_pm_suspend:
- if (!spi_pm_runtime_status_suspended(&pdev->dev))
- tegra_spi_runtime_idle(&pdev->dev);
+ tegra_spi_clk_disable(tspi);
-exit_pm_disable:
- spi_pm_runtime_disable(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
spi_tegra_deinit_dma_param(tspi, false);
@@ -1553,11 +1520,9 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev)
/* Disable clock if it is always enabled */
if (tspi->is_clkon_always)
- spi_pm_runtime_put_sync(&pdev->dev);
+ tegra_spi_clk_disable(tspi);
- spi_pm_runtime_disable(&pdev->dev);
- if (!spi_pm_runtime_status_suspended(&pdev->dev))
- tegra_spi_runtime_idle(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
destroy_workqueue(tspi->spi_workqueue);
@@ -1612,7 +1577,7 @@ static int spi_tegra_suspend(struct device *dev)
/* Disable clock if it is always enabled */
if (tspi->is_clkon_always)
- spi_pm_runtime_put_sync(dev);
+ tegra_spi_clk_disable(tspi);
return 0;
}
@@ -1629,11 +1594,13 @@ static int spi_tegra_resume(struct device *dev)
/* Enable clock if it is always enabled */
if (tspi->is_clkon_always)
- spi_pm_runtime_get_sync(dev);
+ tegra_spi_clk_enable(tspi);
- spi_pm_runtime_get_sync(dev);
+ pm_runtime_get_sync(dev);
+ tegra_spi_clk_enable(tspi);
spi_tegra_writel(tspi, tspi->command_reg, SLINK_COMMAND);
- spi_pm_runtime_put_sync(dev);
+ tegra_spi_clk_disable(tspi);
+ pm_runtime_put_sync(dev);
spin_lock_irqsave(&tspi->lock, flags);
@@ -1656,27 +1623,7 @@ static int spi_tegra_resume(struct device *dev)
}
#endif
-static int tegra_spi_runtime_idle(struct device *dev)
-{
- struct spi_master *master = dev_get_drvdata(dev);
- struct spi_tegra_data *tspi = spi_master_get_devdata(master);
-
- return tegra_spi_clk_disable(tspi);
-}
-
-static int tegra_spi_runtime_resume(struct device *dev)
-{
- struct spi_master *master = dev_get_drvdata(dev);
- struct spi_tegra_data *tspi = spi_master_get_devdata(master);
-
- return tegra_spi_clk_enable(tspi);
-}
-
static const struct dev_pm_ops tegra_spi_dev_pm_ops = {
-#if defined(CONFIG_PM_RUNTIME)
- .runtime_idle = tegra_spi_runtime_idle,
- .runtime_resume = tegra_spi_runtime_resume,
-#endif
#ifdef CONFIG_PM
.suspend = spi_tegra_suspend,
.resume = spi_tegra_resume,
diff --git a/drivers/spi/spi_slave_tegra.c b/drivers/spi/spi_slave_tegra.c
index 7ee53730e736..e6bce127cae3 100644
--- a/drivers/spi/spi_slave_tegra.c
+++ b/drivers/spi/spi_slave_tegra.c
@@ -417,7 +417,7 @@ static unsigned int spi_tegra_read_rx_fifo_to_client_rxbuf(
u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos;
unsigned i, count;
unsigned long x;
- unsigned int read_words;
+ unsigned int read_words = 0;
unsigned len;
fifo_status = spi_tegra_readl(tspi, SLINK_STATUS2);
diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c
index fa76ce7678a6..3e09d57dc6d9 100644
--- a/drivers/staging/android/logger.c
+++ b/drivers/staging/android/logger.c
@@ -57,6 +57,8 @@ struct logger_reader {
struct logger_log *log; /* associated log */
struct list_head list; /* entry in logger_log's list */
size_t r_off; /* current read head offset */
+ bool r_all; /* reader can read all entries */
+ int r_ver; /* reader ABI version */
};
/* logger_offset - returns index 'n' into the log via (optimized) modulus */
@@ -86,25 +88,71 @@ static inline struct logger_log *file_get_log(struct file *file)
}
/*
- * get_entry_len - Grabs the length of the payload of the next entry starting
- * from 'off'.
+ * get_entry_header - returns a pointer to the logger_entry header within
+ * 'log' starting at offset 'off'. A temporary logger_entry 'scratch' must
+ * be provided. Typically the return value will be a pointer within
+ * 'logger->buf'. However, a pointer to 'scratch' may be returned if
+ * the log entry spans the end and beginning of the circular buffer.
+ */
+static struct logger_entry *get_entry_header(struct logger_log *log,
+ size_t off, struct logger_entry *scratch)
+{
+ size_t len = min(sizeof(struct logger_entry), log->size - off);
+ if (len != sizeof(struct logger_entry)) {
+ memcpy(((void *) scratch), log->buffer + off, len);
+ memcpy(((void *) scratch) + len, log->buffer,
+ sizeof(struct logger_entry) - len);
+ return scratch;
+ }
+
+ return (struct logger_entry *) (log->buffer + off);
+}
+
+/*
+ * get_entry_msg_len - Grabs the length of the message of the entry
+ * starting from from 'off'.
*
* Caller needs to hold log->mutex.
*/
-static __u32 get_entry_len(struct logger_log *log, size_t off)
+static __u32 get_entry_msg_len(struct logger_log *log, size_t off)
{
- __u16 val;
+ struct logger_entry scratch;
+ struct logger_entry *entry;
- switch (log->size - off) {
- case 1:
- memcpy(&val, log->buffer + off, 1);
- memcpy(((char *) &val) + 1, log->buffer, 1);
- break;
- default:
- memcpy(&val, log->buffer + off, 2);
+ entry = get_entry_header(log, off, &scratch);
+ return entry->len;
+}
+
+static size_t get_user_hdr_len(int ver)
+{
+ if (ver < 2)
+ return sizeof(struct user_logger_entry_compat);
+ else
+ return sizeof(struct logger_entry);
+}
+
+static ssize_t copy_header_to_user(int ver, struct logger_entry *entry,
+ char __user *buf)
+{
+ void *hdr;
+ size_t hdr_len;
+ struct user_logger_entry_compat v1;
+
+ if (ver < 2) {
+ v1.len = entry->len;
+ v1.__pad = 0;
+ v1.pid = entry->pid;
+ v1.tid = entry->tid;
+ v1.sec = entry->sec;
+ v1.nsec = entry->nsec;
+ hdr = &v1;
+ hdr_len = sizeof(struct user_logger_entry_compat);
+ } else {
+ hdr = entry;
+ hdr_len = sizeof(struct logger_entry);
}
- return sizeof(struct logger_entry) + val;
+ return copy_to_user(buf, hdr, hdr_len);
}
/*
@@ -118,15 +166,30 @@ static ssize_t do_read_log_to_user(struct logger_log *log,
char __user *buf,
size_t count)
{
+ struct logger_entry scratch;
+ struct logger_entry *entry;
size_t len;
+ size_t msg_start;
/*
- * We read from the log in two disjoint operations. First, we read from
- * the current read head offset up to 'count' bytes or to the end of
+ * First, copy the header to userspace, using the version of
+ * the header requested
+ */
+ entry = get_entry_header(log, reader->r_off, &scratch);
+ if (copy_header_to_user(reader->r_ver, entry, buf))
+ return -EFAULT;
+
+ count -= get_user_hdr_len(reader->r_ver);
+ buf += get_user_hdr_len(reader->r_ver);
+ msg_start = logger_offset(reader->r_off + sizeof(struct logger_entry));
+
+ /*
+ * We read from the msg in two disjoint operations. First, we read from
+ * the current msg head offset up to 'count' bytes or to the end of
* the log, whichever comes first.
*/
- len = min(count, log->size - reader->r_off);
- if (copy_to_user(buf, log->buffer + reader->r_off, len))
+ len = min(count, log->size - msg_start);
+ if (copy_to_user(buf, log->buffer + msg_start, len))
return -EFAULT;
/*
@@ -137,9 +200,34 @@ static ssize_t do_read_log_to_user(struct logger_log *log,
if (copy_to_user(buf + len, log->buffer, count - len))
return -EFAULT;
- reader->r_off = logger_offset(reader->r_off + count);
+ reader->r_off = logger_offset(reader->r_off +
+ sizeof(struct logger_entry) + count);
- return count;
+ return count + get_user_hdr_len(reader->r_ver);
+}
+
+/*
+ * get_next_entry_by_uid - Starting at 'off', returns an offset into
+ * 'log->buffer' which contains the first entry readable by 'euid'
+ */
+static size_t get_next_entry_by_uid(struct logger_log *log,
+ size_t off, uid_t euid)
+{
+ while (off != log->w_off) {
+ struct logger_entry *entry;
+ struct logger_entry scratch;
+ size_t next_len;
+
+ entry = get_entry_header(log, off, &scratch);
+
+ if (entry->euid == euid)
+ return off;
+
+ next_len = sizeof(struct logger_entry) + entry->len;
+ off = logger_offset(off + next_len);
+ }
+
+ return off;
}
/*
@@ -151,7 +239,7 @@ static ssize_t do_read_log_to_user(struct logger_log *log,
* - If there are no log entries to read, blocks until log is written to
* - Atomically reads exactly one log entry
*
- * Optimal read size is LOGGER_ENTRY_MAX_LEN. Will set errno to EINVAL if read
+ * Will set errno to EINVAL if read
* buffer is insufficient to hold next entry.
*/
static ssize_t logger_read(struct file *file, char __user *buf,
@@ -191,6 +279,10 @@ start:
mutex_lock(&log->mutex);
+ if (!reader->r_all)
+ reader->r_off = get_next_entry_by_uid(log,
+ reader->r_off, current_euid());
+
/* is there still something to read or did we race? */
if (unlikely(log->w_off == reader->r_off)) {
mutex_unlock(&log->mutex);
@@ -198,7 +290,8 @@ start:
}
/* get the size of the next entry */
- ret = get_entry_len(log, reader->r_off);
+ ret = get_user_hdr_len(reader->r_ver) +
+ get_entry_msg_len(log, reader->r_off);
if (count < ret) {
ret = -EINVAL;
goto out;
@@ -224,7 +317,8 @@ static size_t get_next_entry(struct logger_log *log, size_t off, size_t len)
size_t count = 0;
do {
- size_t nr = get_entry_len(log, off);
+ size_t nr = sizeof(struct logger_entry) +
+ get_entry_msg_len(log, off);
off = logger_offset(off + nr);
count += nr;
} while (count < len);
@@ -336,7 +430,9 @@ ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
header.tid = current->pid;
header.sec = now.tv_sec;
header.nsec = now.tv_nsec;
+ header.euid = current_euid();
header.len = min_t(size_t, iocb->ki_left, LOGGER_ENTRY_MAX_PAYLOAD);
+ header.hdr_size = sizeof(struct logger_entry);
/* null writes succeed, return zero */
if (unlikely(!header.len))
@@ -409,6 +505,10 @@ static int logger_open(struct inode *inode, struct file *file)
return -ENOMEM;
reader->log = log;
+ reader->r_ver = 1;
+ reader->r_all = in_egroup_p(inode->i_gid) ||
+ capable(CAP_SYSLOG);
+
INIT_LIST_HEAD(&reader->list);
mutex_lock(&log->mutex);
@@ -463,6 +563,10 @@ static unsigned int logger_poll(struct file *file, poll_table *wait)
poll_wait(file, &log->wq, wait);
mutex_lock(&log->mutex);
+ if (!reader->r_all)
+ reader->r_off = get_next_entry_by_uid(log,
+ reader->r_off, current_euid());
+
if (log->w_off != reader->r_off)
ret |= POLLIN | POLLRDNORM;
mutex_unlock(&log->mutex);
@@ -470,11 +574,25 @@ static unsigned int logger_poll(struct file *file, poll_table *wait)
return ret;
}
+static long logger_set_version(struct logger_reader *reader, void __user *arg)
+{
+ int version;
+ if (copy_from_user(&version, arg, sizeof(int)))
+ return -EFAULT;
+
+ if ((version < 1) || (version > 2))
+ return -EINVAL;
+
+ reader->r_ver = version;
+ return 0;
+}
+
static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct logger_log *log = file_get_log(file);
struct logger_reader *reader;
- long ret = -ENOTTY;
+ long ret = -EINVAL;
+ void __user *argp = (void __user *) arg;
mutex_lock(&log->mutex);
@@ -499,8 +617,14 @@ static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
}
reader = file->private_data;
+
+ if (!reader->r_all)
+ reader->r_off = get_next_entry_by_uid(log,
+ reader->r_off, current_euid());
+
if (log->w_off != reader->r_off)
- ret = get_entry_len(log, reader->r_off);
+ ret = get_user_hdr_len(reader->r_ver) +
+ get_entry_msg_len(log, reader->r_off);
else
ret = 0;
break;
@@ -514,6 +638,22 @@ static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
log->head = log->w_off;
ret = 0;
break;
+ case LOGGER_GET_VERSION:
+ if (!(file->f_mode & FMODE_READ)) {
+ ret = -EBADF;
+ break;
+ }
+ reader = file->private_data;
+ ret = reader->r_ver;
+ break;
+ case LOGGER_SET_VERSION:
+ if (!(file->f_mode & FMODE_READ)) {
+ ret = -EBADF;
+ break;
+ }
+ reader = file->private_data;
+ ret = logger_set_version(reader, argp);
+ break;
}
mutex_unlock(&log->mutex);
@@ -534,8 +674,8 @@ static const struct file_operations logger_fops = {
/*
* Defines a log structure with name 'NAME' and a size of 'SIZE' bytes, which
- * must be a power of two, greater than LOGGER_ENTRY_MAX_LEN, and less than
- * LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
+ * must be a power of two, and greater than
+ * (LOGGER_ENTRY_MAX_PAYLOAD + sizeof(struct logger_entry)).
*/
#define DEFINE_LOGGER_DEVICE(VAR, NAME, SIZE) \
static unsigned char _buf_ ## VAR[SIZE]; \
diff --git a/drivers/staging/android/logger.h b/drivers/staging/android/logger.h
index 2cb06e9d8f98..3f612a3b101c 100644
--- a/drivers/staging/android/logger.h
+++ b/drivers/staging/android/logger.h
@@ -20,7 +20,12 @@
#include <linux/types.h>
#include <linux/ioctl.h>
-struct logger_entry {
+/*
+ * The userspace structure for version 1 of the logger_entry ABI.
+ * This structure is returned to userspace unless the caller requests
+ * an upgrade to a newer ABI version.
+ */
+struct user_logger_entry_compat {
__u16 len; /* length of the payload */
__u16 __pad; /* no matter what, we get 2 bytes of padding */
__s32 pid; /* generating process's pid */
@@ -30,14 +35,28 @@ struct logger_entry {
char msg[0]; /* the entry's payload */
};
+/*
+ * The structure for version 2 of the logger_entry ABI.
+ * This structure is returned to userspace if ioctl(LOGGER_SET_VERSION)
+ * is called with version >= 2
+ */
+struct logger_entry {
+ __u16 len; /* length of the payload */
+ __u16 hdr_size; /* sizeof(struct logger_entry_v2) */
+ __s32 pid; /* generating process's pid */
+ __s32 tid; /* generating process's tid */
+ __s32 sec; /* seconds since Epoch */
+ __s32 nsec; /* nanoseconds */
+ uid_t euid; /* effective UID of logger */
+ char msg[0]; /* the entry's payload */
+};
+
#define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */
#define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */
#define LOGGER_LOG_SYSTEM "log_system" /* system/framework messages */
#define LOGGER_LOG_MAIN "log_main" /* everything else */
-#define LOGGER_ENTRY_MAX_LEN (4*1024)
-#define LOGGER_ENTRY_MAX_PAYLOAD \
- (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
+#define LOGGER_ENTRY_MAX_PAYLOAD 4076
#define __LOGGERIO 0xAE
@@ -45,5 +64,7 @@ struct logger_entry {
#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */
#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */
#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */
+#define LOGGER_GET_VERSION _IO(__LOGGERIO, 5) /* abi version */
+#define LOGGER_SET_VERSION _IO(__LOGGERIO, 6) /* abi version */
#endif /* _LINUX_LOGGER_H */
diff --git a/drivers/staging/brcm80211/Kconfig b/drivers/staging/brcm80211/Kconfig
index 379cf16e89f7..586de7f74f5f 100644
--- a/drivers/staging/brcm80211/Kconfig
+++ b/drivers/staging/brcm80211/Kconfig
@@ -21,7 +21,6 @@ config BRCMFMAC
default n
depends on MMC
depends on WLAN && CFG80211
- depends on X86 || MIPS
select BRCMUTIL
select FW_LOADER
select WIRELESS_EXT
diff --git a/drivers/staging/brcm80211/Makefile b/drivers/staging/brcm80211/Makefile
index 8b01f5e7ba25..b595cab91e0b 100644
--- a/drivers/staging/brcm80211/Makefile
+++ b/drivers/staging/brcm80211/Makefile
@@ -16,8 +16,8 @@
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# common flags
-subdir-ccflags-y := -DBCMDMA32
-subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG
+subdir-ccflags-y := -DBCMDMA32
+subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG -DBCMDBG_ASSERT
obj-$(CONFIG_BRCMUTIL) += brcmutil/
obj-$(CONFIG_BRCMFMAC) += brcmfmac/
diff --git a/drivers/staging/brcm80211/README b/drivers/staging/brcm80211/README
index bb86b1b3e58e..8ad558675bd3 100644
--- a/drivers/staging/brcm80211/README
+++ b/drivers/staging/brcm80211/README
@@ -1 +1,64 @@
-refer to: http://linuxwireless.org/en/users/Drivers/brcm80211
+Broadcom brcmsmac (mac80211-based softmac PCIe) and brcmfmac (SDIO) drivers.
+
+Completely open source host drivers, no binary object files.
+
+Support for the following chips:
+===============================
+
+ brcmsmac (PCIe)
+ Name Device ID
+ BCM4313 0x4727
+ BCM43224 0x4353
+ BCM43225 0x4357
+
+ brcmfmac (SDIO)
+ Name
+ BCM4329
+
+Both brcmsmac and brcmfmac drivers require firmware files that need to be
+separately downloaded.
+
+Firmware
+======================
+Firmware is available from the Linux firmware repository at:
+
+ git://git.kernel.org/pub/scm/linux/kernel/git/dwmw2/linux-firmware.git
+ http://git.kernel.org/?p=linux/kernel/git/dwmw2/linux-firmware.git
+ https://git.kernel.org/?p=linux/kernel/git/dwmw2/linux-firmware.git
+
+
+===============================================================
+Broadcom brcmsmac driver
+===============================================================
+- Support for both 32 and 64 bit Linux kernels
+
+
+Firmware installation
+======================
+Copy brcm/bcm43xx-0.fw and brcm/bcm43xx_hdr-0.fw to
+/lib/firmware/brcm (or wherever firmware is normally installed
+on your system).
+
+
+===============================================================
+Broadcom brcmfmac driver
+===============================================================
+- Support for 32 bit Linux kernel, 64 bit untested
+
+
+Firmware installation
+======================
+Copy brcm/bcm4329-fullmac-4.bin and brcm/bcm4329-fullmac-4.txt
+to /lib/firmware/brcm (or wherever firmware is normally installed on your
+system).
+
+
+Contact Info:
+=============
+Brett Rudley brudley@broadcom.com
+Henry Ptasinski henryp@broadcom.com
+Dowan Kim dowan@broadcom.com
+Roland Vossen rvossen@broadcom.com
+Arend van Spriel arend@broadcom.com
+
+For more info, refer to: http://linuxwireless.org/en/users/Drivers/brcm80211
diff --git a/drivers/staging/brcm80211/TODO b/drivers/staging/brcm80211/TODO
deleted file mode 100644
index e2e2ef9bd7ac..000000000000
--- a/drivers/staging/brcm80211/TODO
+++ /dev/null
@@ -1,13 +0,0 @@
-To Do List for Broadcom Mac80211 driver before getting in mainline
-
-Bugs
-====
-- none known at this moment
-
-brcmfmac
-=====================
-- ASSERTS deprecated in mainline, replace by warning + error handling
-
-brcm80211 info page
-=====================
-http://linuxwireless.org/en/users/Drivers/brcm80211
diff --git a/drivers/staging/brcm80211/brcmfmac/Makefile b/drivers/staging/brcm80211/brcmfmac/Makefile
index da3c80575907..71c7fe94ece8 100644
--- a/drivers/staging/brcm80211/brcmfmac/Makefile
+++ b/drivers/staging/brcm80211/brcmfmac/Makefile
@@ -15,17 +15,12 @@
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-ccflags-y := \
- -DBRCMF_FIRSTREAD=64 \
- -DBRCMF_SDALIGN=64 \
- -DMAX_HDR_READ=64
-
-ccflags-$(CONFIG_BRCMDBG) += -DSHOW_EVENTS
-
ccflags-y += \
-Idrivers/staging/brcm80211/brcmfmac \
-Idrivers/staging/brcm80211/include
+ccflags-y += -DISR_THREAD
+
DHDOFILES = \
wl_cfg80211.o \
dhd_cdc.o \
@@ -37,3 +32,4 @@ DHDOFILES = \
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
brcmfmac-objs += $(DHDOFILES)
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
index f4e72ed126b0..bff9dcd6fadc 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
@@ -21,6 +21,9 @@
#include <linux/pci_ids.h>
#include <linux/sched.h>
#include <linux/completion.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
#include <defs.h>
#include <brcm_hw_ids.h>
@@ -29,304 +32,103 @@
#include <soc.h>
#include "dhd.h"
#include "dhd_bus.h"
+#include "dhd_dbg.h"
#include "sdio_host.h"
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
-#define BRCMF_SD_ERROR_VAL 0x0001 /* Error */
-#define BRCMF_SD_INFO_VAL 0x0002 /* Info */
-
-
-#ifdef BCMDBG
-#define BRCMF_SD_ERROR(x) \
- do { \
- if ((brcmf_sdio_msglevel & BRCMF_SD_ERROR_VAL) && \
- net_ratelimit()) \
- printk x; \
- } while (0)
-#define BRCMF_SD_INFO(x) \
- do { \
- if ((brcmf_sdio_msglevel & BRCMF_SD_INFO_VAL) && \
- net_ratelimit()) \
- printk x; \
- } while (0)
-#else /* BCMDBG */
-#define BRCMF_SD_ERROR(x)
-#define BRCMF_SD_INFO(x)
-#endif /* BCMDBG */
-
-/* debugging macros */
-#define SDLX_MSG(x)
-
-#define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */
-#define SDIOH_CMD_TYPE_APPEND 1 /* Append command */
-#define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */
-
-#define SDIOH_DATA_PIO 0 /* PIO mode */
-#define SDIOH_DATA_DMA 1 /* DMA mode */
-
-struct brcmf_sdio_card {
- bool init_success; /* underlying driver successfully attached */
- void *sdioh; /* handler for sdioh */
- u32 vendevid; /* Target Vendor and Device ID on SD bus */
- bool regfail; /* Save status of last
- reg_read/reg_write call */
- u32 sbwad; /* Save backplane window address */
-};
-
-/**
- * SDIO Host Controller info
- */
-struct sdio_hc {
- struct sdio_hc *next;
- struct device *dev; /* platform device handle */
- void *regs; /* SDIO Host Controller address */
- struct brcmf_sdio_card *card;
- void *ch;
- unsigned int oob_irq;
- unsigned long oob_flags; /* OOB Host specifiction
- as edge and etc */
- bool oob_irq_registered;
-};
-
-/* local copy of bcm sd handler */
-static struct brcmf_sdio_card *l_card;
-
-const uint brcmf_sdio_msglevel = BRCMF_SD_ERROR_VAL;
-
-static struct sdio_hc *sdhcinfo;
-
-/* driver info, initialized when brcmf_sdio_register is called */
-static struct brcmf_sdioh_driver drvinfo = { NULL, NULL };
-
-/* Module parameters specific to each host-controller driver */
-
-module_param(sd_msglevel, uint, 0);
-
-extern uint sd_f2_blocksize;
-module_param(sd_f2_blocksize, int, 0);
-
-/* forward declarations */
-int brcmf_sdio_probe(struct device *dev);
-EXPORT_SYMBOL(brcmf_sdio_probe);
-
-int brcmf_sdio_remove(struct device *dev);
-EXPORT_SYMBOL(brcmf_sdio_remove);
-
-struct brcmf_sdio_card*
-brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq)
+static void brcmf_sdioh_irqhandler(struct sdio_func *func)
{
- struct brcmf_sdio_card *card;
+ struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
- card = kzalloc(sizeof(struct brcmf_sdio_card), GFP_ATOMIC);
- if (card == NULL) {
- BRCMF_SD_ERROR(("sdcard_attach: out of memory"));
- return NULL;
- }
-
- /* save the handler locally */
- l_card = card;
-
- card->sdioh = brcmf_sdioh_attach(cfghdl, irq);
- if (!card->sdioh) {
- brcmf_sdcard_detach(card);
- return NULL;
- }
+ brcmf_dbg(TRACE, "***IRQHandler\n");
- card->init_success = true;
+ sdio_release_host(func);
- *regsva = SI_ENUM_BASE;
+ brcmf_sdbrcm_isr(sdiodev->bus);
- /* Report the BAR, to fix if needed */
- card->sbwad = SI_ENUM_BASE;
- return card;
+ sdio_claim_host(func);
}
-int brcmf_sdcard_detach(struct brcmf_sdio_card *card)
+int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
{
- if (card != NULL) {
- if (card->sdioh) {
- brcmf_sdioh_detach(card->sdioh);
- card->sdioh = NULL;
- }
- kfree(card);
- }
-
- l_card = NULL;
- return 0;
-}
+ brcmf_dbg(TRACE, "Entering\n");
-int
-brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
- void *params, int plen, void *arg, int len, bool set)
-{
- return brcmf_sdioh_iovar_op(card->sdioh, name, params, plen, arg,
- len, set);
-}
+ sdio_claim_host(sdiodev->func[1]);
+ sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler);
+ sdio_release_host(sdiodev->func[1]);
-int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card)
-{
- return brcmf_sdioh_interrupt_set(card->sdioh, true);
+ return 0;
}
-int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card)
+int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
{
- return brcmf_sdioh_interrupt_set(card->sdioh, false);
-}
+ brcmf_dbg(TRACE, "Entering\n");
-int brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
- void (*fn)(void *), void *argh)
-{
- return brcmf_sdioh_interrupt_register(card->sdioh, fn, argh);
-}
+ sdio_claim_host(sdiodev->func[1]);
+ sdio_release_irq(sdiodev->func[1]);
+ sdio_release_host(sdiodev->func[1]);
-int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card)
-{
- return brcmf_sdioh_interrupt_deregister(card->sdioh);
+ return 0;
}
-u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
+u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
int *err)
{
int status;
s32 retry = 0;
u8 data = 0;
- if (!card)
- card = l_card;
-
do {
if (retry) /* wait for 1 ms till bus get settled down */
udelay(1000);
- status =
- brcmf_sdioh_cfg_read(card->sdioh, fnc_num, addr,
- (u8 *) &data);
+ status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num,
+ addr, (u8 *) &data);
} while (status != 0
&& (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
if (err)
*err = status;
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
- __func__, fnc_num, addr, data));
+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
+ fnc_num, addr, data);
return data;
}
void
-brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
+brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
u8 data, int *err)
{
int status;
s32 retry = 0;
- if (!card)
- card = l_card;
-
do {
if (retry) /* wait for 1 ms till bus get settled down */
udelay(1000);
- status =
- brcmf_sdioh_cfg_write(card->sdioh, fnc_num, addr,
- (u8 *) &data);
+ status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num,
+ addr, (u8 *) &data);
} while (status != 0
&& (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
if (err)
*err = status;
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
- __func__, fnc_num, addr, data));
+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
+ fnc_num, addr, data);
}
-u32 brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
- u32 addr, int *err)
-{
- int status;
- u32 data = 0;
-
- if (!card)
- card = l_card;
-
- status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
- SDIOH_READ, fnc_num, addr, &data, 4);
-
- if (err)
- *err = status;
-
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
- __func__, fnc_num, addr, data));
-
- return data;
-}
-
-void
-brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card, uint fnc_num,
- u32 addr, u32 data, int *err)
-{
- int status;
-
- if (!card)
- card = l_card;
-
- status =
- brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
- SDIOH_WRITE, fnc_num, addr, &data, 4);
-
- if (err)
- *err = status;
-
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
- __func__, fnc_num, addr, data));
-}
-
-int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func, u8 * cis,
- uint length)
-{
- int status;
-
- u8 *tmp_buf, *tmp_ptr;
- u8 *ptr;
- bool ascii = func & ~0xf;
- func &= 0x7;
-
- if (!card)
- card = l_card;
-
- status = brcmf_sdioh_cis_read(card->sdioh, func, cis, length);
-
- if (ascii) {
- /* Move binary bits to tmp and format them
- into the provided buffer. */
- tmp_buf = kmalloc(length, GFP_ATOMIC);
- if (tmp_buf == NULL) {
- BRCMF_SD_ERROR(("%s: out of memory\n", __func__));
- return -ENOMEM;
- }
- memcpy(tmp_buf, cis, length);
- for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
- tmp_ptr++) {
- ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
- if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
- ptr += sprintf((char *)ptr, "\n");
- }
- kfree(tmp_buf);
- }
-
- return status;
-}
-
-static int
-brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card *card, u32 address)
+int
+brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
{
int err = 0;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
(address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
if (!err)
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_SBADDRMID,
(address >> 16) & SBSDIO_SBADDRMID_MASK,
&err);
if (!err)
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_SBADDRHIGH,
(address >> 24) & SBSDIO_SBADDRHIGH_MASK,
&err);
@@ -334,34 +136,31 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card *card, u32 address)
return err;
}
-u32 brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size)
+u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size)
{
int status;
u32 word = 0;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
- BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
-
- if (!card)
- card = l_card;
+ brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr);
- if (bar0 != card->sbwad) {
- if (brcmf_sdcard_set_sbaddr_window(card, bar0))
+ if (bar0 != sdiodev->sbwad) {
+ if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0))
return 0xFFFFFFFF;
- card->sbwad = bar0;
+ sdiodev->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
if (size == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
- SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
+ status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1,
+ addr, &word, size);
- card->regfail = (status != 0);
+ sdiodev->regfail = (status != 0);
- BRCMF_SD_INFO(("u32data = 0x%x\n", word));
+ brcmf_dbg(INFO, "u32data = 0x%x\n", word);
/* if ok, return appropriately masked word */
if (status == 0) {
@@ -373,66 +172,59 @@ u32 brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size)
case sizeof(u32):
return word;
default:
- card->regfail = true;
+ sdiodev->regfail = true;
}
}
/* otherwise, bad sdio access or invalid size */
- BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
- addr, size));
+ brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size);
return 0xFFFFFFFF;
}
-u32 brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
+u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
u32 data)
{
int status;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
- BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
- __func__, addr, size * 8, data));
-
- if (!card)
- card = l_card;
+ brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
+ addr, size * 8, data);
- if (bar0 != card->sbwad) {
- err = brcmf_sdcard_set_sbaddr_window(card, bar0);
+ if (bar0 != sdiodev->sbwad) {
+ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
if (err)
return err;
- card->sbwad = bar0;
+ sdiodev->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
if (size == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
status =
- brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
- SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
- card->regfail = (status != 0);
+ brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1,
+ addr, &data, size);
+ sdiodev->regfail = (status != 0);
if (status == 0)
return 0;
- BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
- __func__, data, addr, size));
+ brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n",
+ data, addr, size);
return 0xFFFFFFFF;
}
-bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card)
+bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev)
{
- return card->regfail;
+ return sdiodev->regfail;
}
int
-brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
+brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags,
- u8 *buf, uint nbytes, struct sk_buff *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle)
+ u8 *buf, uint nbytes, struct sk_buff *pkt)
{
int status;
uint incr_fix;
@@ -440,19 +232,18 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
- __func__, fn, addr, nbytes));
+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes);
/* Async not implemented yet */
if (flags & SDIO_REQ_ASYNC)
return -ENOTSUPP;
- if (bar0 != card->sbwad) {
- err = brcmf_sdcard_set_sbaddr_window(card, bar0);
+ if (bar0 != sdiodev->sbwad) {
+ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
if (err)
return err;
- card->sbwad = bar0;
+ sdiodev->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
@@ -462,37 +253,33 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
if (width == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- status = brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
- incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
+ status = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
+ fn, addr, width, nbytes, buf, pkt);
return status;
}
int
-brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
- uint flags, u8 *buf, uint nbytes, void *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle)
+brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt)
{
uint incr_fix;
uint width;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
- __func__, fn, addr, nbytes));
+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes);
/* Async not implemented yet */
if (flags & SDIO_REQ_ASYNC)
return -ENOTSUPP;
- if (bar0 != card->sbwad) {
- err = brcmf_sdcard_set_sbaddr_window(card, bar0);
+ if (bar0 != sdiodev->sbwad) {
+ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
if (err)
return err;
- card->sbwad = bar0;
+ sdiodev->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
@@ -502,141 +289,83 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
if (width == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
- incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
+ return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
+ addr, width, nbytes, buf, pkt);
}
-int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
+int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
u8 *buf, uint nbytes)
{
addr &= SBSDIO_SB_OFT_ADDR_MASK;
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
- SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
+ return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC,
+ (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
addr, 4, nbytes, buf, NULL);
}
-int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn)
+int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
{
- return brcmf_sdioh_abort(card->sdioh, fn);
-}
-
-int brcmf_sdcard_query_device(struct brcmf_sdio_card *card)
-{
- card->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0;
- return card->vendevid;
-}
+ char t_func = (char)fn;
+ brcmf_dbg(TRACE, "Enter\n");
-u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card)
-{
- if (!card)
- card = l_card;
+ /* issue abort cmd52 command through F0 */
+ brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
+ SDIO_CCCR_ABORT, &t_func);
- return card->sbwad;
+ brcmf_dbg(TRACE, "Exit\n");
+ return 0;
}
-int brcmf_sdio_probe(struct device *dev)
+int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
{
- struct sdio_hc *sdhc = NULL;
u32 regs = 0;
- struct brcmf_sdio_card *card = NULL;
- int irq = 0;
- u32 vendevid;
- unsigned long irq_flags = 0;
-
- /* allocate SDIO Host Controller state info */
- sdhc = kzalloc(sizeof(struct sdio_hc), GFP_ATOMIC);
- if (!sdhc) {
- SDLX_MSG(("%s: out of memory\n", __func__));
- goto err;
- }
- sdhc->dev = (void *)dev;
+ int ret = 0;
- card = brcmf_sdcard_attach((void *)0, &regs, irq);
- if (!card) {
- SDLX_MSG(("%s: attach failed\n", __func__));
- goto err;
- }
+ ret = brcmf_sdioh_attach(sdiodev);
+ if (ret)
+ goto out;
- sdhc->card = card;
- sdhc->oob_irq = irq;
- sdhc->oob_flags = irq_flags;
- sdhc->oob_irq_registered = false; /* to make sure.. */
+ regs = SI_ENUM_BASE;
- /* chain SDIO Host Controller info together */
- sdhc->next = sdhcinfo;
- sdhcinfo = sdhc;
- /* Read the vendor/device ID from the CIS */
- vendevid = brcmf_sdcard_query_device(card);
+ /* Report the BAR, to fix if needed */
+ sdiodev->sbwad = SI_ENUM_BASE;
/* try to attach to the target device */
- sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
- 0, 0, 0, 0, regs, card);
- if (!sdhc->ch) {
- SDLX_MSG(("%s: device attach failed\n", __func__));
- goto err;
+ sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev);
+ if (!sdiodev->bus) {
+ brcmf_dbg(ERROR, "device attach failed\n");
+ ret = -ENODEV;
+ goto out;
}
- return 0;
-
- /* error handling */
-err:
- if (sdhc) {
- if (sdhc->card)
- brcmf_sdcard_detach(sdhc->card);
- kfree(sdhc);
- }
+out:
+ if (ret)
+ brcmf_sdio_remove(sdiodev);
- return -ENODEV;
+ return ret;
}
+EXPORT_SYMBOL(brcmf_sdio_probe);
-int brcmf_sdio_remove(struct device *dev)
+int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
{
- struct sdio_hc *sdhc, *prev;
-
- sdhc = sdhcinfo;
- drvinfo.detach(sdhc->ch);
- brcmf_sdcard_detach(sdhc->card);
- /* find the SDIO Host Controller state for this pdev
- and take it out from the list */
- for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
- if (sdhc->dev == (void *)dev) {
- if (prev)
- prev->next = sdhc->next;
- else
- sdhcinfo = NULL;
- break;
- }
- prev = sdhc;
- }
- if (!sdhc) {
- SDLX_MSG(("%s: failed\n", __func__));
- return 0;
+ if (sdiodev->bus) {
+ brcmf_sdbrcm_disconnect(sdiodev->bus);
+ sdiodev->bus = NULL;
}
- /* release SDIO Host Controller info */
- kfree(sdhc);
- return 0;
-}
-
-int brcmf_sdio_register(struct brcmf_sdioh_driver *driver)
-{
- drvinfo = *driver;
+ brcmf_sdioh_detach(sdiodev);
- SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
- return brcmf_sdio_function_init();
-}
+ sdiodev->sbwad = 0;
-void brcmf_sdio_unregister(void)
-{
- brcmf_sdio_function_cleanup();
+ return 0;
}
+EXPORT_SYMBOL(brcmf_sdio_remove);
-void brcmf_sdio_wdtmr_enable(bool enable)
+void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
{
if (enable)
- brcmf_sdbrcm_wd_timer(sdhcinfo->ch, brcmf_watchdog_ms);
+ brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
else
- brcmf_sdbrcm_wd_timer(sdhcinfo->ch, 0);
+ brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
}
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 38bd9ba3096f..bbaeb2d5c93a 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -23,6 +23,7 @@
#include <linux/suspend.h>
#include <linux/errno.h>
#include <linux/sched.h> /* request_irq() */
+#include <linux/module.h>
#include <net/cfg80211.h>
#include <defs.h>
@@ -34,771 +35,179 @@
#include "dhd_dbg.h"
#include "wl_cfg80211.h"
-#define BLOCK_SIZE_64 64
-#define BLOCK_SIZE_512 512
-#define BLOCK_SIZE_4318 64
-#define BLOCK_SIZE_4328 512
-
-/* private bus modes */
-#define SDIOH_MODE_SD4 2
-
-#define CLIENT_INTR 0x100 /* Get rid of this! */
-
-#if !defined(SDIO_VENDOR_ID_BROADCOM)
#define SDIO_VENDOR_ID_BROADCOM 0x02d0
-#endif /* !defined(SDIO_VENDOR_ID_BROADCOM) */
-
-#define SDIO_DEVICE_ID_BROADCOM_DEFAULT 0x0000
#define DMA_ALIGN_MASK 0x03
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)
-#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB 0x0492 /* BCM94325SDGWB */
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4325)
-#define SDIO_DEVICE_ID_BROADCOM_4325 0x0493
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4329)
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4319)
-#define SDIO_DEVICE_ID_BROADCOM_4319 0x4319
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
-
-/* Common msglevel constants */
-#define SDH_ERROR_VAL 0x0001 /* Error */
-#define SDH_TRACE_VAL 0x0002 /* Trace */
-#define SDH_INFO_VAL 0x0004 /* Info */
-#define SDH_DEBUG_VAL 0x0008 /* Debug */
-#define SDH_DATA_VAL 0x0010 /* Data */
-#define SDH_CTRL_VAL 0x0020 /* Control Regs */
-#define SDH_LOG_VAL 0x0040 /* Enable bcmlog */
-#define SDH_DMA_VAL 0x0080 /* DMA */
-
-#ifdef BCMDBG
-#define sd_err(x) \
- do { \
- if ((sd_msglevel & SDH_ERROR_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#define sd_trace(x) \
- do { \
- if ((sd_msglevel & SDH_TRACE_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#define sd_info(x) \
- do { \
- if ((sd_msglevel & SDH_INFO_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#define sd_debug(x) \
- do { \
- if ((sd_msglevel & SDH_DEBUG_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#define sd_data(x) \
- do { \
- if ((sd_msglevel & SDH_DATA_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#define sd_ctrl(x) \
- do { \
- if ((sd_msglevel & SDH_CTRL_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#else
-#define sd_err(x)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-#endif
-
-struct sdos_info {
- struct sdioh_info *sd;
- spinlock_t lock;
-};
-
-static void brcmf_sdioh_irqhandler(struct sdio_func *func);
-static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func);
-static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr);
-static int brcmf_ops_sdio_probe(struct sdio_func *func,
- const struct sdio_device_id *id);
-static void brcmf_ops_sdio_remove(struct sdio_func *func);
-
-#ifdef CONFIG_PM
-static int brcmf_sdio_suspend(struct device *dev);
-static int brcmf_sdio_resume(struct device *dev);
-#endif /* CONFIG_PM */
-uint sd_f2_blocksize = 512; /* Default blocksize */
-
-uint sd_msglevel = 0x01;
-
-/* module param defaults */
-static int clockoverride;
-
-module_param(clockoverride, int, 0644);
-MODULE_PARM_DESC(clockoverride, "SDIO card clock override");
-
-struct brcmf_sdmmc_instance *gInstance;
-
-struct device sdmmc_dev;
+#define SDIO_FUNC1_BLOCKSIZE 64
+#define SDIO_FUNC2_BLOCKSIZE 512
/* devices we support, null terminated */
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT)},
- {SDIO_DEVICE
- (SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319)},
{ /* end: all zeroes */ },
};
-
-#ifdef CONFIG_PM
-static const struct dev_pm_ops brcmf_sdio_pm_ops = {
- .suspend = brcmf_sdio_suspend,
- .resume = brcmf_sdio_resume,
-};
-#endif /* CONFIG_PM */
-
-static struct sdio_driver brcmf_sdmmc_driver = {
- .probe = brcmf_ops_sdio_probe,
- .remove = brcmf_ops_sdio_remove,
- .name = "brcmfmac",
- .id_table = brcmf_sdmmc_ids,
-#ifdef CONFIG_PM
- .drv = {
- .pm = &brcmf_sdio_pm_ops,
- },
-#endif /* CONFIG_PM */
-};
-
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
-BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
-BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
-BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
-BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
-
-static int
-brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
- int regsize, u32 *data);
-
-static int brcmf_sdioh_enablefuncs(struct sdioh_info *sd)
+static bool
+brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
{
- int err_ret;
- u32 fbraddr;
- u8 func;
-
- sd_trace(("%s\n", __func__));
-
- /* Get the Card's common CIS address */
- sd->com_cis_ptr = brcmf_sdioh_get_cisaddr(sd, SDIO_CCCR_CIS);
- sd->func_cis_ptr[0] = sd->com_cis_ptr;
- sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
- sd->com_cis_ptr));
-
- /* Get the Card's function CIS (for each function) */
- for (fbraddr = SDIO_FBR_BASE(1), func = 1;
- func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
- sd->func_cis_ptr[func] =
- brcmf_sdioh_get_cisaddr(sd, SDIO_FBR_CIS + fbraddr);
- sd_info(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func,
- sd->func_cis_ptr[func]));
- }
-
- sd->func_cis_ptr[0] = sd->com_cis_ptr;
- sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
- sd->com_cis_ptr));
-
- /* Enable Function 1 */
- sdio_claim_host(gInstance->func[1]);
- err_ret = sdio_enable_func(gInstance->func[1]);
- sdio_release_host(gInstance->func[1]);
- if (err_ret) {
- sd_err(("brcmf_sdioh_enablefuncs: Failed to enable F1 "
- "Err: 0x%08x\n", err_ret));
- }
-
- return false;
-}
-
-/*
- * Public entry points & extern's
- */
-struct sdioh_info *brcmf_sdioh_attach(void *bar0, uint irq)
-{
- struct sdioh_info *sd;
- int err_ret;
-
- sd_trace(("%s\n", __func__));
-
- if (gInstance == NULL) {
- sd_err(("%s: SDIO Device not present\n", __func__));
- return NULL;
- }
-
- sd = kzalloc(sizeof(struct sdioh_info), GFP_ATOMIC);
- if (sd == NULL) {
- sd_err(("sdioh_attach: out of memory\n"));
- return NULL;
- }
- if (brcmf_sdioh_osinit(sd) != 0) {
- sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
- kfree(sd);
- return NULL;
- }
-
- sd->num_funcs = 2;
- sd->use_client_ints = true;
- sd->client_block_size[0] = 64;
-
- gInstance->sd = sd;
-
- /* Claim host controller */
- sdio_claim_host(gInstance->func[1]);
-
- sd->client_block_size[1] = 64;
- err_ret = sdio_set_block_size(gInstance->func[1], 64);
- if (err_ret)
- sd_err(("brcmf_sdioh_attach: Failed to set F1 blocksize\n"));
-
- /* Release host controller F1 */
- sdio_release_host(gInstance->func[1]);
-
- if (gInstance->func[2]) {
- /* Claim host controller F2 */
- sdio_claim_host(gInstance->func[2]);
-
- sd->client_block_size[2] = sd_f2_blocksize;
- err_ret =
- sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
- if (err_ret)
- sd_err(("brcmf_sdioh_attach: Failed to set F2 blocksize"
- " to %d\n", sd_f2_blocksize));
-
- /* Release host controller F2 */
- sdio_release_host(gInstance->func[2]);
- }
-
- brcmf_sdioh_enablefuncs(sd);
-
- sd_trace(("%s: Done\n", __func__));
- return sd;
-}
-
-extern int brcmf_sdioh_detach(struct sdioh_info *sd)
-{
- sd_trace(("%s\n", __func__));
-
- if (sd) {
-
- /* Disable Function 2 */
- sdio_claim_host(gInstance->func[2]);
- sdio_disable_func(gInstance->func[2]);
- sdio_release_host(gInstance->func[2]);
-
- /* Disable Function 1 */
- sdio_claim_host(gInstance->func[1]);
- sdio_disable_func(gInstance->func[1]);
- sdio_release_host(gInstance->func[1]);
-
- /* deregister irq */
- brcmf_sdioh_osfree(sd);
-
- kfree(sd);
- }
- return 0;
-}
-
-/* Configure callback to client when we receive client interrupt */
-extern int
-brcmf_sdioh_interrupt_register(struct sdioh_info *sd, void (*fn)(void *),
- void *argh)
-{
- sd_trace(("%s: Entering\n", __func__));
- if (fn == NULL) {
- sd_err(("%s: interrupt handler is NULL, not registering\n",
- __func__));
- return -EINVAL;
- }
-
- sd->intr_handler = fn;
- sd->intr_handler_arg = argh;
- sd->intr_handler_valid = true;
-
- /* register and unmask irq */
- if (gInstance->func[2]) {
- sdio_claim_host(gInstance->func[2]);
- sdio_claim_irq(gInstance->func[2], brcmf_sdioh_irqhandler_f2);
- sdio_release_host(gInstance->func[2]);
- }
-
- if (gInstance->func[1]) {
- sdio_claim_host(gInstance->func[1]);
- sdio_claim_irq(gInstance->func[1], brcmf_sdioh_irqhandler);
- sdio_release_host(gInstance->func[1]);
- }
-
- return 0;
+ bool is_err = false;
+#ifdef CONFIG_PM_SLEEP
+ is_err = atomic_read(&sdiodev->suspend);
+#endif
+ return is_err;
}
-extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *sd)
+static void
+brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq)
{
- sd_trace(("%s: Entering\n", __func__));
-
- if (gInstance->func[1]) {
- /* register and unmask irq */
- sdio_claim_host(gInstance->func[1]);
- sdio_release_irq(gInstance->func[1]);
- sdio_release_host(gInstance->func[1]);
- }
-
- if (gInstance->func[2]) {
- /* Claim host controller F2 */
- sdio_claim_host(gInstance->func[2]);
- sdio_release_irq(gInstance->func[2]);
- /* Release host controller F2 */
- sdio_release_host(gInstance->func[2]);
- }
-
- sd->intr_handler_valid = false;
- sd->intr_handler = NULL;
- sd->intr_handler_arg = NULL;
-
- return 0;
+#ifdef CONFIG_PM_SLEEP
+ int retry = 0;
+ while (atomic_read(&sdiodev->suspend) && retry++ != 30)
+ wait_event_timeout(*wq, false, HZ/100);
+#endif
}
-/* IOVar table */
-enum {
- IOV_MSGLEVEL = 1,
- IOV_BLOCKSIZE,
- IOV_USEINTS,
- IOV_NUMINTS,
- IOV_DEVREG,
- IOV_HCIREGS,
- IOV_RXCHAIN
-};
-
-const struct brcmu_iovar sdioh_iovars[] = {
- {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0},
- {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) |
- size) */
- {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0},
- {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0},
- {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
- ,
- {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
- ,
- {NULL, 0, 0, 0, 0}
-};
-
-int
-brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
- void *params, int plen, void *arg, int len, bool set)
+static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
+ uint regaddr, u8 *byte)
{
- const struct brcmu_iovar *vi = NULL;
- int bcmerror = 0;
- int val_size;
- s32 int_val = 0;
- bool bool_val;
- u32 actionid;
-
- if (name == NULL || len <= 0)
- return -EINVAL;
-
- /* Set does not take qualifiers */
- if (set && (params || plen))
- return -EINVAL;
-
- /* Get must have return space;*/
- if (!set && !(arg && len))
- return -EINVAL;
-
- sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"),
- name));
-
- vi = brcmu_iovar_lookup(sdioh_iovars, name);
- if (vi == NULL) {
- bcmerror = -ENOTSUPP;
- goto exit;
- }
-
- bcmerror = brcmu_iovar_lencheck(vi, arg, len, set);
- if (bcmerror != 0)
- goto exit;
-
- /* Set up params so get and set can share the convenience variables */
- if (params == NULL) {
- params = arg;
- plen = len;
- }
-
- if (vi->type == IOVT_VOID)
- val_size = 0;
- else if (vi->type == IOVT_BUFFER)
- val_size = len;
- else
- val_size = sizeof(int);
-
- if (plen >= (int)sizeof(int_val))
- memcpy(&int_val, params, sizeof(int_val));
-
- bool_val = (int_val != 0) ? true : false;
-
- actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
- switch (actionid) {
- case IOV_GVAL(IOV_MSGLEVEL):
- int_val = (s32) sd_msglevel;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_MSGLEVEL):
- sd_msglevel = int_val;
- break;
-
- case IOV_GVAL(IOV_BLOCKSIZE):
- if ((u32) int_val > si->num_funcs) {
- bcmerror = -EINVAL;
- break;
- }
- int_val = (s32) si->client_block_size[int_val];
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_BLOCKSIZE):
- {
- uint func = ((u32) int_val >> 16);
- uint blksize = (u16) int_val;
- uint maxsize;
-
- if (func > si->num_funcs) {
- bcmerror = -EINVAL;
- break;
- }
-
- switch (func) {
- case 0:
- maxsize = 32;
- break;
- case 1:
- maxsize = BLOCK_SIZE_4318;
- break;
- case 2:
- maxsize = BLOCK_SIZE_4328;
- break;
- default:
- maxsize = 0;
- }
- if (blksize > maxsize) {
- bcmerror = -EINVAL;
- break;
- }
- if (!blksize)
- blksize = maxsize;
-
- /* Now set it */
- si->client_block_size[func] = blksize;
-
- break;
- }
-
- case IOV_GVAL(IOV_RXCHAIN):
- int_val = false;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_GVAL(IOV_USEINTS):
- int_val = (s32) si->use_client_ints;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_USEINTS):
- si->use_client_ints = (bool) int_val;
- if (si->use_client_ints)
- si->intmask |= CLIENT_INTR;
- else
- si->intmask &= ~CLIENT_INTR;
-
- break;
-
- case IOV_GVAL(IOV_NUMINTS):
- int_val = (s32) si->intrcount;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_GVAL(IOV_DEVREG):
- {
- struct brcmf_sdreg *sd_ptr =
- (struct brcmf_sdreg *) params;
- u8 data = 0;
-
- if (brcmf_sdioh_cfg_read
- (si, sd_ptr->func, sd_ptr->offset, &data)) {
- bcmerror = -EIO;
- break;
- }
-
- int_val = (int)data;
- memcpy(arg, &int_val, sizeof(int_val));
- break;
- }
-
- case IOV_SVAL(IOV_DEVREG):
- {
- struct brcmf_sdreg *sd_ptr =
- (struct brcmf_sdreg *) params;
- u8 data = (u8) sd_ptr->value;
+ struct sdio_func *sdfunc = sdiodev->func[0];
+ int err_ret;
- if (brcmf_sdioh_cfg_write
- (si, sd_ptr->func, sd_ptr->offset, &data)) {
- bcmerror = -EIO;
- break;
+ /*
+ * Can only directly write to some F0 registers.
+ * Handle F2 enable/disable and Abort command
+ * as a special case.
+ */
+ if (regaddr == SDIO_CCCR_IOEx) {
+ sdfunc = sdiodev->func[2];
+ if (sdfunc) {
+ sdio_claim_host(sdfunc);
+ if (*byte & SDIO_FUNC_ENABLE_2) {
+ /* Enable Function 2 */
+ err_ret = sdio_enable_func(sdfunc);
+ if (err_ret)
+ brcmf_dbg(ERROR,
+ "enable F2 failed:%d\n",
+ err_ret);
+ } else {
+ /* Disable Function 2 */
+ err_ret = sdio_disable_func(sdfunc);
+ if (err_ret)
+ brcmf_dbg(ERROR,
+ "Disable F2 failed:%d\n",
+ err_ret);
}
- break;
- }
-
- default:
- bcmerror = -ENOTSUPP;
- break;
- }
-exit:
-
- return bcmerror;
-}
-
-extern int
-brcmf_sdioh_cfg_read(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
-{
- int status;
- /* No lock needed since brcmf_sdioh_request_byte does locking */
- status = brcmf_sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
- return status;
-}
-
-extern int
-brcmf_sdioh_cfg_write(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
-{
- /* No lock needed since brcmf_sdioh_request_byte does locking */
- int status;
- status = brcmf_sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
- return status;
-}
-
-static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr)
-{
- /* read 24 bits and return valid 17 bit addr */
- int i;
- u32 scratch, regdata;
- u8 *ptr = (u8 *)&scratch;
- for (i = 0; i < 3; i++) {
- if ((brcmf_sdioh_card_regread(sd, 0, regaddr, 1, &regdata)) !=
- SUCCESS)
- sd_err(("%s: Can't read!\n", __func__));
-
- *ptr++ = (u8) regdata;
- regaddr++;
- }
-
- /* Only the lower 17-bits are valid */
- scratch = le32_to_cpu(scratch);
- scratch &= 0x0001FFFF;
- return scratch;
-}
-
-extern int
-brcmf_sdioh_cis_read(struct sdioh_info *sd, uint func, u8 *cisd, u32 length)
-{
- u32 count;
- int offset;
- u32 foo;
- u8 *cis = cisd;
-
- sd_trace(("%s: Func = %d\n", __func__, func));
-
- if (!sd->func_cis_ptr[func]) {
- memset(cis, 0, length);
- sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func));
- return -ENOTSUPP;
- }
-
- sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func,
- sd->func_cis_ptr[func]));
-
- for (count = 0; count < length; count++) {
- offset = sd->func_cis_ptr[func] + count;
- if (brcmf_sdioh_card_regread(sd, 0, offset, 1, &foo) < 0) {
- sd_err(("%s: regread failed: Can't read CIS\n",
- __func__));
- return -EIO;
+ sdio_release_host(sdfunc);
}
-
- *cis = (u8) (foo & 0xff);
- cis++;
+ } else if (regaddr == SDIO_CCCR_ABORT) {
+ sdio_claim_host(sdfunc);
+ sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
+ sdio_release_host(sdfunc);
+ } else if (regaddr < 0xF0) {
+ brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
+ err_ret = -EPERM;
+ } else {
+ sdio_claim_host(sdfunc);
+ sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
+ sdio_release_host(sdfunc);
}
- return 0;
+ return err_ret;
}
-extern int
-brcmf_sdioh_request_byte(struct sdioh_info *sd, uint rw, uint func,
- uint regaddr, u8 *byte)
+int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
+ uint regaddr, u8 *byte)
{
int err_ret;
- sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func,
- regaddr));
+ brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);
- BRCMF_PM_RESUME_WAIT(sdioh_request_byte_wait);
- BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
- if (rw) { /* CMD52 Write */
- if (func == 0) {
- /* Can only directly write to some F0 registers.
- * Handle F2 enable
- * as a special case.
- */
- if (regaddr == SDIO_CCCR_IOEx) {
- if (gInstance->func[2]) {
- sdio_claim_host(gInstance->func[2]);
- if (*byte & SDIO_FUNC_ENABLE_2) {
- /* Enable Function 2 */
- err_ret =
- sdio_enable_func
- (gInstance->func[2]);
- if (err_ret)
- sd_err(("request_byte: "
- "enable F2 "
- "failed:%d\n",
- err_ret));
- } else {
- /* Disable Function 2 */
- err_ret =
- sdio_disable_func
- (gInstance->func[2]);
- if (err_ret)
- sd_err(("request_byte: "
- "Disab F2 "
- "failed:%d\n",
- err_ret));
- }
- sdio_release_host(gInstance->func[2]);
- }
- }
- /* to allow abort command through F1 */
- else if (regaddr == SDIO_CCCR_ABORT) {
- sdio_claim_host(gInstance->func[func]);
- /*
- * this sdio_f0_writeb() can be replaced
- * with another api
- * depending upon MMC driver change.
- * As of this time, this is temporaray one
- */
- sdio_writeb(gInstance->func[func], *byte,
- regaddr, &err_ret);
- sdio_release_host(gInstance->func[func]);
- } else if (regaddr < 0xF0) {
- sd_err(("brcmf: F0 Wr:0x%02x: write "
- "disallowed\n", regaddr));
- } else {
- /* Claim host controller, perform F0 write,
- and release */
- sdio_claim_host(gInstance->func[func]);
- sdio_f0_writeb(gInstance->func[func], *byte,
- regaddr, &err_ret);
- sdio_release_host(gInstance->func[func]);
- }
- } else {
- /* Claim host controller, perform Fn write,
- and release */
- sdio_claim_host(gInstance->func[func]);
- sdio_writeb(gInstance->func[func], *byte, regaddr,
- &err_ret);
- sdio_release_host(gInstance->func[func]);
- }
- } else { /* CMD52 Read */
- /* Claim host controller, perform Fn read, and release */
- sdio_claim_host(gInstance->func[func]);
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait);
+ if (brcmf_pm_resume_error(sdiodev))
+ return -EIO;
- if (func == 0) {
- *byte =
- sdio_f0_readb(gInstance->func[func], regaddr,
- &err_ret);
+ if (rw && func == 0) {
+ /* handle F0 separately */
+ err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
+ } else {
+ sdio_claim_host(sdiodev->func[func]);
+ if (rw) /* CMD52 Write */
+ sdio_writeb(sdiodev->func[func], *byte, regaddr,
+ &err_ret);
+ else if (func == 0) {
+ *byte = sdio_f0_readb(sdiodev->func[func], regaddr,
+ &err_ret);
} else {
- *byte =
- sdio_readb(gInstance->func[func], regaddr,
- &err_ret);
+ *byte = sdio_readb(sdiodev->func[func], regaddr,
+ &err_ret);
}
-
- sdio_release_host(gInstance->func[func]);
+ sdio_release_host(sdiodev->func[func]);
}
if (err_ret)
- sd_err(("brcmf: Failed to %s byte F%d:@0x%05x=%02x, "
- "Err: %d\n", rw ? "Write" : "Read", func, regaddr,
- *byte, err_ret));
+ brcmf_dbg(ERROR, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
+ rw ? "write" : "read", func, regaddr, *byte, err_ret);
return err_ret;
}
-extern int
-brcmf_sdioh_request_word(struct sdioh_info *sd, uint cmd_type, uint rw,
- uint func, uint addr, u32 *word, uint nbytes)
+int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
+ uint rw, uint func, uint addr, u32 *word,
+ uint nbytes)
{
int err_ret = -EIO;
if (func == 0) {
- sd_err(("%s: Only CMD52 allowed to F0.\n", __func__));
+ brcmf_dbg(ERROR, "Only CMD52 allowed to F0\n");
return -EINVAL;
}
- sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
- __func__, cmd_type, rw, func, addr, nbytes));
+ brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
+ rw, func, addr, nbytes);
- BRCMF_PM_RESUME_WAIT(sdioh_request_word_wait);
- BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
+ if (brcmf_pm_resume_error(sdiodev))
+ return -EIO;
/* Claim host controller */
- sdio_claim_host(gInstance->func[func]);
+ sdio_claim_host(sdiodev->func[func]);
if (rw) { /* CMD52 Write */
- if (nbytes == 4) {
- sdio_writel(gInstance->func[func], *word, addr,
+ if (nbytes == 4)
+ sdio_writel(sdiodev->func[func], *word, addr,
&err_ret);
- } else if (nbytes == 2) {
- sdio_writew(gInstance->func[func], (*word & 0xFFFF),
+ else if (nbytes == 2)
+ sdio_writew(sdiodev->func[func], (*word & 0xFFFF),
addr, &err_ret);
- } else {
- sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
- }
+ else
+ brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
} else { /* CMD52 Read */
- if (nbytes == 4) {
- *word =
- sdio_readl(gInstance->func[func], addr, &err_ret);
- } else if (nbytes == 2) {
- *word =
- sdio_readw(gInstance->func[func], addr,
- &err_ret) & 0xFFFF;
- } else {
- sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
- }
+ if (nbytes == 4)
+ *word = sdio_readl(sdiodev->func[func], addr, &err_ret);
+ else if (nbytes == 2)
+ *word = sdio_readw(sdiodev->func[func], addr,
+ &err_ret) & 0xFFFF;
+ else
+ brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
}
/* Release host controller */
- sdio_release_host(gInstance->func[func]);
+ sdio_release_host(sdiodev->func[func]);
- if (err_ret) {
- sd_err(("brcmf: Failed to %s word, Err: 0x%08x\n",
- rw ? "Write" : "Read", err_ret));
- }
+ if (err_ret)
+ brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n",
+ rw ? "write" : "read", err_ret);
return err_ret;
}
static int
-brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write,
- uint func, uint addr, struct sk_buff *pkt)
+brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
+ uint write, uint func, uint addr,
+ struct sk_buff *pkt)
{
bool fifo = (fix_inc == SDIOH_DATA_FIX);
u32 SGCount = 0;
@@ -806,46 +215,45 @@ brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write,
struct sk_buff *pnext;
- sd_trace(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
- BRCMF_PM_RESUME_WAIT(sdioh_request_packet_wait);
- BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_packet_wait);
+ if (brcmf_pm_resume_error(sdiodev))
+ return -EIO;
/* Claim host controller */
- sdio_claim_host(gInstance->func[func]);
+ sdio_claim_host(sdiodev->func[func]);
for (pnext = pkt; pnext; pnext = pnext->next) {
uint pkt_len = pnext->len;
pkt_len += 3;
pkt_len &= 0xFFFFFFFC;
if ((write) && (!fifo)) {
- err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
+ err_ret = sdio_memcpy_toio(sdiodev->func[func], addr,
((u8 *) (pnext->data)),
pkt_len);
} else if (write) {
- err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
+ err_ret = sdio_memcpy_toio(sdiodev->func[func], addr,
((u8 *) (pnext->data)),
pkt_len);
} else if (fifo) {
- err_ret = sdio_readsb(gInstance->func[func],
+ err_ret = sdio_readsb(sdiodev->func[func],
((u8 *) (pnext->data)),
addr, pkt_len);
} else {
- err_ret = sdio_memcpy_fromio(gInstance->func[func],
+ err_ret = sdio_memcpy_fromio(sdiodev->func[func],
((u8 *) (pnext->data)),
addr, pkt_len);
}
if (err_ret) {
- sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d,"
- "ERR=0x%08x\n", __func__,
- (write) ? "TX" : "RX",
- pnext, SGCount, addr, pkt_len, err_ret));
+ brcmf_dbg(ERROR, "%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
+ write ? "TX" : "RX", pnext, SGCount, addr,
+ pkt_len, err_ret);
} else {
- sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
- __func__,
- (write) ? "TX" : "RX",
- pnext, SGCount, addr, pkt_len));
+ brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n",
+ write ? "TX" : "RX", pnext, SGCount, addr,
+ pkt_len);
}
if (!fifo)
@@ -855,9 +263,9 @@ brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write,
}
/* Release host controller */
- sdio_release_host(gInstance->func[func]);
+ sdio_release_host(sdiodev->func[func]);
- sd_trace(("%s: Exit\n", __func__));
+ brcmf_dbg(TRACE, "Exit\n");
return err_ret;
}
@@ -876,26 +284,27 @@ brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write,
* aligned packet.
*
*/
-extern int
-brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc,
- uint write, uint func, uint addr, uint reg_width,
- uint buflen_u, u8 *buffer, struct sk_buff *pkt)
+int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
+ uint fix_inc, uint write, uint func, uint addr,
+ uint reg_width, uint buflen_u, u8 *buffer,
+ struct sk_buff *pkt)
{
int Status;
struct sk_buff *mypkt = NULL;
- sd_trace(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
- BRCMF_PM_RESUME_WAIT(sdioh_request_buffer_wait);
- BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
+ if (brcmf_pm_resume_error(sdiodev))
+ return -EIO;
/* Case 1: we don't have a packet. */
if (pkt == NULL) {
- sd_data(("%s: Creating new %s Packet, len=%d\n",
- __func__, write ? "TX" : "RX", buflen_u));
+ brcmf_dbg(DATA, "Creating new %s Packet, len=%d\n",
+ write ? "TX" : "RX", buflen_u);
mypkt = brcmu_pkt_buf_get_skb(buflen_u);
if (!mypkt) {
- sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
- __func__, buflen_u));
+ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
+ buflen_u);
return -EIO;
}
@@ -903,8 +312,8 @@ brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc,
if (write)
memcpy(mypkt->data, buffer, buflen_u);
- Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
- addr, mypkt);
+ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
+ func, addr, mypkt);
/* For a read, copy the packet data back to the buffer. */
if (!write)
@@ -916,12 +325,12 @@ brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc,
* Case 2: We have a packet, but it is unaligned.
* In this case, we cannot have a chain (pkt->next == NULL)
*/
- sd_data(("%s: Creating aligned %s Packet, len=%d\n",
- __func__, write ? "TX" : "RX", pkt->len));
+ brcmf_dbg(DATA, "Creating aligned %s Packet, len=%d\n",
+ write ? "TX" : "RX", pkt->len);
mypkt = brcmu_pkt_buf_get_skb(pkt->len);
if (!mypkt) {
- sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
- __func__, pkt->len));
+ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
+ pkt->len);
return -EIO;
}
@@ -929,8 +338,8 @@ brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc,
if (write)
memcpy(mypkt->data, pkt->data, pkt->len);
- Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
- addr, mypkt);
+ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
+ func, addr, mypkt);
/* For a read, copy the packet data back to the buffer. */
if (!write)
@@ -939,128 +348,185 @@ brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc,
brcmu_pkt_buf_free_skb(mypkt);
} else { /* case 3: We have a packet and
it is aligned. */
- sd_data(("%s: Aligned %s Packet, direct DMA\n",
- __func__, write ? "Tx" : "Rx"));
- Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
- addr, pkt);
+ brcmf_dbg(DATA, "Aligned %s Packet, direct DMA\n",
+ write ? "Tx" : "Rx");
+ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
+ func, addr, pkt);
}
return Status;
}
-/* this function performs "abort" for both of host & device */
-extern int brcmf_sdioh_abort(struct sdioh_info *sd, uint func)
-{
- char t_func = (char)func;
- sd_trace(("%s: Enter\n", __func__));
-
- /* issue abort cmd52 command through F0 */
- brcmf_sdioh_request_byte(sd, SDIOH_WRITE, SDIO_FUNC_0, SDIO_CCCR_ABORT,
- &t_func);
-
- sd_trace(("%s: Exit\n", __func__));
- return 0;
-}
-
-/* Disable device interrupt */
-void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd)
-{
- sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
- sd->intmask &= ~CLIENT_INTR;
-}
-
-/* Enable device interrupt */
-void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd)
-{
- sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
- sd->intmask |= CLIENT_INTR;
-}
-
/* Read client card reg */
-int
-brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
+static int
+brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr,
int regsize, u32 *data)
{
if ((func == 0) || (regsize == 1)) {
u8 temp = 0;
- brcmf_sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
+ brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, func, regaddr,
+ &temp);
*data = temp;
*data &= 0xff;
- sd_data(("%s: byte read data=0x%02x\n", __func__, *data));
+ brcmf_dbg(DATA, "byte read data=0x%02x\n", *data);
} else {
- brcmf_sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
- regsize);
+ brcmf_sdioh_request_word(sdiodev, SDIOH_READ, func, regaddr,
+ data, regsize);
if (regsize == 2)
*data &= 0xffff;
- sd_data(("%s: word read data=0x%08x\n", __func__, *data));
+ brcmf_dbg(DATA, "word read data=0x%08x\n", *data);
}
return SUCCESS;
}
-static void brcmf_sdioh_irqhandler(struct sdio_func *func)
+static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr)
{
- struct sdioh_info *sd;
+ /* read 24 bits and return valid 17 bit addr */
+ int i;
+ u32 scratch, regdata;
+ __le32 scratch_le;
+ u8 *ptr = (u8 *)&scratch_le;
- sd_trace(("brcmf: ***IRQHandler\n"));
- sd = gInstance->sd;
+ for (i = 0; i < 3; i++) {
+ if ((brcmf_sdioh_card_regread(sdiodev, 0, regaddr, 1,
+ &regdata)) != SUCCESS)
+ brcmf_dbg(ERROR, "Can't read!\n");
- sdio_release_host(gInstance->func[0]);
+ *ptr++ = (u8) regdata;
+ regaddr++;
+ }
- if (sd->use_client_ints) {
- sd->intrcount++;
- (sd->intr_handler) (sd->intr_handler_arg);
- } else {
- sd_err(("brcmf: ***IRQHandler\n"));
+ /* Only the lower 17-bits are valid */
+ scratch = le32_to_cpu(scratch_le);
+ scratch &= 0x0001FFFF;
+ return scratch;
+}
- sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
- __func__, sd->client_intr_enabled, sd->intr_handler));
+static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
+{
+ int err_ret;
+ u32 fbraddr;
+ u8 func;
+
+ brcmf_dbg(TRACE, "\n");
+
+ /* Get the Card's common CIS address */
+ sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev,
+ SDIO_CCCR_CIS);
+ brcmf_dbg(INFO, "Card's Common CIS Ptr = 0x%x\n",
+ sdiodev->func_cis_ptr[0]);
+
+ /* Get the Card's function CIS (for each function) */
+ for (fbraddr = SDIO_FBR_BASE(1), func = 1;
+ func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
+ sdiodev->func_cis_ptr[func] =
+ brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr);
+ brcmf_dbg(INFO, "Function %d CIS Ptr = 0x%x\n",
+ func, sdiodev->func_cis_ptr[func]);
+ }
+
+ /* Enable Function 1 */
+ sdio_claim_host(sdiodev->func[1]);
+ err_ret = sdio_enable_func(sdiodev->func[1]);
+ sdio_release_host(sdiodev->func[1]);
+ if (err_ret)
+ brcmf_dbg(ERROR, "Failed to enable F1 Err: 0x%08x\n", err_ret);
+
+ return false;
+}
+
+/*
+ * Public entry points & extern's
+ */
+int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
+{
+ int err_ret = 0;
+
+ brcmf_dbg(TRACE, "\n");
+
+ sdiodev->num_funcs = 2;
+
+ sdio_claim_host(sdiodev->func[1]);
+ err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE);
+ sdio_release_host(sdiodev->func[1]);
+ if (err_ret) {
+ brcmf_dbg(ERROR, "Failed to set F1 blocksize\n");
+ goto out;
+ }
+
+ sdio_claim_host(sdiodev->func[2]);
+ err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE);
+ sdio_release_host(sdiodev->func[2]);
+ if (err_ret) {
+ brcmf_dbg(ERROR, "Failed to set F2 blocksize\n");
+ goto out;
}
- sdio_claim_host(gInstance->func[0]);
+ brcmf_sdioh_enablefuncs(sdiodev);
+
+out:
+ brcmf_dbg(TRACE, "Done\n");
+ return err_ret;
}
-/* interrupt handler for F2 (dummy handler) */
-static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func)
+void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
{
- struct sdioh_info *sd;
+ brcmf_dbg(TRACE, "\n");
+
+ /* Disable Function 2 */
+ sdio_claim_host(sdiodev->func[2]);
+ sdio_disable_func(sdiodev->func[2]);
+ sdio_release_host(sdiodev->func[2]);
- sd_trace(("brcmf: ***IRQHandlerF2\n"));
+ /* Disable Function 1 */
+ sdio_claim_host(sdiodev->func[1]);
+ sdio_disable_func(sdiodev->func[1]);
+ sdio_release_host(sdiodev->func[1]);
- sd = gInstance->sd;
}
static int brcmf_ops_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
int ret = 0;
- static struct sdio_func sdio_func_0;
- sd_trace(("sdio_probe: %s Enter\n", __func__));
- sd_trace(("sdio_probe: func->class=%x\n", func->class));
- sd_trace(("sdio_vendor: 0x%04x\n", func->vendor));
- sd_trace(("sdio_device: 0x%04x\n", func->device));
- sd_trace(("Function#: 0x%04x\n", func->num));
+ struct brcmf_sdio_dev *sdiodev;
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(TRACE, "func->class=%x\n", func->class);
+ brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor);
+ brcmf_dbg(TRACE, "sdio_device: 0x%04x\n", func->device);
+ brcmf_dbg(TRACE, "Function#: 0x%04x\n", func->num);
if (func->num == 1) {
- sdio_func_0.num = 0;
- sdio_func_0.card = func->card;
- gInstance->func[0] = &sdio_func_0;
- if (func->device == 0x4) { /* 4318 */
- gInstance->func[2] = NULL;
- sd_trace(("NIC found, calling brcmf_sdio_probe...\n"));
- ret = brcmf_sdio_probe(&sdmmc_dev);
+ if (dev_get_drvdata(&func->card->dev)) {
+ brcmf_dbg(ERROR, "card private drvdata occupied\n");
+ return -ENXIO;
}
- }
+ sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
+ if (!sdiodev)
+ return -ENOMEM;
+ sdiodev->func[0] = func->card->sdio_func[0];
+ sdiodev->func[1] = func;
+ dev_set_drvdata(&func->card->dev, sdiodev);
- gInstance->func[func->num] = func;
+ atomic_set(&sdiodev->suspend, false);
+ init_waitqueue_head(&sdiodev->request_byte_wait);
+ init_waitqueue_head(&sdiodev->request_word_wait);
+ init_waitqueue_head(&sdiodev->request_packet_wait);
+ init_waitqueue_head(&sdiodev->request_buffer_wait);
+ }
if (func->num == 2) {
- brcmf_cfg80211_sdio_func(func);
- sd_trace(("F2 found, calling brcmf_sdio_probe...\n"));
- ret = brcmf_sdio_probe(&sdmmc_dev);
+ sdiodev = dev_get_drvdata(&func->card->dev);
+ if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
+ return -ENODEV;
+ sdiodev->func[2] = func;
+
+ brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
+ ret = brcmf_sdio_probe(sdiodev);
}
return ret;
@@ -1068,129 +534,93 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
static void brcmf_ops_sdio_remove(struct sdio_func *func)
{
- sd_trace(("%s Enter\n", __func__));
- sd_info(("func->class=%x\n", func->class));
- sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
- sd_info(("sdio_device: 0x%04x\n", func->device));
- sd_info(("Function#: 0x%04x\n", func->num));
+ struct brcmf_sdio_dev *sdiodev;
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(INFO, "func->class=%x\n", func->class);
+ brcmf_dbg(INFO, "sdio_vendor: 0x%04x\n", func->vendor);
+ brcmf_dbg(INFO, "sdio_device: 0x%04x\n", func->device);
+ brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num);
if (func->num == 2) {
- sd_trace(("F2 found, calling brcmf_sdio_remove...\n"));
- brcmf_sdio_remove(&sdmmc_dev);
+ sdiodev = dev_get_drvdata(&func->card->dev);
+ brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n");
+ brcmf_sdio_remove(sdiodev);
+ dev_set_drvdata(&func->card->dev, NULL);
+ kfree(sdiodev);
}
}
-
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int brcmf_sdio_suspend(struct device *dev)
{
mmc_pm_flag_t sdio_flags;
+ struct brcmf_sdio_dev *sdiodev;
+ struct sdio_func *func = dev_to_sdio_func(dev);
int ret = 0;
- sd_trace(("%s\n", __func__));
+ brcmf_dbg(TRACE, "\n");
+
+ sdiodev = dev_get_drvdata(&func->card->dev);
+
+ atomic_set(&sdiodev->suspend, true);
- sdio_flags = sdio_get_host_pm_caps(gInstance->func[1]);
+ sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
- sd_err(("Host can't keep power while suspended\n"));
+ brcmf_dbg(ERROR, "Host can't keep power while suspended\n");
return -EINVAL;
}
- ret = sdio_set_host_pm_flags(gInstance->func[1], MMC_PM_KEEP_POWER);
+ ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER);
if (ret) {
- sd_err(("Failed to set pm_flags\n"));
+ brcmf_dbg(ERROR, "Failed to set pm_flags\n");
return ret;
}
- brcmf_sdio_wdtmr_enable(false);
+ brcmf_sdio_wdtmr_enable(sdiodev, false);
return ret;
}
static int brcmf_sdio_resume(struct device *dev)
{
- brcmf_sdio_wdtmr_enable(true);
- return 0;
-}
-#endif /* CONFIG_PM */
-
-int brcmf_sdioh_osinit(struct sdioh_info *sd)
-{
- struct sdos_info *sdos;
-
- sdos = kmalloc(sizeof(struct sdos_info), GFP_ATOMIC);
- sd->sdos_info = (void *)sdos;
- if (sdos == NULL)
- return -ENOMEM;
+ struct brcmf_sdio_dev *sdiodev;
+ struct sdio_func *func = dev_to_sdio_func(dev);
- sdos->sd = sd;
- spin_lock_init(&sdos->lock);
+ sdiodev = dev_get_drvdata(&func->card->dev);
+ brcmf_sdio_wdtmr_enable(sdiodev, true);
+ atomic_set(&sdiodev->suspend, false);
return 0;
}
-void brcmf_sdioh_osfree(struct sdioh_info *sd)
-{
- struct sdos_info *sdos;
-
- sdos = (struct sdos_info *)sd->sdos_info;
- kfree(sdos);
-}
-
-/* Interrupt enable/disable */
-int brcmf_sdioh_interrupt_set(struct sdioh_info *sd, bool enable)
-{
- unsigned long flags;
- struct sdos_info *sdos;
-
- sd_trace(("%s: %s\n", __func__, enable ? "Enabling" : "Disabling"));
-
- sdos = (struct sdos_info *)sd->sdos_info;
-
- if (enable && !(sd->intr_handler && sd->intr_handler_arg)) {
- sd_err(("%s: no handler registered, will not enable\n",
- __func__));
- return -EINVAL;
- }
-
- /* Ensure atomicity for enable/disable calls */
- spin_lock_irqsave(&sdos->lock, flags);
-
- sd->client_intr_enabled = enable;
- if (enable)
- brcmf_sdioh_dev_intr_on(sd);
- else
- brcmf_sdioh_dev_intr_off(sd);
-
- spin_unlock_irqrestore(&sdos->lock, flags);
+static const struct dev_pm_ops brcmf_sdio_pm_ops = {
+ .suspend = brcmf_sdio_suspend,
+ .resume = brcmf_sdio_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
- return 0;
-}
+static struct sdio_driver brcmf_sdmmc_driver = {
+ .probe = brcmf_ops_sdio_probe,
+ .remove = brcmf_ops_sdio_remove,
+ .name = "brcmfmac",
+ .id_table = brcmf_sdmmc_ids,
+#ifdef CONFIG_PM_SLEEP
+ .drv = {
+ .pm = &brcmf_sdio_pm_ops,
+ },
+#endif /* CONFIG_PM_SLEEP */
+};
-/*
- * module init
-*/
-int brcmf_sdio_function_init(void)
+/* bus register interface */
+int brcmf_bus_register(void)
{
- int error = 0;
- sd_trace(("brcmf_sdio_function_init: %s Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
- gInstance = kzalloc(sizeof(struct brcmf_sdmmc_instance), GFP_KERNEL);
- if (!gInstance)
- return -ENOMEM;
-
- memset(&sdmmc_dev, 0, sizeof(sdmmc_dev));
- error = sdio_register_driver(&brcmf_sdmmc_driver);
-
- return error;
+ return sdio_register_driver(&brcmf_sdmmc_driver);
}
-/*
- * module cleanup
-*/
-void brcmf_sdio_function_cleanup(void)
+void brcmf_bus_unregister(void)
{
- sd_trace(("%s Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
sdio_unregister_driver(&brcmf_sdmmc_driver);
-
- kfree(gInstance);
}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd.h b/drivers/staging/brcm80211/brcmfmac/dhd.h
index 82bf04df16d0..4645766b4070 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd.h
@@ -23,10 +23,9 @@
#define BRCMF_VERSION_STR "4.218.248.5"
-#define BRCMF_C_IOCTL_SMLEN 256 /* "small" ioctl buffer required */
-#define BRCMF_C_IOCTL_MEDLEN 1536 /* "med" ioctl buffer required */
-#define BRCMF_C_IOCTL_MAXLEN 8192
-
+/*******************************************************************************
+ * IO codes that are interpreted by dongle firmware
+ ******************************************************************************/
#define BRCMF_C_UP 2
#define BRCMF_C_SET_PROMISC 10
#define BRCMF_C_GET_RATE 12
@@ -83,18 +82,11 @@
#define WLC_PHY_TYPE_LCN 8
#define WLC_PHY_TYPE_NULL 0xf
-#define BRCMF_PKT_FILTER_FIXED_LEN offsetof(struct brcmf_pkt_filter, u)
-#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \
- offsetof(struct brcmf_pkt_filter_pattern, mask_and_pattern)
-
#define BRCMF_EVENTING_MASK_LEN 16
#define TOE_TX_CSUM_OL 0x00000001
#define TOE_RX_CSUM_OL 0x00000002
-/* maximum channels returned by the get valid channels iovar */
-#define WL_NUMCHANNELS 64
-
#define BRCMF_BSS_INFO_VERSION 108 /* current ver of brcmf_bss_info struct */
/* size of brcmf_scan_params not including variable length array */
@@ -117,11 +109,16 @@
#define BRCMF_SCAN_RESULTS_ABORTED 3
#define BRCMF_SCAN_RESULTS_NO_MEM 4
-#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */
-#define BRCMF_PRIMARY_KEY (1 << 1) /* primary (ie tx) key */
-#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */
-#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */
-#define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */
+/* Indicates this key is using soft encrypt */
+#define WL_SOFT_KEY (1 << 0)
+/* primary (ie tx) key */
+#define BRCMF_PRIMARY_KEY (1 << 1)
+/* Reserved for backward compat */
+#define WL_KF_RES_4 (1 << 4)
+/* Reserved for backward compat */
+#define WL_KF_RES_5 (1 << 5)
+/* Indicates a group key for a IBSS PEER */
+#define WL_IBSS_PEER_GROUP_KEY (1 << 6)
/* For supporting multiple interfaces */
#define BRCMF_MAX_IFS 16
@@ -136,13 +133,13 @@
#define BRCMF_EVENT_MSG_GROUP 0x04
struct brcmf_event_msg {
- u16 version;
- u16 flags;
- u32 event_type;
- u32 status;
- u32 reason;
- u32 auth_type;
- u32 datalen;
+ __be16 version;
+ __be16 flags;
+ __be32 event_type;
+ __be32 status;
+ __be32 reason;
+ __be32 auth_type;
+ __be32 datalen;
u8 addr[ETH_ALEN];
char ifname[IFNAMSIZ];
} __packed;
@@ -173,6 +170,7 @@ struct dngl_stats {
unsigned long multicast; /* multicast packets received */
};
+/* event codes sent by the dongle to this driver */
#define BRCMF_E_SET_SSID 0
#define BRCMF_E_JOIN 1
#define BRCMF_E_START 2
@@ -332,30 +330,35 @@ enum brcmf_bus_state {
* start matching, the pattern to match, the size of the pattern, and a bitmask
* that indicates which bits within the pattern should be matched.
*/
-struct brcmf_pkt_filter_pattern {
- u32 offset; /* Offset within received packet to start pattern matching.
- * Offset '0' is the first byte of the ethernet header.
- */
- u32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */
- u8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts
- * at offset 0. Pattern immediately follows mask.
- */
+struct brcmf_pkt_filter_pattern_le {
+ /*
+ * Offset within received packet to start pattern matching.
+ * Offset '0' is the first byte of the ethernet header.
+ */
+ __le32 offset;
+ /* Size of the pattern. Bitmask must be the same size.*/
+ __le32 size_bytes;
+ /*
+ * Variable length mask and pattern data. mask starts at offset 0.
+ * Pattern immediately follows mask.
+ */
+ u8 mask_and_pattern[1];
};
/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
-struct brcmf_pkt_filter {
- u32 id; /* Unique filter id, specified by app. */
- u32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */
- u32 negate_match; /* Negate the result of filter matches */
+struct brcmf_pkt_filter_le {
+ __le32 id; /* Unique filter id, specified by app. */
+ __le32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */
+ __le32 negate_match; /* Negate the result of filter matches */
union { /* Filter definitions */
- struct brcmf_pkt_filter_pattern pattern; /* Filter pattern */
+ struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */
} u;
};
/* IOVAR "pkt_filter_enable" parameter. */
-struct brcmf_pkt_filter_enable {
- u32 id; /* Unique filter id */
- u32 enable; /* Enable/disable bool */
+struct brcmf_pkt_filter_enable_le {
+ __le32 id; /* Unique filter id */
+ __le32 enable; /* Enable/disable bool */
};
/* BSS info structure
@@ -363,63 +366,76 @@ struct brcmf_pkt_filter_enable {
* next bss_info structure in a vector (in struct brcmf_scan_results)
*/
struct brcmf_bss_info {
- u32 version; /* version field */
- u32 length; /* byte length of data in this record,
+ __le32 version; /* version field */
+ __le32 length; /* byte length of data in this record,
* starting at version and including IEs
*/
u8 BSSID[ETH_ALEN];
- u16 beacon_period; /* units are Kusec */
- u16 capability; /* Capability information */
+ __le16 beacon_period; /* units are Kusec */
+ __le16 capability; /* Capability information */
u8 SSID_len;
u8 SSID[32];
struct {
- uint count; /* # rates in this set */
- u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
+ __le32 count; /* # rates in this set */
+ u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
} rateset; /* supported rates */
- chanspec_t chanspec; /* chanspec for bss */
- u16 atim_window; /* units are Kusec */
+ __le16 chanspec; /* chanspec for bss */
+ __le16 atim_window; /* units are Kusec */
u8 dtim_period; /* DTIM period */
- s16 RSSI; /* receive signal strength (in dBm) */
+ __le16 RSSI; /* receive signal strength (in dBm) */
s8 phy_noise; /* noise (in dBm) */
u8 n_cap; /* BSS is 802.11N Capable */
- u32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */
+ /* 802.11N BSS Capabilities (based on HT_CAP_*): */
+ __le32 nbss_cap;
u8 ctl_ch; /* 802.11N BSS control channel number */
- u32 reserved32[1]; /* Reserved for expansion of BSS properties */
+ __le32 reserved32[1]; /* Reserved for expansion of BSS properties */
u8 flags; /* flags */
u8 reserved[3]; /* Reserved for expansion of BSS properties */
u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */
- u16 ie_offset; /* offset at which IEs start, from beginning */
- u32 ie_length; /* byte length of Information Elements */
- s16 SNR; /* average SNR of during frame reception */
+ __le16 ie_offset; /* offset at which IEs start, from beginning */
+ __le32 ie_length; /* byte length of Information Elements */
+ __le16 SNR; /* average SNR of during frame reception */
/* Add new fields here */
/* variable length Information Elements */
};
+struct brcm_rateset_le {
+ /* # rates in this set */
+ __le32 count;
+ /* rates in 500kbps units w/hi bit set if basic */
+ u8 rates[WL_NUMRATES];
+};
+
struct brcmf_ssid {
u32 SSID_len;
unsigned char SSID[32];
};
-struct brcmf_scan_params {
- struct brcmf_ssid ssid; /* default: {0, ""} */
+struct brcmf_ssid_le {
+ __le32 SSID_len;
+ unsigned char SSID[32];
+};
+
+struct brcmf_scan_params_le {
+ struct brcmf_ssid_le ssid_le; /* default: {0, ""} */
u8 bssid[ETH_ALEN]; /* default: bcast */
s8 bss_type; /* default: any,
* DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
*/
u8 scan_type; /* flags, 0 use default */
- s32 nprobes; /* -1 use default, number of probes per channel */
- s32 active_time; /* -1 use default, dwell time per channel for
+ __le32 nprobes; /* -1 use default, number of probes per channel */
+ __le32 active_time; /* -1 use default, dwell time per channel for
* active scanning
*/
- s32 passive_time; /* -1 use default, dwell time per channel
+ __le32 passive_time; /* -1 use default, dwell time per channel
* for passive scanning
*/
- s32 home_time; /* -1 use default, dwell time for the home channel
- * between channel scans
+ __le32 home_time; /* -1 use default, dwell time for the
+ * home channel between channel scans
*/
- s32 channel_num; /* count of channels and ssids that follow
+ __le32 channel_num; /* count of channels and ssids that follow
*
* low half is count of channels in
* channel_list, 0 means default (use all
@@ -435,22 +451,17 @@ struct brcmf_scan_params {
* fixed parameter portion is assumed, otherwise
* ssid in the fixed portion is ignored
*/
- u16 channel_list[1]; /* list of chanspecs */
+ __le16 channel_list[1]; /* list of chanspecs */
};
/* incremental scan struct */
-struct brcmf_iscan_params {
- u32 version;
- u16 action;
- u16 scan_duration;
- struct brcmf_scan_params params;
+struct brcmf_iscan_params_le {
+ __le32 version;
+ __le16 action;
+ __le16 scan_duration;
+ struct brcmf_scan_params_le params_le;
};
-/* 3 fields + size of brcmf_scan_params, not including variable length array */
-#define BRCMF_ISCAN_PARAMS_FIXED_SIZE \
- (offsetof(struct brcmf_iscan_params, params) + \
- sizeof(struct brcmf_ssid))
-
struct brcmf_scan_results {
u32 buflen;
u32 version;
@@ -458,21 +469,28 @@ struct brcmf_scan_results {
struct brcmf_bss_info bss_info[1];
};
+struct brcmf_scan_results_le {
+ __le32 buflen;
+ __le32 version;
+ __le32 count;
+ struct brcmf_bss_info bss_info[1];
+};
+
/* used for association with a specific BSSID and chanspec list */
-struct brcmf_assoc_params {
- u8 bssid[ETH_ALEN]; /* 00:00:00:00:00:00: broadcast scan */
- s32 chanspec_num; /* 0: all available channels,
- * otherwise count of chanspecs in chanspec_list
- */
- chanspec_t chanspec_list[1]; /* list of chanspecs */
+struct brcmf_assoc_params_le {
+ /* 00:00:00:00:00:00: broadcast scan */
+ u8 bssid[ETH_ALEN];
+ /* 0: all available channels, otherwise count of chanspecs in
+ * chanspec_list */
+ __le32 chanspec_num;
+ /* list of chanspecs */
+ __le16 chanspec_list[1];
};
-#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
- (sizeof(struct brcmf_assoc_params) - sizeof(chanspec_t))
/* used for join with or without a specific bssid and channel list */
struct brcmf_join_params {
- struct brcmf_ssid ssid;
- struct brcmf_assoc_params params;
+ struct brcmf_ssid_le ssid_le;
+ struct brcmf_assoc_params_le params_le;
};
/* size of brcmf_scan_results not including variable length array */
@@ -481,8 +499,14 @@ struct brcmf_join_params {
/* incremental scan results struct */
struct brcmf_iscan_results {
- u32 status;
- struct brcmf_scan_results results;
+ union {
+ u32 status;
+ __le32 status_le;
+ };
+ union {
+ struct brcmf_scan_results results;
+ struct brcmf_scan_results_le results_le;
+ };
};
/* size of brcmf_iscan_results not including variable length array */
@@ -495,40 +519,61 @@ struct brcmf_wsec_key {
u32 len; /* key length */
u8 data[WLAN_MAX_KEY_LEN]; /* key data */
u32 pad_1[18];
- u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
- u32 flags; /* misc flags */
- u32 pad_2[2];
- int pad_3;
- int iv_initialized; /* has IV been initialized already? */
- int pad_4;
+ u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+ u32 flags; /* misc flags */
+ u32 pad_2[3];
+ u32 iv_initialized; /* has IV been initialized already? */
+ u32 pad_3;
/* Rx IV */
struct {
u32 hi; /* upper 32 bits of IV */
u16 lo; /* lower 16 bits of IV */
} rxiv;
- u32 pad_5[2];
+ u32 pad_4[2];
+ u8 ea[ETH_ALEN]; /* per station */
+};
+
+/*
+ * dongle requires same struct as above but with fields in little endian order
+ */
+struct brcmf_wsec_key_le {
+ __le32 index; /* key index */
+ __le32 len; /* key length */
+ u8 data[WLAN_MAX_KEY_LEN]; /* key data */
+ __le32 pad_1[18];
+ __le32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+ __le32 flags; /* misc flags */
+ __le32 pad_2[3];
+ __le32 iv_initialized; /* has IV been initialized already? */
+ __le32 pad_3;
+ /* Rx IV */
+ struct {
+ __le32 hi; /* upper 32 bits of IV */
+ __le16 lo; /* lower 16 bits of IV */
+ } rxiv;
+ __le32 pad_4[2];
u8 ea[ETH_ALEN]; /* per station */
};
/* Used to get specific STA parameters */
-struct brcmf_scb_val {
- u32 val;
+struct brcmf_scb_val_le {
+ __le32 val;
u8 ea[ETH_ALEN];
};
/* channel encoding */
-struct brcmf_channel_info {
- int hw_channel;
- int target_channel;
- int scan_channel;
+struct brcmf_channel_info_le {
+ __le32 hw_channel;
+ __le32 target_channel;
+ __le32 scan_channel;
};
-/* Linux network driver ioctl encoding */
-struct brcmf_ioctl {
- uint cmd; /* common ioctl definition */
+/* Bus independent dongle command */
+struct brcmf_dcmd {
+ uint cmd; /* common dongle cmd definition */
void *buf; /* pointer to user buffer */
uint len; /* length of user buffer */
- u8 set; /* get or set request (optional) */
+ u8 set; /* get or set request (optional) */
uint used; /* bytes read or written (optional) */
uint needed; /* bytes needed (optional) */
};
@@ -537,6 +582,7 @@ struct brcmf_ioctl {
struct brcmf_bus; /* device bus info */
struct brcmf_proto; /* device communication protocol info */
struct brcmf_info; /* device driver info */
+struct brcmf_cfg80211_dev; /* cfg80211 device info */
/* Common structure for module and instance linkage */
struct brcmf_pub {
@@ -544,11 +590,11 @@ struct brcmf_pub {
struct brcmf_bus *bus;
struct brcmf_proto *prot;
struct brcmf_info *info;
+ struct brcmf_cfg80211_dev *config;
/* Internal brcmf items */
bool up; /* Driver up/down (to OS) */
bool txoff; /* Transmit flow-controlled */
- bool dongle_reset; /* true = DEVRESET put dongle into reset */
enum brcmf_bus_state busstate;
uint hdrlen; /* Total BRCMF header length (proto + bus) */
uint maxctl; /* Max size rxctl request from proto to bus */
@@ -558,32 +604,45 @@ struct brcmf_pub {
/* Dongle media info */
bool iswl; /* Dongle-resident driver is wl */
unsigned long drv_version; /* Version of dongle-resident driver */
- u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
+ u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
struct dngl_stats dstats; /* Stats for dongle-based data */
/* Additional stats for the bus level */
- unsigned long tx_packets; /* Data packets sent to dongle */
- unsigned long tx_multicast; /* Multicast data packets sent to dongle */
- unsigned long tx_errors; /* Errors in sending data to dongle */
- unsigned long tx_ctlpkts; /* Control packets sent to dongle */
- unsigned long tx_ctlerrs; /* Errors sending control frames to dongle */
- unsigned long rx_packets; /* Packets sent up the network interface */
- unsigned long rx_multicast; /* Multicast packets sent up the network
- interface */
- unsigned long rx_errors; /* Errors processing rx data packets */
- unsigned long rx_ctlpkts; /* Control frames processed from dongle */
- unsigned long rx_ctlerrs; /* Errors in processing rx control frames */
- unsigned long rx_dropped; /* Packets dropped locally (no memory) */
- unsigned long rx_flushed; /* Packets flushed due to
- unscheduled sendup thread */
- unsigned long wd_dpc_sched; /* Number of times dpc scheduled by
- watchdog timer */
-
- unsigned long rx_readahead_cnt; /* Number of packets where header read-ahead
- was used. */
- unsigned long tx_realloc; /* Number of tx packets we had to realloc for
- headroom */
- unsigned long fc_packets; /* Number of flow control pkts recvd */
+
+ /* Data packets sent to dongle */
+ unsigned long tx_packets;
+ /* Multicast data packets sent to dongle */
+ unsigned long tx_multicast;
+ /* Errors in sending data to dongle */
+ unsigned long tx_errors;
+ /* Control packets sent to dongle */
+ unsigned long tx_ctlpkts;
+ /* Errors sending control frames to dongle */
+ unsigned long tx_ctlerrs;
+ /* Packets sent up the network interface */
+ unsigned long rx_packets;
+ /* Multicast packets sent up the network interface */
+ unsigned long rx_multicast;
+ /* Errors processing rx data packets */
+ unsigned long rx_errors;
+ /* Control frames processed from dongle */
+ unsigned long rx_ctlpkts;
+
+ /* Errors in processing rx control frames */
+ unsigned long rx_ctlerrs;
+ /* Packets dropped locally (no memory) */
+ unsigned long rx_dropped;
+ /* Packets flushed due to unscheduled sendup thread */
+ unsigned long rx_flushed;
+ /* Number of times dpc scheduled by watchdog timer */
+ unsigned long wd_dpc_sched;
+
+ /* Number of packets where header read-ahead was used. */
+ unsigned long rx_readahead_cnt;
+ /* Number of tx packets we had to realloc for headroom */
+ unsigned long tx_realloc;
+ /* Number of flow control pkts recvd */
+ unsigned long fc_packets;
/* Last error return */
int bcmerror;
@@ -614,146 +673,15 @@ struct brcmf_if_event {
u8 bssidx;
};
-struct brcmf_timeout {
- u32 limit; /* Expiration time (usec) */
- u32 increment; /* Current expiration increment (usec) */
- u32 elapsed; /* Current elapsed time (usec) */
- u32 tick; /* O/S tick time (usec) */
-};
-
struct bcmevent_name {
uint event;
const char *name;
};
-#if defined(CONFIG_PM_SLEEP)
-extern atomic_t brcmf_mmc_suspend;
-#define BRCMF_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-#define _BRCMF_PM_RESUME_WAIT(a, b) do { \
- int retry = 0; \
- while (atomic_read(&brcmf_mmc_suspend) && retry++ != b) { \
- wait_event_timeout(a, false, HZ/100); \
- } \
- } while (0)
-#define BRCMF_PM_RESUME_WAIT(a) _BRCMF_PM_RESUME_WAIT(a, 30)
-#define BRCMF_PM_RESUME_RETURN_ERROR(a) \
- do { if (atomic_read(&brcmf_mmc_suspend)) return a; } while (0)
-
-#define BRCMF_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \
- uint countdown = (us) + 9999; \
- while ((exp) && (countdown >= 10000)) { \
- wait_event_timeout(a, false, HZ/100); \
- countdown -= 10000; \
- } \
- } while (0)
-
-#else
-
-#define BRCMF_PM_RESUME_WAIT_INIT(a)
-#define BRCMF_PM_RESUME_WAIT(a)
-#define BRCMF_PM_RESUME_RETURN_ERROR(a)
-
-#define BRCMF_SPINWAIT_SLEEP_INIT(a)
-#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \
- uint countdown = (us) + 9; \
- while ((exp) && (countdown >= 10)) { \
- udelay(10); \
- countdown -= 10; \
- } \
- } while (0)
-
-#endif /* defined(CONFIG_PM_SLEEP) */
-
-/*
- * Insmod parameters for debug/test
- */
-
-/* Use interrupts */
-extern uint brcmf_intr;
-
-/* Use polling */
-extern uint brcmf_poll;
-
-/* ARP offload agent mode */
-extern uint brcmf_arp_mode;
-
-/* ARP offload enable */
-extern uint brcmf_arp_enable;
-
-/* Pkt filte enable control */
-extern uint brcmf_pkt_filter_enable;
-
-/* Pkt filter init setup */
-extern uint brcmf_pkt_filter_init;
-
-/* Pkt filter mode control */
-extern uint brcmf_master_mode;
-
-/* Roaming mode control */
-extern uint brcmf_roam;
-
-/* Roaming mode control */
-extern uint brcmf_radio_up;
-
-/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
-extern int brcmf_idletime;
-#define BRCMF_IDLETIME_TICKS 1
-
-/* SDIO Drive Strength */
-extern uint brcmf_sdiod_drive_strength;
-
-/* Override to force tx queueing all the time */
-extern uint brcmf_force_tx_queueing;
-
-#ifdef SDTEST
-/* Echo packet generator (SDIO), pkts/s */
-extern uint brcmf_pktgen;
-
-/* Echo packet len (0 => sawtooth, max 1800) */
-extern uint brcmf_pktgen_len;
-#define BRCMF_MAX_PKTGEN_LEN 1800
-#endif
-
extern const struct bcmevent_name bcmevent_names[];
-extern const int bcmevent_names_size;
-
-
-static inline void MUTEX_LOCK_INIT(struct brcmf_pub *drvr)
-{
-}
-
-static inline void MUTEX_LOCK(struct brcmf_pub *drvr)
-{
-}
-
-static inline void MUTEX_UNLOCK(struct brcmf_pub *drvr)
-{
-}
-
-static inline void MUTEX_LOCK_SOFTAP_SET_INIT(struct brcmf_pub *drvr)
-{
-}
-
-static inline void MUTEX_LOCK_SOFTAP_SET(struct brcmf_pub *drvr)
-{
-}
-
-static inline void MUTEX_UNLOCK_SOFTAP_SET(struct brcmf_pub *drvr)
-{
-}
-static inline void MUTEX_LOCK_WL_SCAN_SET_INIT(void)
-{
-}
-
-static inline void MUTEX_LOCK_WL_SCAN_SET(void)
-{
-}
-
-static inline void MUTEX_UNLOCK_WL_SCAN_SET(void)
-{
-}
+extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
+ char *buf, uint len);
/* Indication from bus module regarding presence/insertion of dongle.
* Return struct brcmf_pub pointer, used as handle to OS module in later calls.
@@ -763,7 +691,9 @@ static inline void MUTEX_UNLOCK_WL_SCAN_SET(void)
extern struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus,
uint bus_hdrlen);
extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx);
-extern int brcmf_netdev_wait_pend8021x(struct net_device *dev);
+extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
+
+extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len);
/* Indication from bus module regarding removal/absence of dongle */
extern void brcmf_detach(struct brcmf_pub *drvr);
@@ -785,25 +715,17 @@ extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
extern void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp,
bool success);
-/* Query ioctl */
-extern int brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx,
+/* Query dongle */
+extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
uint cmd, void *buf, uint len);
/* OS independent layer functions */
extern int brcmf_os_proto_block(struct brcmf_pub *drvr);
extern int brcmf_os_proto_unblock(struct brcmf_pub *drvr);
-extern int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition,
- bool *pending);
-extern int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr);
-extern unsigned int brcmf_os_get_ioctl_resp_timeout(void);
-extern void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec);
#ifdef BCMDBG
-extern int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size);
+extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size);
#endif /* BCMDBG */
-extern void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec);
-extern int brcmf_timeout_expired(struct brcmf_timeout *tmo);
-
extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name);
extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx,
void *pktdata, struct brcmf_event_msg *,
@@ -811,44 +733,24 @@ extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx,
extern void brcmf_c_init(void);
-extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle,
- char *name, u8 *mac_addr, u32 flags, u8 bssidx);
+extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx,
+ struct net_device *ndev, char *name, u8 *mac_addr,
+ u32 flags, u8 bssidx);
extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx);
/* Send packet to dongle via data channel */
extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\
struct sk_buff *pkt);
-extern int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag);
extern int brcmf_bus_start(struct brcmf_pub *drvr);
extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg);
extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg,
int enable, int master_mode);
-/* Linux network driver ioctl encoding */
-struct brcmf_c_ioctl {
- uint cmd; /* common ioctl definition */
- void *buf; /* pointer to user buffer */
- uint len; /* length of user buffer */
- bool set; /* get or set request (optional) */
- uint used; /* bytes read or written (optional) */
- uint needed; /* bytes needed (optional) */
- uint driver; /* to identify target driver */
-};
-
-/* per-driver magic numbers */
-#define BRCMF_IOCTL_MAGIC 0x00444944
-
-/* bump this number if you change the ioctl interface */
-#define BRCMF_IOCTL_VERSION 1
-#define BRCMF_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */
-
-/* common ioctl definitions */
-#define BRCMF_GET_MAGIC 0
-#define BRCMF_GET_VERSION 1
-#define BRCMF_GET_VAR 2
-#define BRCMF_SET_VAR 3
+#define BRCMF_DCMD_SMLEN 256 /* "small" cmd buffer required */
+#define BRCMF_DCMD_MEDLEN 1536 /* "med" cmd buffer required */
+#define BRCMF_DCMD_MAXLEN 8192 /* max length cmd buffer required */
/* message levels */
#define BRCMF_ERROR_VAL 0x0001
@@ -865,40 +767,10 @@ struct brcmf_c_ioctl {
#define BRCMF_BTA_VAL 0x1000
#define BRCMF_ISCAN_VAL 0x2000
-#ifdef SDTEST
-/* For pktgen iovar */
-struct brcmf_pktgen {
- uint version; /* To allow structure change tracking */
- uint freq; /* Max ticks between tx/rx attempts */
- uint count; /* Test packets to send/rcv each attempt */
- uint print; /* Print counts every <print> attempts */
- uint total; /* Total packets (or bursts) */
- uint minlen; /* Minimum length of packets to send */
- uint maxlen; /* Maximum length of packets to send */
- uint numsent; /* Count of test packets sent */
- uint numrcvd; /* Count of test packets received */
- uint numfail; /* Count of test send failures */
- uint mode; /* Test mode (type of test packets) */
- uint stop; /* Stop after this many tx failures */
-};
-
-/* Version in case structure changes */
-#define BRCMF_PKTGEN_VERSION 2
-
-/* Type of test packets to use */
-#define BRCMF_PKTGEN_ECHO 1 /* Send echo requests */
-#define BRCMF_PKTGEN_SEND 2 /* Send discard packets */
-#define BRCMF_PKTGEN_RXBURST 3 /* Request dongle send N packets */
-#define BRCMF_PKTGEN_RECV 4 /* Continuous rx from continuous
- tx dongle */
-#endif /* SDTEST */
-
/* Enter idle immediately (no timeout) */
#define BRCMF_IDLE_IMMEDIATE (-1)
-
-/* Values for idleclock iovar: other values are the sd_divisor to use
- when idle */
#define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change
when idle */
+#define BRCMF_IDLE_INTERVAL 1
#endif /* _BRCMF_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h b/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
index 653cf0daa0eb..a249407c9a1b 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
@@ -18,36 +18,27 @@
#define _BRCMF_BUS_H_
/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef BRCMF_SDALIGN
-#define BRCMF_SDALIGN 32
-#endif
-#if !ISPOWEROF2(BRCMF_SDALIGN)
-#error BRCMF_SDALIGN is not a power of 2!
-#endif
+#define BRCMF_SDALIGN (1 << 6)
+
+/* watchdog polling interval in ms */
+#define BRCMF_WD_POLL_MS 10
/*
* Exported from brcmf bus module (brcmf_usb, brcmf_sdio)
*/
-/* dongle ram module parameter */
-extern int brcmf_dongle_memsize;
-
-/* Tx/Rx bounds module parameters */
-extern uint brcmf_txbound;
-extern uint brcmf_rxbound;
-
-/* Watchdog timer interval */
-extern uint brcmf_watchdog_ms;
-
/* Indicate (dis)interest in finding dongles. */
extern int brcmf_bus_register(void);
extern void brcmf_bus_unregister(void);
+/* obtain linux device object providing bus function */
+extern struct device *brcmf_bus_get_device(struct brcmf_bus *bus);
+
/* Stop bus module: clear pending frames, disable data flow */
-extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex);
+extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus);
/* Initialize bus module: prepare for communication w/dongle */
-extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex);
+extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr);
/* Send a data frame to the dongle. Callee disposes of txp. */
extern int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *txp);
@@ -61,18 +52,6 @@ brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen);
extern int
brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen);
-/* Check for and handle local prot-specific iovar commands */
-extern int brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name,
- void *params, int plen, void *arg, int len,
- bool set);
-
-/* Add bus dump output to a buffer */
-extern void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr,
- struct brcmu_strbuf *strbuf);
-
-/* Clear any bus counters */
-extern void brcmf_bus_clearcounts(struct brcmf_pub *drvr);
-
extern void brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick);
#endif /* _BRCMF_BUS_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
index 345acabe935e..e34c5c3d1d55 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
@@ -14,6 +14,11 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/*******************************************************************************
+ * Communicates with the dongle by using dcmd codes.
+ * For certain dcmd codes, the dongle interprets string data from the host.
+ ******************************************************************************/
+
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/sched.h>
@@ -27,29 +32,26 @@
#include "dhd_bus.h"
#include "dhd_dbg.h"
-struct brcmf_proto_cdc_ioctl {
- u32 cmd; /* ioctl command value */
- u32 len; /* lower 16: output buflen;
+struct brcmf_proto_cdc_dcmd {
+ __le32 cmd; /* dongle command value */
+ __le32 len; /* lower 16: output buflen;
* upper 16: input buflen (excludes header) */
- u32 flags; /* flag defns given below */
- u32 status; /* status code returned from the device */
+ __le32 flags; /* flag defns given below */
+ __le32 status; /* status code returned from the device */
};
/* Max valid buffer size that can be sent to the dongle */
#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN)
/* CDC flag definitions */
-#define CDCF_IOC_ERROR 0x01 /* 1=ioctl cmd failed */
-#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */
-#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */
-#define CDCF_IOC_IF_SHIFT 12
-#define CDCF_IOC_ID_MASK 0xFFFF0000 /* id an ioctl pairing */
-#define CDCF_IOC_ID_SHIFT 16 /* ID Mask shift bits */
-#define CDC_IOC_ID(flags) \
- (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
-#define CDC_SET_IF_IDX(hdr, idx) \
- ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \
- ((idx) << CDCF_IOC_IF_SHIFT)))
+#define CDC_DCMD_ERROR 0x01 /* 1=cmd failed */
+#define CDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */
+#define CDC_DCMD_IF_MASK 0xF000 /* I/F index */
+#define CDC_DCMD_IF_SHIFT 12
+#define CDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */
+#define CDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */
+#define CDC_DCMD_ID(flags) \
+ (((flags) & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT)
/*
* BDC header - Broadcom specific extension of CDC.
@@ -79,7 +81,7 @@ struct brcmf_proto_bdc_header {
};
-#define RETRIES 2 /* # of retries to retrieve matching ioctl response */
+#define RETRIES 2 /* # of retries to retrieve matching dcmd response */
#define BUS_HEADER_LEN (16+BRCMF_SDALIGN) /* Must be atleast SDPCM_RESERVE
* (amount of header tha might be added)
* plus any space that might be needed
@@ -94,17 +96,17 @@ struct brcmf_proto {
u8 pending;
u32 lastcmd;
u8 bus_header[BUS_HEADER_LEN];
- struct brcmf_proto_cdc_ioctl msg;
- unsigned char buf[BRCMF_C_IOCTL_MAXLEN + ROUND_UP_MARGIN];
+ struct brcmf_proto_cdc_dcmd msg;
+ unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN];
};
static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)
{
struct brcmf_proto *prot = drvr->prot;
int len = le32_to_cpu(prot->msg.len) +
- sizeof(struct brcmf_proto_cdc_ioctl);
+ sizeof(struct brcmf_proto_cdc_dcmd);
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
/* NOTE : cdc->msg.len holds the desired length of the buffer to be
* returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
@@ -123,31 +125,31 @@ static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
int ret;
struct brcmf_proto *prot = drvr->prot;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
do {
ret = brcmf_sdbrcm_bus_rxctl(drvr->bus,
(unsigned char *)&prot->msg,
- len + sizeof(struct brcmf_proto_cdc_ioctl));
+ len + sizeof(struct brcmf_proto_cdc_dcmd));
if (ret < 0)
break;
- } while (CDC_IOC_ID(le32_to_cpu(prot->msg.flags)) != id);
+ } while (CDC_DCMD_ID(le32_to_cpu(prot->msg.flags)) != id);
return ret;
}
int
-brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
- void *buf, uint len)
+brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+ void *buf, uint len)
{
struct brcmf_proto *prot = drvr->prot;
- struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
+ struct brcmf_proto_cdc_dcmd *msg = &prot->msg;
void *info;
int ret = 0, retries = 0;
- u32 id, flags = 0;
+ u32 id, flags;
- BRCMF_TRACE(("%s: Enter\n", __func__));
- BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len);
/* Respond "bcmerror" and "bcmerrorstr" with local cache */
if (cmd == BRCMF_C_GET_VAR && buf) {
@@ -161,21 +163,22 @@ brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
}
}
- memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
+ memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd));
msg->cmd = cpu_to_le32(cmd);
msg->len = cpu_to_le32(len);
- msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
- CDC_SET_IF_IDX(msg, ifidx);
- msg->flags = cpu_to_le32(msg->flags);
+ flags = (++prot->reqid << CDC_DCMD_ID_SHIFT);
+ flags = (flags & ~CDC_DCMD_IF_MASK) |
+ (ifidx << CDC_DCMD_IF_SHIFT);
+ msg->flags = cpu_to_le32(flags);
if (buf)
memcpy(prot->buf, buf, len);
ret = brcmf_proto_cdc_msg(drvr);
if (ret < 0) {
- BRCMF_ERROR(("brcmf_proto_cdc_query_ioctl: brcmf_proto_cdc_msg "
- "failed w/status %d\n", ret));
+ brcmf_dbg(ERROR, "brcmf_proto_cdc_msg failed w/status %d\n",
+ ret);
goto done;
}
@@ -186,14 +189,13 @@ retry:
goto done;
flags = le32_to_cpu(msg->flags);
- id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
+ id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT;
if ((id < prot->reqid) && (++retries < RETRIES))
goto retry;
if (id != prot->reqid) {
- BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
- brcmf_ifname(drvr, ifidx), __func__, id,
- prot->reqid));
+ brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n",
+ brcmf_ifname(drvr, ifidx), id, prot->reqid);
ret = -EINVAL;
goto done;
}
@@ -209,7 +211,7 @@ retry:
}
/* Check the ERROR flag */
- if (flags & CDCF_IOC_ERROR) {
+ if (flags & CDC_DCMD_ERROR) {
ret = le32_to_cpu(msg->status);
/* Cache error from dongle */
drvr->dongle_error = ret;
@@ -219,24 +221,25 @@ done:
return ret;
}
-int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
- void *buf, uint len)
+int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+ void *buf, uint len)
{
struct brcmf_proto *prot = drvr->prot;
- struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
+ struct brcmf_proto_cdc_dcmd *msg = &prot->msg;
int ret = 0;
u32 flags, id;
- BRCMF_TRACE(("%s: Enter\n", __func__));
- BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len);
- memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
+ memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd));
msg->cmd = cpu_to_le32(cmd);
msg->len = cpu_to_le32(len);
- msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET;
- CDC_SET_IF_IDX(msg, ifidx);
- msg->flags = cpu_to_le32(msg->flags);
+ flags = (++prot->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET;
+ flags = (flags & ~CDC_DCMD_IF_MASK) |
+ (ifidx << CDC_DCMD_IF_SHIFT);
+ msg->flags = cpu_to_le32(flags);
if (buf)
memcpy(prot->buf, buf, len);
@@ -250,18 +253,17 @@ int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
goto done;
flags = le32_to_cpu(msg->flags);
- id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
+ id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT;
if (id != prot->reqid) {
- BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
- brcmf_ifname(drvr, ifidx), __func__, id,
- prot->reqid));
+ brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n",
+ brcmf_ifname(drvr, ifidx), id, prot->reqid);
ret = -EINVAL;
goto done;
}
/* Check the ERROR flag */
- if (flags & CDCF_IOC_ERROR) {
+ if (flags & CDC_DCMD_ERROR) {
ret = le32_to_cpu(msg->status);
/* Cache error from dongle */
drvr->dongle_error = ret;
@@ -272,65 +274,64 @@ done:
}
int
-brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx, struct brcmf_ioctl *ioc,
- void *buf, int len)
+brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, struct brcmf_dcmd *dcmd,
+ int len)
{
struct brcmf_proto *prot = drvr->prot;
int ret = -1;
if (drvr->busstate == BRCMF_BUS_DOWN) {
- BRCMF_ERROR(("%s : bus is down. we have nothing to do\n",
- __func__));
+ brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n");
return ret;
}
brcmf_os_proto_block(drvr);
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
- if (len > BRCMF_C_IOCTL_MAXLEN)
+ if (len > BRCMF_DCMD_MAXLEN)
goto done;
if (prot->pending == true) {
- BRCMF_TRACE(("CDC packet is pending!!!! cmd=0x%x (%lu) "
- "lastcmd=0x%x (%lu)\n",
- ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd,
- (unsigned long)prot->lastcmd));
- if ((ioc->cmd == BRCMF_C_SET_VAR) ||
- (ioc->cmd == BRCMF_C_GET_VAR))
- BRCMF_TRACE(("iovar cmd=%s\n", (char *)buf));
+ brcmf_dbg(TRACE, "CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n",
+ dcmd->cmd, (unsigned long)dcmd->cmd, prot->lastcmd,
+ (unsigned long)prot->lastcmd);
+ if (dcmd->cmd == BRCMF_C_SET_VAR ||
+ dcmd->cmd == BRCMF_C_GET_VAR)
+ brcmf_dbg(TRACE, "iovar cmd=%s\n", (char *)dcmd->buf);
goto done;
}
prot->pending = true;
- prot->lastcmd = ioc->cmd;
- if (ioc->set)
- ret = brcmf_proto_cdc_set_ioctl(drvr, ifidx, ioc->cmd,
- buf, len);
+ prot->lastcmd = dcmd->cmd;
+ if (dcmd->set)
+ ret = brcmf_proto_cdc_set_dcmd(drvr, ifidx, dcmd->cmd,
+ dcmd->buf, len);
else {
- ret = brcmf_proto_cdc_query_ioctl(drvr, ifidx, ioc->cmd,
- buf, len);
+ ret = brcmf_proto_cdc_query_dcmd(drvr, ifidx, dcmd->cmd,
+ dcmd->buf, len);
if (ret > 0)
- ioc->used = ret - sizeof(struct brcmf_proto_cdc_ioctl);
+ dcmd->used = ret -
+ sizeof(struct brcmf_proto_cdc_dcmd);
}
- /* Too many programs assume ioctl() returns 0 on success */
if (ret >= 0)
ret = 0;
else {
- struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
+ struct brcmf_proto_cdc_dcmd *msg = &prot->msg;
/* len == needed when set/query fails from dongle */
- ioc->needed = le32_to_cpu(msg->len);
+ dcmd->needed = le32_to_cpu(msg->len);
}
- /* Intercept the wme_dp ioctl here */
- if (!ret && ioc->cmd == BRCMF_C_SET_VAR &&
- !strcmp(buf, "wme_dp")) {
- int slen, val = 0;
+ /* Intercept the wme_dp dongle cmd here */
+ if (!ret && dcmd->cmd == BRCMF_C_SET_VAR &&
+ !strcmp(dcmd->buf, "wme_dp")) {
+ int slen;
+ __le32 val = 0;
slen = strlen("wme_dp") + 1;
if (len >= (int)(slen + sizeof(int)))
- memcpy(&val, (char *)buf + slen, sizeof(int));
+ memcpy(&val, (char *)dcmd->buf + slen, sizeof(int));
drvr->wme_dp = (u8) le32_to_cpu(val);
}
@@ -342,15 +343,14 @@ done:
return ret;
}
-#define PKTSUMNEEDED(skb) \
- (((struct sk_buff *)(skb))->ip_summed == CHECKSUM_PARTIAL)
-#define PKTSETSUMGOOD(skb, x) \
- (((struct sk_buff *)(skb))->ip_summed = \
- ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE))
+static bool pkt_sum_needed(struct sk_buff *skb)
+{
+ return skb->ip_summed == CHECKSUM_PARTIAL;
+}
-void brcmf_proto_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf)
+static void pkt_set_sum_good(struct sk_buff *skb, bool x)
{
- brcmu_bprintf(strbuf, "Protocol CDC: reqid %d\n", drvr->prot->reqid);
+ skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
}
void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
@@ -358,7 +358,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
{
struct brcmf_proto_bdc_header *h;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
/* Push BDC header used to convey priority for buses that don't */
@@ -367,7 +367,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
- if (PKTSUMNEEDED(pktbuf))
+ if (pkt_sum_needed(pktbuf))
h->flags |= BDC_FLAG_SUM_NEEDED;
h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
@@ -381,13 +381,13 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx,
{
struct brcmf_proto_bdc_header *h;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
/* Pop BDC header used to convey priority for buses that don't */
if (pktbuf->len < BDC_HEADER_LEN) {
- BRCMF_ERROR(("%s: rx data too short (%d < %d)\n", __func__,
- pktbuf->len, BDC_HEADER_LEN));
+ brcmf_dbg(ERROR, "rx data too short (%d < %d)\n",
+ pktbuf->len, BDC_HEADER_LEN);
return -EBADE;
}
@@ -395,23 +395,21 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx,
*ifidx = BDC_GET_IF_IDX(h);
if (*ifidx >= BRCMF_MAX_IFS) {
- BRCMF_ERROR(("%s: rx data ifnum out of range (%d)\n",
- __func__, *ifidx));
+ brcmf_dbg(ERROR, "rx data ifnum out of range (%d)\n", *ifidx);
return -EBADE;
}
if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
BDC_PROTO_VER) {
- BRCMF_ERROR(("%s: non-BDC packet received, flags 0x%x\n",
- brcmf_ifname(drvr, *ifidx), h->flags));
+ brcmf_dbg(ERROR, "%s: non-BDC packet received, flags 0x%x\n",
+ brcmf_ifname(drvr, *ifidx), h->flags);
return -EBADE;
}
if (h->flags & BDC_FLAG_SUM_GOOD) {
- BRCMF_INFO(("%s: BDC packet received with good rx-csum, "
- "flags 0x%x\n",
- brcmf_ifname(drvr, *ifidx), h->flags));
- PKTSETSUMGOOD(pktbuf, true);
+ brcmf_dbg(INFO, "%s: BDC packet received with good rx-csum, flags 0x%x\n",
+ brcmf_ifname(drvr, *ifidx), h->flags);
+ pkt_set_sum_good(pktbuf, true);
}
pktbuf->priority = h->priority & BDC_PRIORITY_MASK;
@@ -426,21 +424,19 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
struct brcmf_proto *cdc;
cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC);
- if (!cdc) {
- BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
+ if (!cdc)
goto fail;
- }
/* ensure that the msg buf directly follows the cdc msg struct */
if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) {
- BRCMF_ERROR(("struct brcmf_proto is not correctly defined\n"));
+ brcmf_dbg(ERROR, "struct brcmf_proto is not correctly defined\n");
goto fail;
}
drvr->prot = cdc;
drvr->hdrlen += BDC_HEADER_LEN;
- drvr->maxctl = BRCMF_C_IOCTL_MAXLEN +
- sizeof(struct brcmf_proto_cdc_ioctl) + ROUND_UP_MARGIN;
+ drvr->maxctl = BRCMF_DCMD_MAXLEN +
+ sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN;
return 0;
fail:
@@ -472,13 +468,13 @@ int brcmf_proto_init(struct brcmf_pub *drvr)
int ret = 0;
char buf[128];
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
brcmf_os_proto_block(drvr);
/* Get the device MAC address */
strcpy(buf, "cur_etheraddr");
- ret = brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR,
+ ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR,
buf, sizeof(buf));
if (ret < 0) {
brcmf_os_proto_unblock(drvr);
@@ -488,7 +484,7 @@ int brcmf_proto_init(struct brcmf_pub *drvr)
brcmf_os_proto_unblock(drvr);
- ret = brcmf_c_preinit_ioctls(drvr);
+ ret = brcmf_c_preinit_dcmds(drvr);
/* Always assumes wl for now */
drvr->iswl = true;
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_common.c b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
index fdec4683c422..891826197f96 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
@@ -30,73 +30,61 @@
#define DOT11_OUI_LEN 3
#define BCMILCP_BCM_SUBTYPE_EVENT 1
#define PKTFILTER_BUF_SIZE 2048
+#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */
int brcmf_msg_level;
#define MSGTRACE_VERSION 1
+#define BRCMF_PKT_FILTER_FIXED_LEN offsetof(struct brcmf_pkt_filter_le, u)
+#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \
+ offsetof(struct brcmf_pkt_filter_pattern_le, mask_and_pattern)
+
#ifdef BCMDBG
-const char brcmf_version[] =
-"Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on " __DATE__
-" at " __TIME__;
+static const char brcmf_version[] =
+ "Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on "
+ __DATE__ " at " __TIME__;
#else
-const char brcmf_version[] = "Dongle Host Driver, version " BRCMF_VERSION_STR;
+static const char brcmf_version[] =
+ "Dongle Host Driver, version " BRCMF_VERSION_STR;
#endif
-/* IOVar table */
-enum {
- IOV_VERSION = 1,
- IOV_MSGLEVEL,
- IOV_BCMERRORSTR,
- IOV_BCMERROR,
- IOV_DUMP,
- IOV_CLEARCOUNTS,
- IOV_LOGDUMP,
- IOV_LOGCAL,
- IOV_LOGSTAMP,
- IOV_GPIOOB,
- IOV_IOCTLTIMEOUT,
- IOV_LAST
-};
-
-const struct brcmu_iovar brcmf_iovars[] = {
- {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(brcmf_version)}
- ,
-#ifdef BCMDBG
- {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0}
- ,
-#endif /* BCMDBG */
- {"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN}
- ,
- {"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0}
- ,
- {"dump", IOV_DUMP, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN}
- ,
- {"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0}
- ,
- {"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0}
- ,
- {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0}
- ,
- {NULL, 0, 0, 0, 0}
-};
-
/* Message trace header */
struct msgtrace_hdr {
u8 version;
u8 spare;
- u16 len; /* Len of the trace */
- u32 seqnum; /* Sequence number of message. Useful
+ __be16 len; /* Len of the trace */
+ __be32 seqnum; /* Sequence number of message. Useful
* if the messsage has been lost
* because of DMA error or a bus reset
* (ex: SDIO Func2)
*/
- u32 discarded_bytes; /* Number of discarded bytes because of
+ __be32 discarded_bytes; /* Number of discarded bytes because of
trace overflow */
- u32 discarded_printf; /* Number of discarded printf
+ __be32 discarded_printf; /* Number of discarded printf
because of trace overflow */
} __packed;
+
+uint
+brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
+{
+ uint len;
+
+ len = strlen(name) + 1;
+
+ if ((len + datalen) > buflen)
+ return 0;
+
+ strncpy(buf, name, buflen);
+
+ /* append data onto the end of the name string */
+ memcpy(&buf[len], data, datalen);
+ len += datalen;
+
+ return len;
+}
+
void brcmf_c_init(void)
{
/* Init global variables at run-time, not as part of the declaration.
@@ -110,147 +98,6 @@ void brcmf_c_init(void)
brcmf_msg_level = BRCMF_ERROR_VAL;
}
-static int brcmf_c_dump(struct brcmf_pub *drvr, char *buf, int buflen)
-{
- struct brcmu_strbuf b;
- struct brcmu_strbuf *strbuf = &b;
-
- brcmu_binit(strbuf, buf, buflen);
-
- /* Base info */
- brcmu_bprintf(strbuf, "%s\n", brcmf_version);
- brcmu_bprintf(strbuf, "\n");
- brcmu_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n",
- drvr->up, drvr->txoff, drvr->busstate);
- brcmu_bprintf(strbuf, "pub.hdrlen %d pub.maxctl %d pub.rxsz %d\n",
- drvr->hdrlen, drvr->maxctl, drvr->rxsz);
- brcmu_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %pM\n",
- drvr->iswl, drvr->drv_version, &drvr->mac);
- brcmu_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", drvr->bcmerror,
- drvr->tickcnt);
-
- brcmu_bprintf(strbuf, "dongle stats:\n");
- brcmu_bprintf(strbuf,
- "tx_packets %ld tx_bytes %ld tx_errors %ld tx_dropped %ld\n",
- drvr->dstats.tx_packets, drvr->dstats.tx_bytes,
- drvr->dstats.tx_errors, drvr->dstats.tx_dropped);
- brcmu_bprintf(strbuf,
- "rx_packets %ld rx_bytes %ld rx_errors %ld rx_dropped %ld\n",
- drvr->dstats.rx_packets, drvr->dstats.rx_bytes,
- drvr->dstats.rx_errors, drvr->dstats.rx_dropped);
- brcmu_bprintf(strbuf, "multicast %ld\n", drvr->dstats.multicast);
-
- brcmu_bprintf(strbuf, "bus stats:\n");
- brcmu_bprintf(strbuf, "tx_packets %ld tx_multicast %ld tx_errors %ld\n",
- drvr->tx_packets, drvr->tx_multicast, drvr->tx_errors);
- brcmu_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n",
- drvr->tx_ctlpkts, drvr->tx_ctlerrs);
- brcmu_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld\n",
- drvr->rx_packets, drvr->rx_multicast, drvr->rx_errors);
- brcmu_bprintf(strbuf,
- "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld rx_flushed %ld\n",
- drvr->rx_ctlpkts, drvr->rx_ctlerrs, drvr->rx_dropped,
- drvr->rx_flushed);
- brcmu_bprintf(strbuf,
- "rx_readahead_cnt %ld tx_realloc %ld fc_packets %ld\n",
- drvr->rx_readahead_cnt, drvr->tx_realloc, drvr->fc_packets);
- brcmu_bprintf(strbuf, "wd_dpc_sched %ld\n", drvr->wd_dpc_sched);
- brcmu_bprintf(strbuf, "\n");
-
- /* Add any prot info */
- brcmf_proto_dump(drvr, strbuf);
- brcmu_bprintf(strbuf, "\n");
-
- /* Add any bus info */
- brcmf_sdbrcm_bus_dump(drvr, strbuf);
-
- return !strbuf->size ? -EOVERFLOW : 0;
-}
-
-static int
-brcmf_c_doiovar(struct brcmf_pub *drvr, const struct brcmu_iovar *vi,
- u32 actionid, const char *name, void *params, int plen,
- void *arg, int len, int val_size)
-{
- int bcmerror = 0;
- s32 int_val = 0;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
- if (bcmerror != 0)
- goto exit;
-
- if (plen >= (int)sizeof(int_val))
- memcpy(&int_val, params, sizeof(int_val));
-
- switch (actionid) {
- case IOV_GVAL(IOV_VERSION):
- /* Need to have checked buffer length */
- strncpy((char *)arg, brcmf_version, len);
- break;
-
- case IOV_GVAL(IOV_MSGLEVEL):
- int_val = (s32) brcmf_msg_level;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_MSGLEVEL):
- brcmf_msg_level = int_val;
- break;
-
- case IOV_GVAL(IOV_BCMERRORSTR):
- strncpy((char *)arg, "bcm_error",
- BCME_STRLEN);
- ((char *)arg)[BCME_STRLEN - 1] = 0x00;
- break;
-
- case IOV_GVAL(IOV_BCMERROR):
- int_val = (s32) drvr->bcmerror;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_GVAL(IOV_DUMP):
- bcmerror = brcmf_c_dump(drvr, arg, len);
- break;
-
- case IOV_SVAL(IOV_CLEARCOUNTS):
- drvr->tx_packets = drvr->rx_packets = 0;
- drvr->tx_errors = drvr->rx_errors = 0;
- drvr->tx_ctlpkts = drvr->rx_ctlpkts = 0;
- drvr->tx_ctlerrs = drvr->rx_ctlerrs = 0;
- drvr->rx_dropped = 0;
- drvr->rx_readahead_cnt = 0;
- drvr->tx_realloc = 0;
- drvr->wd_dpc_sched = 0;
- memset(&drvr->dstats, 0, sizeof(drvr->dstats));
- brcmf_bus_clearcounts(drvr);
- break;
-
- case IOV_GVAL(IOV_IOCTLTIMEOUT):{
- int_val = (s32) brcmf_os_get_ioctl_resp_timeout();
- memcpy(arg, &int_val, sizeof(int_val));
- break;
- }
-
- case IOV_SVAL(IOV_IOCTLTIMEOUT):{
- if (int_val <= 0)
- bcmerror = -EINVAL;
- else
- brcmf_os_set_ioctl_resp_timeout((unsigned int)
- int_val);
- break;
- }
-
- default:
- bcmerror = -ENOTSUPP;
- break;
- }
-
-exit:
- return bcmerror;
-}
-
bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
struct sk_buff *pkt, int prec)
{
@@ -278,159 +125,28 @@ bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
/* Evict if needed */
if (eprec >= 0) {
/* Detect queueing to unconfigured precedence */
- discard_oldest = AC_BITMAP_TST(drvr->wme_dp, eprec);
+ discard_oldest = ac_bitmap_tst(drvr->wme_dp, eprec);
if (eprec == prec && !discard_oldest)
return false; /* refuse newer (incoming) packet */
/* Evict packet according to discard policy */
p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
brcmu_pktq_pdeq_tail(q, eprec);
- if (p == NULL) {
- BRCMF_ERROR(("%s: brcmu_pktq_penq() failed, oldest %d.",
- __func__, discard_oldest));
- }
+ if (p == NULL)
+ brcmf_dbg(ERROR, "brcmu_pktq_penq() failed, oldest %d\n",
+ discard_oldest);
+
brcmu_pkt_buf_free_skb(p);
}
/* Enqueue */
p = brcmu_pktq_penq(q, prec, pkt);
- if (p == NULL) {
- BRCMF_ERROR(("%s: brcmu_pktq_penq() failed.", __func__));
- }
+ if (p == NULL)
+ brcmf_dbg(ERROR, "brcmu_pktq_penq() failed\n");
return p != NULL;
}
-static int
-brcmf_c_iovar_op(struct brcmf_pub *drvr, const char *name,
- void *params, int plen, void *arg, int len, bool set)
-{
- int bcmerror = 0;
- int val_size;
- const struct brcmu_iovar *vi = NULL;
- u32 actionid;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (name == NULL || len <= 0)
- return -EINVAL;
-
- /* Set does not take qualifiers */
- if (set && (params || plen))
- return -EINVAL;
-
- /* Get must have return space;*/
- if (!set && !(arg && len))
- return -EINVAL;
-
- vi = brcmu_iovar_lookup(brcmf_iovars, name);
- if (vi == NULL) {
- bcmerror = -ENOTSUPP;
- goto exit;
- }
-
- BRCMF_CTL(("%s: %s %s, len %d plen %d\n", __func__,
- name, (set ? "set" : "get"), len, plen));
-
- /* set up 'params' pointer in case this is a set command so that
- * the convenience int and bool code can be common to set and get
- */
- if (params == NULL) {
- params = arg;
- plen = len;
- }
-
- if (vi->type == IOVT_VOID)
- val_size = 0;
- else if (vi->type == IOVT_BUFFER)
- val_size = len;
- else
- /* all other types are integer sized */
- val_size = sizeof(int);
-
- actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
- bcmerror =
- brcmf_c_doiovar(drvr, vi, actionid, name, params, plen, arg, len,
- val_size);
-
-exit:
- return bcmerror;
-}
-
-int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc, void *buf,
- uint buflen)
-{
- int bcmerror = 0;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (!buf)
- return -EINVAL;
-
- switch (ioc->cmd) {
- case BRCMF_GET_MAGIC:
- if (buflen < sizeof(int))
- bcmerror = -EOVERFLOW;
- else
- *(int *)buf = BRCMF_IOCTL_MAGIC;
- break;
-
- case BRCMF_GET_VERSION:
- if (buflen < sizeof(int))
- bcmerror = -EOVERFLOW;
- else
- *(int *)buf = BRCMF_IOCTL_VERSION;
- break;
-
- case BRCMF_GET_VAR:
- case BRCMF_SET_VAR:{
- char *arg;
- uint arglen;
-
- /* scan past the name to any arguments */
- for (arg = buf, arglen = buflen; *arg && arglen;
- arg++, arglen--)
- ;
-
- if (*arg) {
- bcmerror = -EOVERFLOW;
- break;
- }
-
- /* account for the NUL terminator */
- arg++, arglen--;
-
- /* call with the appropriate arguments */
- if (ioc->cmd == BRCMF_GET_VAR)
- bcmerror = brcmf_c_iovar_op(drvr, buf, arg,
- arglen, buf, buflen, IOV_GET);
- else
- bcmerror =
- brcmf_c_iovar_op(drvr, buf, NULL, 0, arg,
- arglen, IOV_SET);
- if (bcmerror != -ENOTSUPP)
- break;
-
- /* if still not found, try bus module */
- if (ioc->cmd == BRCMF_GET_VAR)
- bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr,
- buf, arg, arglen, buf, buflen,
- IOV_GET);
- else
- bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr,
- buf, NULL, 0, arg, arglen,
- IOV_SET);
-
- break;
- }
-
- default:
- bcmerror = -ENOTSUPP;
- }
-
- return bcmerror;
-}
-
-#ifdef SHOW_EVENTS
+#ifdef BCMDBG
static void
brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
{
@@ -502,6 +218,11 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}
};
uint event_type, flags, auth_type, datalen;
+ static u32 seqnum_prev;
+ struct msgtrace_hdr hdr;
+ u32 nblost;
+ char *s, *p;
+
event_type = be32_to_cpu(event->event_type);
flags = be16_to_cpu(event->flags);
status = be32_to_cpu(event->status);
@@ -517,9 +238,9 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
event_name = event_names[i].event_name;
}
- BRCMF_EVENT(("EVENT: %s, event ID = %d\n", event_name, event_type));
- BRCMF_EVENT(("flags 0x%04x, status %d, reason %d, auth_type %d"
- " MAC %s\n", flags, status, reason, auth_type, eabuf));
+ brcmf_dbg(EVENT, "EVENT: %s, event ID = %d\n", event_name, event_type);
+ brcmf_dbg(EVENT, "flags 0x%04x, status %d, reason %d, auth_type %d MAC %s\n",
+ flags, status, reason, auth_type, eabuf);
if (flags & BRCMF_EVENT_MSG_LINK)
link = true;
@@ -532,36 +253,34 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
case BRCMF_E_START:
case BRCMF_E_DEAUTH:
case BRCMF_E_DISASSOC:
- BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
break;
case BRCMF_E_ASSOC_IND:
case BRCMF_E_REASSOC_IND:
- BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
break;
case BRCMF_E_ASSOC:
case BRCMF_E_REASSOC:
- if (status == BRCMF_E_STATUS_SUCCESS) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n",
- event_name, eabuf));
- } else if (status == BRCMF_E_STATUS_TIMEOUT) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n",
- event_name, eabuf));
- } else if (status == BRCMF_E_STATUS_FAIL) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, FAILURE,"
- " reason %d\n", event_name, eabuf,
- (int)reason));
- } else {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, unexpected status "
- "%d\n", event_name, eabuf, (int)status));
- }
+ if (status == BRCMF_E_STATUS_SUCCESS)
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, SUCCESS\n",
+ event_name, eabuf);
+ else if (status == BRCMF_E_STATUS_TIMEOUT)
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, TIMEOUT\n",
+ event_name, eabuf);
+ else if (status == BRCMF_E_STATUS_FAIL)
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, FAILURE, reason %d\n",
+ event_name, eabuf, (int)reason);
+ else
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, unexpected status %d\n",
+ event_name, eabuf, (int)status);
break;
case BRCMF_E_DEAUTH_IND:
case BRCMF_E_DISASSOC_IND:
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name,
- eabuf, (int)reason));
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, reason %d\n",
+ event_name, eabuf, (int)reason);
break;
case BRCMF_E_AUTH:
@@ -574,19 +293,18 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
sprintf(err_msg, "AUTH unknown: %d", (int)auth_type);
auth_str = err_msg;
}
- if (event_type == BRCMF_E_AUTH_IND) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name,
- eabuf, auth_str));
- } else if (status == BRCMF_E_STATUS_SUCCESS) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n",
- event_name, eabuf, auth_str));
- } else if (status == BRCMF_E_STATUS_TIMEOUT) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
- event_name, eabuf, auth_str));
- } else if (status == BRCMF_E_STATUS_FAIL) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, "
- "reason %d\n",
- event_name, eabuf, auth_str, (int)reason));
+ if (event_type == BRCMF_E_AUTH_IND)
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s\n",
+ event_name, eabuf, auth_str);
+ else if (status == BRCMF_E_STATUS_SUCCESS)
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, SUCCESS\n",
+ event_name, eabuf, auth_str);
+ else if (status == BRCMF_E_STATUS_TIMEOUT)
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
+ event_name, eabuf, auth_str);
+ else if (status == BRCMF_E_STATUS_FAIL) {
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n",
+ event_name, eabuf, auth_str, (int)reason);
}
break;
@@ -594,149 +312,138 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
case BRCMF_E_JOIN:
case BRCMF_E_ROAM:
case BRCMF_E_SET_SSID:
- if (status == BRCMF_E_STATUS_SUCCESS) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name,
- eabuf));
- } else if (status == BRCMF_E_STATUS_FAIL) {
- BRCMF_EVENT(("MACEVENT: %s, failed\n", event_name));
- } else if (status == BRCMF_E_STATUS_NO_NETWORKS) {
- BRCMF_EVENT(("MACEVENT: %s, no networks found\n",
- event_name));
- } else {
- BRCMF_EVENT(("MACEVENT: %s, unexpected status %d\n",
- event_name, (int)status));
- }
+ if (status == BRCMF_E_STATUS_SUCCESS)
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n",
+ event_name, eabuf);
+ else if (status == BRCMF_E_STATUS_FAIL)
+ brcmf_dbg(EVENT, "MACEVENT: %s, failed\n", event_name);
+ else if (status == BRCMF_E_STATUS_NO_NETWORKS)
+ brcmf_dbg(EVENT, "MACEVENT: %s, no networks found\n",
+ event_name);
+ else
+ brcmf_dbg(EVENT, "MACEVENT: %s, unexpected status %d\n",
+ event_name, (int)status);
break;
case BRCMF_E_BEACON_RX:
- if (status == BRCMF_E_STATUS_SUCCESS) {
- BRCMF_EVENT(("MACEVENT: %s, SUCCESS\n", event_name));
- } else if (status == BRCMF_E_STATUS_FAIL) {
- BRCMF_EVENT(("MACEVENT: %s, FAIL\n", event_name));
- } else {
- BRCMF_EVENT(("MACEVENT: %s, status %d\n", event_name,
- status));
- }
+ if (status == BRCMF_E_STATUS_SUCCESS)
+ brcmf_dbg(EVENT, "MACEVENT: %s, SUCCESS\n", event_name);
+ else if (status == BRCMF_E_STATUS_FAIL)
+ brcmf_dbg(EVENT, "MACEVENT: %s, FAIL\n", event_name);
+ else
+ brcmf_dbg(EVENT, "MACEVENT: %s, status %d\n",
+ event_name, status);
break;
case BRCMF_E_LINK:
- BRCMF_EVENT(("MACEVENT: %s %s\n", event_name,
- link ? "UP" : "DOWN"));
+ brcmf_dbg(EVENT, "MACEVENT: %s %s\n",
+ event_name, link ? "UP" : "DOWN");
break;
case BRCMF_E_MIC_ERROR:
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
- event_name, eabuf, group, flush_txq));
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
+ event_name, eabuf, group, flush_txq);
break;
case BRCMF_E_ICV_ERROR:
case BRCMF_E_UNICAST_DECODE_ERROR:
case BRCMF_E_MULTICAST_DECODE_ERROR:
- BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
break;
case BRCMF_E_TXFAIL:
- BRCMF_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf));
+ brcmf_dbg(EVENT, "MACEVENT: %s, RA %s\n", event_name, eabuf);
break;
case BRCMF_E_SCAN_COMPLETE:
case BRCMF_E_PMKID_CACHE:
- BRCMF_EVENT(("MACEVENT: %s\n", event_name));
+ brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name);
break;
case BRCMF_E_PFN_NET_FOUND:
case BRCMF_E_PFN_NET_LOST:
case BRCMF_E_PFN_SCAN_COMPLETE:
- BRCMF_EVENT(("PNOEVENT: %s\n", event_name));
+ brcmf_dbg(EVENT, "PNOEVENT: %s\n", event_name);
break;
case BRCMF_E_PSK_SUP:
case BRCMF_E_PRUNE:
- BRCMF_EVENT(("MACEVENT: %s, status %d, reason %d\n",
- event_name, (int)status, (int)reason));
+ brcmf_dbg(EVENT, "MACEVENT: %s, status %d, reason %d\n",
+ event_name, (int)status, (int)reason);
break;
case BRCMF_E_TRACE:
- {
- static u32 seqnum_prev;
- struct msgtrace_hdr hdr;
- u32 nblost;
- char *s, *p;
-
- buf = (unsigned char *) event_data;
- memcpy(&hdr, buf, sizeof(struct msgtrace_hdr));
-
- if (hdr.version != MSGTRACE_VERSION) {
- BRCMF_ERROR(
- ("\nMACEVENT: %s [unsupported version --> "
- "brcmf version:%d dongle version:%d]\n",
- event_name, MSGTRACE_VERSION, hdr.version)
- );
- /* Reset datalen to avoid display below */
- datalen = 0;
- break;
- }
-
- /* There are 2 bytes available at the end of data */
- *(buf + sizeof(struct msgtrace_hdr)
- + be16_to_cpu(hdr.len)) = '\0';
-
- if (be32_to_cpu(hdr.discarded_bytes)
- || be32_to_cpu(hdr.discarded_printf)) {
- BRCMF_ERROR(
- ("\nWLC_E_TRACE: [Discarded traces in dongle -->"
- "discarded_bytes %d discarded_printf %d]\n",
- be32_to_cpu(hdr.discarded_bytes),
- be32_to_cpu(hdr.discarded_printf)));
- }
-
- nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1;
- if (nblost > 0) {
- BRCMF_ERROR(
- ("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n",
- be32_to_cpu(hdr.seqnum), nblost));
- }
- seqnum_prev = be32_to_cpu(hdr.seqnum);
-
- /* Display the trace buffer. Advance from \n to \n to
- * avoid display big
- * printf (issue with Linux printk )
- */
- p = (char *)&buf[sizeof(struct msgtrace_hdr)];
- while ((s = strstr(p, "\n")) != NULL) {
- *s = '\0';
- printk(KERN_DEBUG"%s\n", p);
- p = s + 1;
- }
- printk(KERN_DEBUG "%s\n", p);
+ buf = (unsigned char *) event_data;
+ memcpy(&hdr, buf, sizeof(struct msgtrace_hdr));
+ if (hdr.version != MSGTRACE_VERSION) {
+ brcmf_dbg(ERROR,
+ "MACEVENT: %s [unsupported version --> brcmf"
+ " version:%d dongle version:%d]\n",
+ event_name, MSGTRACE_VERSION, hdr.version);
/* Reset datalen to avoid display below */
datalen = 0;
+ break;
+ }
+
+ /* There are 2 bytes available at the end of data */
+ *(buf + sizeof(struct msgtrace_hdr)
+ + be16_to_cpu(hdr.len)) = '\0';
+
+ if (be32_to_cpu(hdr.discarded_bytes)
+ || be32_to_cpu(hdr.discarded_printf))
+ brcmf_dbg(ERROR,
+ "WLC_E_TRACE: [Discarded traces in dongle -->"
+ " discarded_bytes %d discarded_printf %d]\n",
+ be32_to_cpu(hdr.discarded_bytes),
+ be32_to_cpu(hdr.discarded_printf));
+
+ nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1;
+ if (nblost > 0)
+ brcmf_dbg(ERROR, "WLC_E_TRACE: [Event lost --> seqnum "
+ " %d nblost %d\n", be32_to_cpu(hdr.seqnum),
+ nblost);
+ seqnum_prev = be32_to_cpu(hdr.seqnum);
+
+ /* Display the trace buffer. Advance from \n to \n to
+ * avoid display big
+ * printf (issue with Linux printk )
+ */
+ p = (char *)&buf[sizeof(struct msgtrace_hdr)];
+ while ((s = strstr(p, "\n")) != NULL) {
+ *s = '\0';
+ printk(KERN_DEBUG"%s\n", p);
+ p = s + 1;
}
+ printk(KERN_DEBUG "%s\n", p);
+
+ /* Reset datalen to avoid display below */
+ datalen = 0;
break;
case BRCMF_E_RSSI:
- BRCMF_EVENT(("MACEVENT: %s %d\n", event_name,
- be32_to_cpu(*((int *)event_data))));
+ brcmf_dbg(EVENT, "MACEVENT: %s %d\n",
+ event_name, be32_to_cpu(*((__be32 *)event_data)));
break;
default:
- BRCMF_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, "
- "auth %d\n", event_name, event_type, eabuf,
- (int)status, (int)reason, (int)auth_type));
+ brcmf_dbg(EVENT,
+ "MACEVENT: %s %d, MAC %s, status %d, reason %d, "
+ "auth %d\n", event_name, event_type, eabuf,
+ (int)status, (int)reason, (int)auth_type);
break;
}
/* show any appended data */
if (datalen) {
buf = (unsigned char *) event_data;
- BRCMF_EVENT((" data (%d) : ", datalen));
+ brcmf_dbg(EVENT, " data (%d) : ", datalen);
for (i = 0; i < datalen; i++)
- BRCMF_EVENT((" 0x%02x ", *buf++));
- BRCMF_EVENT(("\n"));
+ brcmf_dbg(EVENT, " 0x%02x ", *buf++);
+ brcmf_dbg(EVENT, "\n");
}
}
-#endif /* SHOW_EVENTS */
+#endif /* BCMDBG */
int
brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
@@ -744,20 +451,21 @@ brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
{
/* check whether packet is a BRCM event pkt */
struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata;
+ struct brcmf_if_event *ifevent;
char *event_data;
u32 type, status;
u16 flags;
int evlen;
if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) {
- BRCMF_ERROR(("%s: mismatched OUI, bailing\n", __func__));
+ brcmf_dbg(ERROR, "mismatched OUI, bailing\n");
return -EBADE;
}
/* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) !=
BCMILCP_BCM_SUBTYPE_EVENT) {
- BRCMF_ERROR(("%s: mismatched subtype, bailing\n", __func__));
+ brcmf_dbg(ERROR, "mismatched subtype, bailing\n");
return -EBADE;
}
@@ -775,27 +483,22 @@ brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
switch (type) {
case BRCMF_E_IF:
- {
- struct brcmf_if_event *ifevent =
- (struct brcmf_if_event *) event_data;
- BRCMF_TRACE(("%s: if event\n", __func__));
-
- if (ifevent->ifidx > 0 &&
- ifevent->ifidx < BRCMF_MAX_IFS) {
- if (ifevent->action == BRCMF_E_IF_ADD)
- brcmf_add_if(drvr_priv, ifevent->ifidx,
- NULL, event->ifname,
- pvt_data->eth.h_dest,
- ifevent->flags,
- ifevent->bssidx);
- else
- brcmf_del_if(drvr_priv, ifevent->ifidx);
- } else {
- BRCMF_ERROR(("%s: Invalid ifidx %d for %s\n",
- __func__, ifevent->ifidx,
- event->ifname));
- }
+ ifevent = (struct brcmf_if_event *) event_data;
+ brcmf_dbg(TRACE, "if event\n");
+
+ if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) {
+ if (ifevent->action == BRCMF_E_IF_ADD)
+ brcmf_add_if(drvr_priv, ifevent->ifidx, NULL,
+ event->ifname,
+ pvt_data->eth.h_dest,
+ ifevent->flags, ifevent->bssidx);
+ else
+ brcmf_del_if(drvr_priv, ifevent->ifidx);
+ } else {
+ brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n",
+ ifevent->ifidx, event->ifname);
}
+
/* send up the if event: btamp user needs it */
*ifidx = brcmf_ifname2idx(drvr_priv, event->ifname);
break;
@@ -810,27 +513,28 @@ brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
/* Fall through: this should get _everything_ */
*ifidx = brcmf_ifname2idx(drvr_priv, event->ifname);
- BRCMF_TRACE(("%s: MAC event %d, flags %x, status %x\n",
- __func__, type, flags, status));
+ brcmf_dbg(TRACE, "MAC event %d, flags %x, status %x\n",
+ type, flags, status);
/* put it back to BRCMF_E_NDIS_LINK */
if (type == BRCMF_E_NDIS_LINK) {
- u32 temp;
+ u32 temp1;
+ __be32 temp2;
- temp = get_unaligned_be32(&event->event_type);
- BRCMF_TRACE(("Converted to WLC_E_LINK type %d\n",
- temp));
+ temp1 = get_unaligned_be32(&event->event_type);
+ brcmf_dbg(TRACE, "Converted to WLC_E_LINK type %d\n",
+ temp1);
- temp = be32_to_cpu(BRCMF_E_NDIS_LINK);
- memcpy((void *)(&pvt_data->msg.event_type), &temp,
+ temp2 = cpu_to_be32(BRCMF_E_NDIS_LINK);
+ memcpy((void *)(&pvt_data->msg.event_type), &temp2,
sizeof(pvt_data->msg.event_type));
}
break;
}
-#ifdef SHOW_EVENTS
+#ifdef BCMDBG
brcmf_c_show_host_event(event, event_data);
-#endif /* SHOW_EVENTS */
+#endif /* BCMDBG */
return 0;
}
@@ -840,19 +544,22 @@ static int brcmf_c_pattern_atoh(char *src, char *dst)
{
int i;
if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
- BRCMF_ERROR(("Mask invalid format. Needs to start with 0x\n"));
- return -1;
+ brcmf_dbg(ERROR, "Mask invalid format. Needs to start with 0x\n");
+ return -EINVAL;
}
src = src + 2; /* Skip past 0x */
if (strlen(src) % 2 != 0) {
- BRCMF_ERROR(("Mask invalid format. Length must be even.\n"));
- return -1;
+ brcmf_dbg(ERROR, "Mask invalid format. Length must be even.\n");
+ return -EINVAL;
}
for (i = 0; *src != '\0'; i++) {
+ unsigned long res;
char num[3];
strncpy(num, src, 2);
num[2] = '\0';
- dst[i] = (u8) simple_strtoul(num, NULL, 16);
+ if (kstrtoul(num, 16, &res))
+ return -EINVAL;
+ dst[i] = (u8)res;
src += 2;
}
return i;
@@ -862,22 +569,23 @@ void
brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
int master_mode)
{
+ unsigned long res;
char *argv[8];
int i = 0;
const char *str;
int buf_len;
int str_len;
- char *arg_save = 0, *arg_org = 0;
+ char *arg_save = NULL, *arg_org = NULL;
int rc;
char buf[128];
- struct brcmf_pkt_filter_enable enable_parm;
- struct brcmf_pkt_filter_enable *pkt_filterp;
+ struct brcmf_pkt_filter_enable_le enable_parm;
+ struct brcmf_pkt_filter_enable_le *pkt_filterp;
+ __le32 mmode_le;
arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
- if (!arg_save) {
- BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
+ if (!arg_save)
goto fail;
- }
+
arg_org = arg_save;
memcpy(arg_save, arg, strlen(arg) + 1);
@@ -885,7 +593,7 @@ brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
i = 0;
if (NULL == argv[i]) {
- BRCMF_ERROR(("No args provided\n"));
+ brcmf_dbg(ERROR, "No args provided\n");
goto fail;
}
@@ -895,36 +603,38 @@ brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
buf[str_len] = '\0';
buf_len = str_len + 1;
- pkt_filterp = (struct brcmf_pkt_filter_enable *) (buf + str_len + 1);
+ pkt_filterp = (struct brcmf_pkt_filter_enable_le *) (buf + str_len + 1);
/* Parse packet filter id. */
- enable_parm.id = simple_strtoul(argv[i], NULL, 0);
+ enable_parm.id = 0;
+ if (!kstrtoul(argv[i], 0, &res))
+ enable_parm.id = cpu_to_le32((u32)res);
/* Parse enable/disable value. */
- enable_parm.enable = enable;
+ enable_parm.enable = cpu_to_le32(enable);
buf_len += sizeof(enable_parm);
memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
/* Enable/disable the specified filter. */
- rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
+ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
rc = rc >= 0 ? 0 : rc;
if (rc)
- BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
- __func__, arg, rc));
+ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
+ arg, rc);
else
- BRCMF_TRACE(("%s: successfully added pktfilter %s\n",
- __func__, arg));
+ brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg);
/* Contorl the master mode */
- brcmu_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf,
+ mmode_le = cpu_to_le32(master_mode);
+ brcmf_c_mkiovar("pkt_filter_mode", (char *)&mmode_le, 4, buf,
sizeof(buf));
- rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf,
+ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf,
sizeof(buf));
rc = rc >= 0 ? 0 : rc;
if (rc)
- BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
- __func__, arg, rc));
+ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
+ arg, rc);
fail:
kfree(arg_org);
@@ -933,32 +643,27 @@ fail:
void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
{
const char *str;
- struct brcmf_pkt_filter pkt_filter;
- struct brcmf_pkt_filter *pkt_filterp;
+ struct brcmf_pkt_filter_le pkt_filter;
+ struct brcmf_pkt_filter_le *pkt_filterp;
+ unsigned long res;
int buf_len;
int str_len;
int rc;
u32 mask_size;
u32 pattern_size;
- char *argv[8], *buf = 0;
+ char *argv[8], *buf = NULL;
int i = 0;
- char *arg_save = 0, *arg_org = 0;
+ char *arg_save = NULL, *arg_org = NULL;
- arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
- if (!arg_save) {
- BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
+ arg_save = kstrdup(arg, GFP_ATOMIC);
+ if (!arg_save)
goto fail;
- }
arg_org = arg_save;
buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC);
- if (!buf) {
- BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
+ if (!buf)
goto fail;
- }
-
- strcpy(arg_save, arg);
argv[i] = strsep(&arg_save, " ");
while (argv[i++])
@@ -966,7 +671,7 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
i = 0;
if (NULL == argv[i]) {
- BRCMF_ERROR(("No args provided\n"));
+ brcmf_dbg(ERROR, "No args provided\n");
goto fail;
}
@@ -975,37 +680,45 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
str_len = strlen(str);
buf_len = str_len + 1;
- pkt_filterp = (struct brcmf_pkt_filter *) (buf + str_len + 1);
+ pkt_filterp = (struct brcmf_pkt_filter_le *) (buf + str_len + 1);
/* Parse packet filter id. */
- pkt_filter.id = simple_strtoul(argv[i], NULL, 0);
+ pkt_filter.id = 0;
+ if (!kstrtoul(argv[i], 0, &res))
+ pkt_filter.id = cpu_to_le32((u32)res);
if (NULL == argv[++i]) {
- BRCMF_ERROR(("Polarity not provided\n"));
+ brcmf_dbg(ERROR, "Polarity not provided\n");
goto fail;
}
/* Parse filter polarity. */
- pkt_filter.negate_match = simple_strtoul(argv[i], NULL, 0);
+ pkt_filter.negate_match = 0;
+ if (!kstrtoul(argv[i], 0, &res))
+ pkt_filter.negate_match = cpu_to_le32((u32)res);
if (NULL == argv[++i]) {
- BRCMF_ERROR(("Filter type not provided\n"));
+ brcmf_dbg(ERROR, "Filter type not provided\n");
goto fail;
}
/* Parse filter type. */
- pkt_filter.type = simple_strtoul(argv[i], NULL, 0);
+ pkt_filter.type = 0;
+ if (!kstrtoul(argv[i], 0, &res))
+ pkt_filter.type = cpu_to_le32((u32)res);
if (NULL == argv[++i]) {
- BRCMF_ERROR(("Offset not provided\n"));
+ brcmf_dbg(ERROR, "Offset not provided\n");
goto fail;
}
/* Parse pattern filter offset. */
- pkt_filter.u.pattern.offset = simple_strtoul(argv[i], NULL, 0);
+ pkt_filter.u.pattern.offset = 0;
+ if (!kstrtoul(argv[i], 0, &res))
+ pkt_filter.u.pattern.offset = cpu_to_le32((u32)res);
if (NULL == argv[++i]) {
- BRCMF_ERROR(("Bitmask not provided\n"));
+ brcmf_dbg(ERROR, "Bitmask not provided\n");
goto fail;
}
@@ -1015,7 +728,7 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
(argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern);
if (NULL == argv[++i]) {
- BRCMF_ERROR(("Pattern not provided\n"));
+ brcmf_dbg(ERROR, "Pattern not provided\n");
goto fail;
}
@@ -1026,11 +739,11 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
mask_and_pattern[mask_size]);
if (mask_size != pattern_size) {
- BRCMF_ERROR(("Mask and pattern not the same size\n"));
+ brcmf_dbg(ERROR, "Mask and pattern not the same size\n");
goto fail;
}
- pkt_filter.u.pattern.size_bytes = mask_size;
+ pkt_filter.u.pattern.size_bytes = cpu_to_le32(mask_size);
buf_len += BRCMF_PKT_FILTER_FIXED_LEN;
buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
@@ -1043,15 +756,14 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
&pkt_filter,
BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN);
- rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
+ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
rc = rc >= 0 ? 0 : rc;
if (rc)
- BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
- __func__, arg, rc));
+ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
+ arg, rc);
else
- BRCMF_TRACE(("%s: successfully added pktfilter %s\n",
- __func__, arg));
+ brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg);
fail:
kfree(arg_org);
@@ -1059,49 +771,50 @@ fail:
kfree(buf);
}
-void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
+static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
{
char iovbuf[32];
int retcode;
- brcmu_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
- retcode = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR,
+ brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
+ retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
iovbuf, sizeof(iovbuf));
retcode = retcode >= 0 ? 0 : retcode;
if (retcode)
- BRCMF_TRACE(("%s: failed to set ARP offload mode to 0x%x, "
- "retcode = %d\n", __func__, arp_mode, retcode));
+ brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, retcode = %d\n",
+ arp_mode, retcode);
else
- BRCMF_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
- __func__, arp_mode));
+ brcmf_dbg(TRACE, "successfully set ARP offload mode to 0x%x\n",
+ arp_mode);
}
-void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
+static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
{
char iovbuf[32];
int retcode;
- brcmu_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
- retcode = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR,
+ brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4,
+ iovbuf, sizeof(iovbuf));
+ retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
iovbuf, sizeof(iovbuf));
retcode = retcode >= 0 ? 0 : retcode;
if (retcode)
- BRCMF_TRACE(("%s: failed to enabe ARP offload to %d, "
- "retcode = %d\n", __func__, arp_enable, retcode));
+ brcmf_dbg(TRACE, "failed to enable ARP offload to %d, retcode = %d\n",
+ arp_enable, retcode);
else
- BRCMF_TRACE(("%s: successfully enabed ARP offload to %d\n",
- __func__, arp_enable));
+ brcmf_dbg(TRACE, "successfully enabled ARP offload to %d\n",
+ arp_enable);
}
-int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr)
+int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
{
char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for
"event_msgs" + '\0' + bitvec */
uint up = 0;
char buf[128], *ptr;
- uint power_mode = PM_FAST;
u32 dongle_align = BRCMF_SDALIGN;
u32 glom = 0;
+ u32 roaming = 1;
uint bcn_timeout = 3;
int scan_assoc_time = 40;
int scan_unassoc_time = 40;
@@ -1111,83 +824,69 @@ int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr)
/* Set Country code */
if (drvr->country_code[0] != 0) {
- if (brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_COUNTRY,
- drvr->country_code,
- sizeof(drvr->country_code)) < 0) {
- BRCMF_ERROR(("%s: country code setting failed\n",
- __func__));
- }
+ if (brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_COUNTRY,
+ drvr->country_code,
+ sizeof(drvr->country_code)) < 0)
+ brcmf_dbg(ERROR, "country code setting failed\n");
}
/* query for 'ver' to get version info from firmware */
memset(buf, 0, sizeof(buf));
ptr = buf;
- brcmu_mkiovar("ver", 0, 0, buf, sizeof(buf));
- brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf));
+ brcmf_c_mkiovar("ver", NULL, 0, buf, sizeof(buf));
+ brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf));
strsep(&ptr, "\n");
/* Print fw version info */
- BRCMF_ERROR(("Firmware version = %s\n", buf));
-
- /* Set PowerSave mode */
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_PM, (char *)&power_mode,
- sizeof(power_mode));
+ brcmf_dbg(ERROR, "Firmware version = %s\n", buf);
/* Match Host and Dongle rx alignment */
- brcmu_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
+ brcmf_c_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
sizeof(iovbuf));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
sizeof(iovbuf));
/* disable glom option per default */
- brcmu_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+ brcmf_c_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
sizeof(iovbuf));
/* Setup timeout if Beacons are lost and roam is off to report
link down */
- brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
+ brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
sizeof(iovbuf));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
sizeof(iovbuf));
/* Enable/Disable build-in roaming to allowed ext supplicant to take
of romaing */
- brcmu_mkiovar("roam_off", (char *)&brcmf_roam, 4,
+ brcmf_c_mkiovar("roam_off", (char *)&roaming, 4,
iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
sizeof(iovbuf));
/* Force STA UP */
- if (brcmf_radio_up)
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_UP, (char *)&up,
- sizeof(up));
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up));
/* Setup event_msgs */
- brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
+ brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
sizeof(iovbuf));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME,
(char *)&scan_assoc_time, sizeof(scan_assoc_time));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
(char *)&scan_unassoc_time, sizeof(scan_unassoc_time));
/* Set and enable ARP offload feature */
- if (brcmf_arp_enable)
- brcmf_c_arp_offload_set(drvr, brcmf_arp_mode);
- brcmf_c_arp_offload_enable(drvr, brcmf_arp_enable);
+ brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE);
+ brcmf_c_arp_offload_enable(drvr, true);
/* Set up pkt filter */
- if (brcmf_pkt_filter_enable) {
- for (i = 0; i < drvr->pktfilter_count; i++) {
- brcmf_c_pktfilter_offload_set(drvr,
- drvr->pktfilter[i]);
- brcmf_c_pktfilter_offload_enable(drvr,
- drvr->pktfilter[i],
- brcmf_pkt_filter_init,
- brcmf_master_mode);
- }
+ for (i = 0; i < drvr->pktfilter_count; i++) {
+ brcmf_c_pktfilter_offload_set(drvr, drvr->pktfilter[i]);
+ brcmf_c_pktfilter_offload_enable(drvr, drvr->pktfilter[i],
+ 0, true);
}
brcmf_os_proto_unblock(drvr);
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h b/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
index 5be4d7a609c2..7467922f0536 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
@@ -19,25 +19,21 @@
#if defined(BCMDBG)
-#define BRCMF_ERROR(args) \
- do {if ((brcmf_msg_level & BRCMF_ERROR_VAL) && (net_ratelimit())) \
- printk args; } while (0)
-#define BRCMF_TRACE(args) do {if (brcmf_msg_level & BRCMF_TRACE_VAL) \
- printk args; } while (0)
-#define BRCMF_INFO(args) do {if (brcmf_msg_level & BRCMF_INFO_VAL) \
- printk args; } while (0)
-#define BRCMF_DATA(args) do {if (brcmf_msg_level & BRCMF_DATA_VAL) \
- printk args; } while (0)
-#define BRCMF_CTL(args) do {if (brcmf_msg_level & BRCMF_CTL_VAL) \
- printk args; } while (0)
-#define BRCMF_TIMER(args) do {if (brcmf_msg_level & BRCMF_TIMER_VAL) \
- printk args; } while (0)
-#define BRCMF_INTR(args) do {if (brcmf_msg_level & BRCMF_INTR_VAL) \
- printk args; } while (0)
-#define BRCMF_GLOM(args) do {if (brcmf_msg_level & BRCMF_GLOM_VAL) \
- printk args; } while (0)
-#define BRCMF_EVENT(args) do {if (brcmf_msg_level & BRCMF_EVENT_VAL) \
- printk args; } while (0)
+#define brcmf_dbg(level, fmt, ...) \
+do { \
+ if (BRCMF_ERROR_VAL == BRCMF_##level##_VAL) { \
+ if (brcmf_msg_level & BRCMF_##level##_VAL) { \
+ if (net_ratelimit()) \
+ printk(KERN_DEBUG "%s: " fmt, \
+ __func__, ##__VA_ARGS__); \
+ } \
+ } else { \
+ if (brcmf_msg_level & BRCMF_##level##_VAL) { \
+ printk(KERN_DEBUG "%s: " fmt, \
+ __func__, ##__VA_ARGS__); \
+ } \
+ } \
+} while (0)
#define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL)
#define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL)
@@ -47,20 +43,12 @@
#else /* (defined BCMDBG) || (defined BCMDBG) */
-#define BRCMF_ERROR(args) do {if (net_ratelimit()) printk args; } while (0)
-#define BRCMF_TRACE(args)
-#define BRCMF_INFO(args)
-#define BRCMF_DATA(args)
-#define BRCMF_CTL(args)
-#define BRCMF_TIMER(args)
-#define BRCMF_INTR(args)
-#define BRCMF_GLOM(args)
-#define BRCMF_EVENT(args)
+#define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__)
#define BRCMF_DATA_ON() 0
#define BRCMF_CTL_ON() 0
#define BRCMF_HDRS_ON() 0
-#define BRCMF_BYTES_ON() 0
+#define BRCMF_BYTES_ON() 0
#define BRCMF_GLOM_ON() 0
#endif /* defined(BCMDBG) */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
index 05dada98eb6b..4acbac5a74c6 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
@@ -28,9 +28,12 @@
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
-#include <linux/interrupt.h>
#include <linux/hardirq.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/module.h>
#include <net/cfg80211.h>
+#include <net/rtnetlink.h>
#include <defs.h>
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
@@ -42,11 +45,6 @@
#include "wl_cfg80211.h"
#include "bcmchip.h"
-#if defined(CONFIG_PM_SLEEP)
-#include <linux/suspend.h>
-atomic_t brcmf_mmc_suspend;
-#endif /* defined(CONFIG_PM_SLEEP) */
-
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver.");
MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards");
@@ -57,15 +55,11 @@ MODULE_LICENSE("Dual BSD/GPL");
struct brcmf_if {
struct brcmf_info *info; /* back pointer to brcmf_info */
/* OS/stack specifics */
- struct net_device *net;
+ struct net_device *ndev;
struct net_device_stats stats;
int idx; /* iface idx in dongle */
int state; /* interface state */
- uint subunit; /* subunit */
u8 mac_addr[ETH_ALEN]; /* assigned MAC address */
- bool attached; /* Delayed attachment when unset */
- bool txflowcontrol; /* Per interface flow control indicator */
- char name[IFNAMSIZ]; /* linux interface name */
};
/* Local private structure (extension of pub) */
@@ -75,14 +69,10 @@ struct brcmf_info {
/* OS/stack specifics */
struct brcmf_if *iflist[BRCMF_MAX_IFS];
- struct semaphore proto_sem;
- wait_queue_head_t ioctl_resp_wait;
+ struct mutex proto_block;
- /* Thread to issue ioctl for multicast */
- struct task_struct *sysioc_tsk;
- struct semaphore sysioc_sem;
- bool set_multicast;
- bool set_macaddress;
+ struct work_struct setmacaddr_work;
+ struct work_struct multicast_work;
u8 macvalue[ETH_ALEN];
atomic_t pend_8021x_cnt;
};
@@ -90,148 +80,13 @@ struct brcmf_info {
/* Error bits */
module_param(brcmf_msg_level, int, 0);
-/* Spawn a thread for system ioctls (set mac, set mcast) */
-uint brcmf_sysioc = true;
-module_param(brcmf_sysioc, uint, 0);
-
-/* ARP offload agent mode : Enable ARP Host Auto-Reply
-and ARP Peer Auto-Reply */
-uint brcmf_arp_mode = 0xb;
-module_param(brcmf_arp_mode, uint, 0);
-
-/* ARP offload enable */
-uint brcmf_arp_enable = true;
-module_param(brcmf_arp_enable, uint, 0);
-
-/* Global Pkt filter enable control */
-uint brcmf_pkt_filter_enable = true;
-module_param(brcmf_pkt_filter_enable, uint, 0);
-
-/* Pkt filter init setup */
-uint brcmf_pkt_filter_init;
-module_param(brcmf_pkt_filter_init, uint, 0);
-
-/* Pkt filter mode control */
-uint brcmf_master_mode = true;
-module_param(brcmf_master_mode, uint, 0);
-
-module_param(brcmf_dongle_memsize, int, 0);
-
-/* Contorl fw roaming */
-uint brcmf_roam = 1;
-
-/* Control radio state */
-uint brcmf_radio_up = 1;
-
-/* Network inteface name */
-char iface_name[IFNAMSIZ] = "wlan";
-module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
-
-/* The following are specific to the SDIO dongle */
-
-/* IOCTL response timeout */
-int brcmf_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT;
-
-/* Idle timeout for backplane clock */
-int brcmf_idletime = BRCMF_IDLETIME_TICKS;
-module_param(brcmf_idletime, int, 0);
-
-/* Use polling */
-uint brcmf_poll;
-module_param(brcmf_poll, uint, 0);
-/* Use interrupts */
-uint brcmf_intr = true;
-module_param(brcmf_intr, uint, 0);
-
-/* SDIO Drive Strength (in milliamps) */
-uint brcmf_sdiod_drive_strength = 6;
-module_param(brcmf_sdiod_drive_strength, uint, 0);
-
-/* Tx/Rx bounds */
-module_param(brcmf_txbound, uint, 0);
-module_param(brcmf_rxbound, uint, 0);
-
-#ifdef SDTEST
-/* Echo packet generator (pkts/s) */
-uint brcmf_pktgen;
-module_param(brcmf_pktgen, uint, 0);
-
-/* Echo packet len (0 => sawtooth, max 2040) */
-uint brcmf_pktgen_len;
-module_param(brcmf_pktgen_len, uint, 0);
-#endif
-
-static int brcmf_toe_get(struct brcmf_info *drvr_priv, int idx, u32 *toe_ol);
-static int brcmf_toe_set(struct brcmf_info *drvr_priv, int idx, u32 toe_ol);
-static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
- struct brcmf_event_msg *event_ptr,
- void **data_ptr);
-
-/*
- * Generalized timeout mechanism. Uses spin sleep with exponential
- * back-off until
- * the sleep time reaches one jiffy, then switches over to task delay. Usage:
- *
- * brcmf_timeout_start(&tmo, usec);
- * while (!brcmf_timeout_expired(&tmo))
- * if (poll_something())
- * break;
- * if (brcmf_timeout_expired(&tmo))
- * fatal();
- */
-
-void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec)
-{
- tmo->limit = usec;
- tmo->increment = 0;
- tmo->elapsed = 0;
- tmo->tick = 1000000 / HZ;
-}
-
-int brcmf_timeout_expired(struct brcmf_timeout *tmo)
-{
- /* Does nothing the first call */
- if (tmo->increment == 0) {
- tmo->increment = 1;
- return 0;
- }
-
- if (tmo->elapsed >= tmo->limit)
- return 1;
-
- /* Add the delay that's about to take place */
- tmo->elapsed += tmo->increment;
-
- if (tmo->increment < tmo->tick) {
- udelay(tmo->increment);
- tmo->increment *= 2;
- if (tmo->increment > tmo->tick)
- tmo->increment = tmo->tick;
- } else {
- wait_queue_head_t delay_wait;
- DECLARE_WAITQUEUE(wait, current);
- int pending;
- init_waitqueue_head(&delay_wait);
- add_wait_queue(&delay_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- pending = signal_pending(current);
- remove_wait_queue(&delay_wait, &wait);
- set_current_state(TASK_RUNNING);
- if (pending)
- return 1; /* Interrupted */
- }
-
- return 0;
-}
-
-static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *net)
+static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *ndev)
{
int i = 0;
while (i < BRCMF_MAX_IFS) {
- if (drvr_priv->iflist[i] && (drvr_priv->iflist[i]->net == net))
+ if (drvr_priv->iflist[i] && drvr_priv->iflist[i]->ndev == ndev)
return i;
i++;
}
@@ -242,16 +97,18 @@ static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *net)
int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
{
int i = BRCMF_MAX_IFS;
+ struct brcmf_if *ifp;
if (name == NULL || *name == '\0')
return 0;
- while (--i > 0)
- if (drvr_priv->iflist[i]
- && !strncmp(drvr_priv->iflist[i]->name, name, IFNAMSIZ))
+ while (--i > 0) {
+ ifp = drvr_priv->iflist[i];
+ if (ifp && !strncmp(ifp->ndev->name, name, IFNAMSIZ))
break;
+ }
- BRCMF_TRACE(("%s: return idx %d for \"%s\"\n", __func__, i, name));
+ brcmf_dbg(TRACE, "return idx %d for \"%s\"\n", i, name);
return i; /* default - the primary interface */
}
@@ -261,56 +118,58 @@ char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
struct brcmf_info *drvr_priv = drvr->info;
if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
- BRCMF_ERROR(("%s: ifidx %d out of range\n", __func__, ifidx));
+ brcmf_dbg(ERROR, "ifidx %d out of range\n", ifidx);
return "<if_bad>";
}
if (drvr_priv->iflist[ifidx] == NULL) {
- BRCMF_ERROR(("%s: null i/f %d\n", __func__, ifidx));
+ brcmf_dbg(ERROR, "null i/f %d\n", ifidx);
return "<if_null>";
}
- if (drvr_priv->iflist[ifidx]->net)
- return drvr_priv->iflist[ifidx]->net->name;
+ if (drvr_priv->iflist[ifidx]->ndev)
+ return drvr_priv->iflist[ifidx]->ndev->name;
return "<if_none>";
}
-static void _brcmf_set_multicast_list(struct brcmf_info *drvr_priv, int ifidx)
+static void _brcmf_set_multicast_list(struct work_struct *work)
{
- struct net_device *dev;
+ struct net_device *ndev;
struct netdev_hw_addr *ha;
- u32 allmulti, cnt;
+ u32 dcmd_value, cnt;
+ __le32 cnt_le;
+ __le32 dcmd_le_value;
- struct brcmf_ioctl ioc;
+ struct brcmf_dcmd dcmd;
char *buf, *bufp;
uint buflen;
int ret;
- dev = drvr_priv->iflist[ifidx]->net;
- cnt = netdev_mc_count(dev);
+ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info,
+ multicast_work);
+
+ ndev = drvr_priv->iflist[0]->ndev;
+ cnt = netdev_mc_count(ndev);
/* Determine initial value of allmulti flag */
- allmulti = (dev->flags & IFF_ALLMULTI) ? true : false;
+ dcmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false;
/* Send down the multicast list first. */
buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN);
bufp = buf = kmalloc(buflen, GFP_ATOMIC);
- if (!bufp) {
- BRCMF_ERROR(("%s: out of memory for mcast_list, cnt %d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), cnt));
+ if (!bufp)
return;
- }
strcpy(bufp, "mcast_list");
bufp += strlen("mcast_list") + 1;
- cnt = cpu_to_le32(cnt);
- memcpy(bufp, &cnt, sizeof(cnt));
- bufp += sizeof(cnt);
+ cnt_le = cpu_to_le32(cnt);
+ memcpy(bufp, &cnt_le, sizeof(cnt));
+ bufp += sizeof(cnt_le);
- netdev_for_each_mc_addr(ha, dev) {
+ netdev_for_each_mc_addr(ha, ndev) {
if (!cnt)
break;
memcpy(bufp, ha->addr, ETH_ALEN);
@@ -318,17 +177,17 @@ static void _brcmf_set_multicast_list(struct brcmf_info *drvr_priv, int ifidx)
cnt--;
}
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = BRCMF_C_SET_VAR;
- ioc.buf = buf;
- ioc.len = buflen;
- ioc.set = true;
+ memset(&dcmd, 0, sizeof(dcmd));
+ dcmd.cmd = BRCMF_C_SET_VAR;
+ dcmd.buf = buf;
+ dcmd.len = buflen;
+ dcmd.set = true;
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len);
if (ret < 0) {
- BRCMF_ERROR(("%s: set mcast_list failed, cnt %d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), cnt));
- allmulti = cnt ? true : allmulti;
+ brcmf_dbg(ERROR, "%s: set mcast_list failed, cnt %d\n",
+ brcmf_ifname(&drvr_priv->pub, 0), cnt);
+ dcmd_value = cnt ? true : dcmd_value;
}
kfree(buf);
@@ -338,36 +197,34 @@ static void _brcmf_set_multicast_list(struct brcmf_info *drvr_priv, int ifidx)
* were trying to set some addresses and dongle rejected it...
*/
- buflen = sizeof("allmulti") + sizeof(allmulti);
+ buflen = sizeof("allmulti") + sizeof(dcmd_value);
buf = kmalloc(buflen, GFP_ATOMIC);
- if (!buf) {
- BRCMF_ERROR(("%s: out of memory for allmulti\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
+ if (!buf)
return;
- }
- allmulti = cpu_to_le32(allmulti);
-
- if (!brcmu_mkiovar
- ("allmulti", (void *)&allmulti, sizeof(allmulti), buf, buflen)) {
- BRCMF_ERROR(("%s: mkiovar failed for allmulti, datalen %d "
- "buflen %u\n",
- brcmf_ifname(&drvr_priv->pub, ifidx),
- (int)sizeof(allmulti), buflen));
+
+ dcmd_le_value = cpu_to_le32(dcmd_value);
+
+ if (!brcmf_c_mkiovar
+ ("allmulti", (void *)&dcmd_le_value,
+ sizeof(dcmd_le_value), buf, buflen)) {
+ brcmf_dbg(ERROR, "%s: mkiovar failed for allmulti, datalen %d buflen %u\n",
+ brcmf_ifname(&drvr_priv->pub, 0),
+ (int)sizeof(dcmd_value), buflen);
kfree(buf);
return;
}
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = BRCMF_C_SET_VAR;
- ioc.buf = buf;
- ioc.len = buflen;
- ioc.set = true;
+ memset(&dcmd, 0, sizeof(dcmd));
+ dcmd.cmd = BRCMF_C_SET_VAR;
+ dcmd.buf = buf;
+ dcmd.len = buflen;
+ dcmd.set = true;
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len);
if (ret < 0) {
- BRCMF_ERROR(("%s: set allmulti %d failed\n",
- brcmf_ifname(&drvr_priv->pub, ifidx),
- le32_to_cpu(allmulti)));
+ brcmf_dbg(ERROR, "%s: set allmulti %d failed\n",
+ brcmf_ifname(&drvr_priv->pub, 0),
+ le32_to_cpu(dcmd_le_value));
}
kfree(buf);
@@ -375,237 +232,84 @@ static void _brcmf_set_multicast_list(struct brcmf_info *drvr_priv, int ifidx)
/* Finally, pick up the PROMISC flag as well, like the NIC
driver does */
- allmulti = (dev->flags & IFF_PROMISC) ? true : false;
- allmulti = cpu_to_le32(allmulti);
+ dcmd_value = (ndev->flags & IFF_PROMISC) ? true : false;
+ dcmd_le_value = cpu_to_le32(dcmd_value);
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = BRCMF_C_SET_PROMISC;
- ioc.buf = &allmulti;
- ioc.len = sizeof(allmulti);
- ioc.set = true;
+ memset(&dcmd, 0, sizeof(dcmd));
+ dcmd.cmd = BRCMF_C_SET_PROMISC;
+ dcmd.buf = &dcmd_le_value;
+ dcmd.len = sizeof(dcmd_le_value);
+ dcmd.set = true;
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len);
if (ret < 0) {
- BRCMF_ERROR(("%s: set promisc %d failed\n",
- brcmf_ifname(&drvr_priv->pub, ifidx),
- le32_to_cpu(allmulti)));
+ brcmf_dbg(ERROR, "%s: set promisc %d failed\n",
+ brcmf_ifname(&drvr_priv->pub, 0),
+ le32_to_cpu(dcmd_le_value));
}
}
-static int _brcmf_set_mac_address(struct brcmf_info *drvr_priv, int ifidx, u8 *addr)
+static void
+_brcmf_set_mac_address(struct work_struct *work)
{
char buf[32];
- struct brcmf_ioctl ioc;
+ struct brcmf_dcmd dcmd;
int ret;
- BRCMF_TRACE(("%s enter\n", __func__));
- if (!brcmu_mkiovar
- ("cur_etheraddr", (char *)addr, ETH_ALEN, buf, 32)) {
- BRCMF_ERROR(("%s: mkiovar failed for cur_etheraddr\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
- return -1;
- }
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = BRCMF_C_SET_VAR;
- ioc.buf = buf;
- ioc.len = 32;
- ioc.set = true;
-
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
- if (ret < 0) {
- BRCMF_ERROR(("%s: set cur_etheraddr failed\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
- } else {
- memcpy(drvr_priv->iflist[ifidx]->net->dev_addr, addr, ETH_ALEN);
- }
-
- return ret;
-}
-
-#ifdef SOFTAP
-extern struct net_device *ap_net_dev;
-#endif
-
-/* Virtual interfaces only ((ifp && ifp->info && ifp->idx == true) */
-static void brcmf_op_if(struct brcmf_if *ifp)
-{
- struct brcmf_info *drvr_priv;
- int ret = 0, err = 0;
-
- drvr_priv = ifp->info;
-
- BRCMF_TRACE(("%s: idx %d, state %d\n", __func__, ifp->idx, ifp->state));
-
- switch (ifp->state) {
- case BRCMF_E_IF_ADD:
- /*
- * Delete the existing interface before overwriting it
- * in case we missed the BRCMF_E_IF_DEL event.
- */
- if (ifp->net != NULL) {
- BRCMF_ERROR(("%s: ERROR: netdev:%s already exists, "
- "try free & unregister\n",
- __func__, ifp->net->name));
- netif_stop_queue(ifp->net);
- unregister_netdev(ifp->net);
- free_netdev(ifp->net);
- }
- /* Allocate etherdev, including space for private structure */
- ifp->net = alloc_etherdev(sizeof(drvr_priv));
- if (!ifp->net) {
- BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
- ret = -ENOMEM;
- }
- if (ret == 0) {
- strcpy(ifp->net->name, ifp->name);
- memcpy(netdev_priv(ifp->net), &drvr_priv, sizeof(drvr_priv));
- err = brcmf_net_attach(&drvr_priv->pub, ifp->idx);
- if (err != 0) {
- BRCMF_ERROR(("%s: brcmf_net_attach failed, "
- "err %d\n",
- __func__, err));
- ret = -EOPNOTSUPP;
- } else {
-#ifdef SOFTAP
- /* semaphore that the soft AP CODE
- waits on */
- extern struct semaphore ap_eth_sema;
-
- /* save ptr to wl0.1 netdev for use
- in wl_iw.c */
- ap_net_dev = ifp->net;
- /* signal to the SOFTAP 'sleeper' thread,
- wl0.1 is ready */
- up(&ap_eth_sema);
-#endif
- BRCMF_TRACE(("\n ==== pid:%x, net_device for "
- "if:%s created ===\n\n",
- current->pid, ifp->net->name));
- ifp->state = 0;
- }
- }
- break;
- case BRCMF_E_IF_DEL:
- if (ifp->net != NULL) {
- BRCMF_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n",
- __func__));
- netif_stop_queue(ifp->net);
- unregister_netdev(ifp->net);
- ret = BRCMF_DEL_IF; /* Make sure the free_netdev()
- is called */
- }
- break;
- default:
- BRCMF_ERROR(("%s: bad op %d\n", __func__, ifp->state));
- break;
- }
+ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info,
+ setmacaddr_work);
- if (ret < 0) {
- if (ifp->net)
- free_netdev(ifp->net);
-
- drvr_priv->iflist[ifp->idx] = NULL;
- kfree(ifp);
-#ifdef SOFTAP
- if (ifp->net == ap_net_dev)
- ap_net_dev = NULL; /* NULL SOFTAP global
- wl0.1 as well */
-#endif /* SOFTAP */
+ brcmf_dbg(TRACE, "enter\n");
+ if (!brcmf_c_mkiovar("cur_etheraddr", (char *)drvr_priv->macvalue,
+ ETH_ALEN, buf, 32)) {
+ brcmf_dbg(ERROR, "%s: mkiovar failed for cur_etheraddr\n",
+ brcmf_ifname(&drvr_priv->pub, 0));
+ return;
}
-}
-
-static int _brcmf_sysioc_thread(void *data)
-{
- struct brcmf_info *drvr_priv = (struct brcmf_info *) data;
- int i;
-#ifdef SOFTAP
- bool in_ap = false;
-#endif
+ memset(&dcmd, 0, sizeof(dcmd));
+ dcmd.cmd = BRCMF_C_SET_VAR;
+ dcmd.buf = buf;
+ dcmd.len = 32;
+ dcmd.set = true;
- allow_signal(SIGTERM);
+ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len);
+ if (ret < 0)
+ brcmf_dbg(ERROR, "%s: set cur_etheraddr failed\n",
+ brcmf_ifname(&drvr_priv->pub, 0));
+ else
+ memcpy(drvr_priv->iflist[0]->ndev->dev_addr,
+ drvr_priv->macvalue, ETH_ALEN);
- while (down_interruptible(&drvr_priv->sysioc_sem) == 0) {
- if (kthread_should_stop())
- break;
- for (i = 0; i < BRCMF_MAX_IFS; i++) {
- struct brcmf_if *ifentry = drvr_priv->iflist[i];
- if (ifentry) {
-#ifdef SOFTAP
- in_ap = (ap_net_dev != NULL);
-#endif /* SOFTAP */
- if (ifentry->state)
- brcmf_op_if(ifentry);
-#ifdef SOFTAP
- if (drvr_priv->iflist[i] == NULL) {
- BRCMF_TRACE(("\n\n %s: interface %d "
- "removed!\n", __func__,
- i));
- continue;
- }
-
- if (in_ap && drvr_priv->set_macaddress) {
- BRCMF_TRACE(("attempt to set MAC for"
- " %s in AP Mode,"
- " blocked.\n",
- ifentry->net->name));
- drvr_priv->set_macaddress = false;
- continue;
- }
-
- if (in_ap && drvr_priv->set_multicast) {
- BRCMF_TRACE(("attempt to set MULTICAST "
- "list for %s in AP Mode, "
- "blocked.\n",
- ifentry->net->name));
- drvr_priv->set_multicast = false;
- continue;
- }
-#endif /* SOFTAP */
- if (drvr_priv->set_multicast) {
- drvr_priv->set_multicast = false;
- _brcmf_set_multicast_list(drvr_priv, i);
- }
- if (drvr_priv->set_macaddress) {
- drvr_priv->set_macaddress = false;
- _brcmf_set_mac_address(drvr_priv, i,
- drvr_priv->macvalue);
- }
- }
- }
- }
- return 0;
+ return;
}
-static int brcmf_netdev_set_mac_address(struct net_device *dev, void *addr)
+static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
{
- int ret = 0;
-
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
struct sockaddr *sa = (struct sockaddr *)addr;
int ifidx;
- ifidx = brcmf_net2idx(drvr_priv, dev);
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
if (ifidx == BRCMF_BAD_IF)
return -1;
memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
- drvr_priv->set_macaddress = true;
- up(&drvr_priv->sysioc_sem);
-
- return ret;
+ schedule_work(&drvr_priv->setmacaddr_work);
+ return 0;
}
-static void brcmf_netdev_set_multicast_list(struct net_device *dev)
+static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
int ifidx;
- ifidx = brcmf_net2idx(drvr_priv, dev);
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
if (ifidx == BRCMF_BAD_IF)
return;
- drvr_priv->set_multicast = true;
- up(&drvr_priv->sysioc_sem);
+ schedule_work(&drvr_priv->multicast_work);
}
int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
@@ -634,27 +338,27 @@ int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf);
}
-static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *net)
+static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
int ret;
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
int ifidx;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
/* Reject if down */
if (!drvr_priv->pub.up || (drvr_priv->pub.busstate == BRCMF_BUS_DOWN)) {
- BRCMF_ERROR(("%s: xmit rejected pub.up=%d busstate=%d\n",
- __func__, drvr_priv->pub.up,
- drvr_priv->pub.busstate));
- netif_stop_queue(net);
+ brcmf_dbg(ERROR, "xmit rejected pub.up=%d busstate=%d\n",
+ drvr_priv->pub.up, drvr_priv->pub.busstate);
+ netif_stop_queue(ndev);
return -ENODEV;
}
- ifidx = brcmf_net2idx(drvr_priv, net);
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
if (ifidx == BRCMF_BAD_IF) {
- BRCMF_ERROR(("%s: bad ifidx %d\n", __func__, ifidx));
- netif_stop_queue(net);
+ brcmf_dbg(ERROR, "bad ifidx %d\n", ifidx);
+ netif_stop_queue(ndev);
return -ENODEV;
}
@@ -662,15 +366,15 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *net)
if (skb_headroom(skb) < drvr_priv->pub.hdrlen) {
struct sk_buff *skb2;
- BRCMF_INFO(("%s: insufficient headroom\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
+ brcmf_dbg(INFO, "%s: insufficient headroom\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx));
drvr_priv->pub.tx_realloc++;
skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
dev_kfree_skb(skb);
skb = skb2;
if (skb == NULL) {
- BRCMF_ERROR(("%s: skb_realloc_headroom failed\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
+ brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx));
ret = -ENOMEM;
goto done;
}
@@ -690,17 +394,34 @@ done:
void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool state)
{
- struct net_device *net;
+ struct net_device *ndev;
struct brcmf_info *drvr_priv = drvr->info;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
drvr->txoff = state;
- net = drvr_priv->iflist[ifidx]->net;
+ ndev = drvr_priv->iflist[ifidx]->ndev;
if (state == ON)
- netif_stop_queue(net);
+ netif_stop_queue(ndev);
else
- netif_wake_queue(net);
+ netif_wake_queue(ndev);
+}
+
+static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx,
+ void *pktdata, struct brcmf_event_msg *event,
+ void **data)
+{
+ int bcmerror = 0;
+
+ bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data);
+ if (bcmerror != 0)
+ return bcmerror;
+
+ if (drvr_priv->iflist[*ifidx]->ndev)
+ brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->ndev,
+ event, *data);
+
+ return bcmerror;
}
void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
@@ -715,7 +436,7 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
struct brcmf_if *ifp;
struct brcmf_event_msg event;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
save_pktbuf = skb;
@@ -743,7 +464,7 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
if (ifp == NULL)
ifp = drvr_priv->iflist[0];
- skb->dev = ifp->net;
+ skb->dev = ifp->ndev;
skb->protocol = eth_type_trans(skb, skb->dev);
if (skb->pkt_type == PACKET_MULTICAST)
@@ -765,15 +486,15 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
!drvr_priv->iflist[ifidx]->state)
ifp = drvr_priv->iflist[ifidx];
- if (ifp->net)
- ifp->net->last_rx = jiffies;
+ if (ifp->ndev)
+ ifp->ndev->last_rx = jiffies;
drvr->dstats.rx_bytes += skb->len;
drvr->rx_packets++; /* Local count */
- if (in_interrupt()) {
+ if (in_interrupt())
netif_rx(skb);
- } else {
+ else
/* If the receive is not processed inside an ISR,
* the softirqd must be woken explicitly to service
* the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled
@@ -781,7 +502,6 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
* to do it manually.
*/
netif_rx_ni(skb);
- }
}
}
@@ -802,24 +522,24 @@ void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success)
}
-static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *net)
+static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
struct brcmf_if *ifp;
int ifidx;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
- ifidx = brcmf_net2idx(drvr_priv, net);
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
if (ifidx == BRCMF_BAD_IF)
return NULL;
ifp = drvr_priv->iflist[ifidx];
- if (drvr_priv->pub.up) {
+ if (drvr_priv->pub.up)
/* Use the protocol to get dongle stats */
brcmf_proto_dstats(&drvr_priv->pub);
- }
/* Copy dongle stats to net device stats */
ifp->stats.rx_packets = drvr_priv->pub.dstats.rx_packets;
@@ -839,33 +559,35 @@ static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *net)
as a bitmap in toe_ol iovar */
static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol)
{
- struct brcmf_ioctl ioc;
+ struct brcmf_dcmd dcmd;
+ __le32 toe_le;
char buf[32];
int ret;
- memset(&ioc, 0, sizeof(ioc));
+ memset(&dcmd, 0, sizeof(dcmd));
- ioc.cmd = BRCMF_C_GET_VAR;
- ioc.buf = buf;
- ioc.len = (uint) sizeof(buf);
- ioc.set = false;
+ dcmd.cmd = BRCMF_C_GET_VAR;
+ dcmd.buf = buf;
+ dcmd.len = (uint) sizeof(buf);
+ dcmd.set = false;
strcpy(buf, "toe_ol");
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len);
if (ret < 0) {
/* Check for older dongle image that doesn't support toe_ol */
if (ret == -EIO) {
- BRCMF_ERROR(("%s: toe not supported by device\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
+ brcmf_dbg(ERROR, "%s: toe not supported by device\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx));
return -EOPNOTSUPP;
}
- BRCMF_INFO(("%s: could not get toe_ol: ret=%d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), ret));
+ brcmf_dbg(INFO, "%s: could not get toe_ol: ret=%d\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx), ret);
return ret;
}
- memcpy(toe_ol, buf, sizeof(u32));
+ memcpy(&toe_le, buf, sizeof(u32));
+ *toe_ol = le32_to_cpu(toe_le);
return 0;
}
@@ -873,63 +595,63 @@ static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol)
and set toe global enable iovar */
static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
{
- struct brcmf_ioctl ioc;
+ struct brcmf_dcmd dcmd;
char buf[32];
- int toe, ret;
+ int ret;
+ __le32 toe_le = cpu_to_le32(toe_ol);
- memset(&ioc, 0, sizeof(ioc));
+ memset(&dcmd, 0, sizeof(dcmd));
- ioc.cmd = BRCMF_C_SET_VAR;
- ioc.buf = buf;
- ioc.len = (uint) sizeof(buf);
- ioc.set = true;
+ dcmd.cmd = BRCMF_C_SET_VAR;
+ dcmd.buf = buf;
+ dcmd.len = (uint) sizeof(buf);
+ dcmd.set = true;
/* Set toe_ol as requested */
-
strcpy(buf, "toe_ol");
- memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(u32));
+ memcpy(&buf[sizeof("toe_ol")], &toe_le, sizeof(u32));
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len);
if (ret < 0) {
- BRCMF_ERROR(("%s: could not set toe_ol: ret=%d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), ret));
+ brcmf_dbg(ERROR, "%s: could not set toe_ol: ret=%d\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx), ret);
return ret;
}
/* Enable toe globally only if any components are enabled. */
-
- toe = (toe_ol != 0);
+ toe_le = cpu_to_le32(toe_ol != 0);
strcpy(buf, "toe");
- memcpy(&buf[sizeof("toe")], &toe, sizeof(u32));
+ memcpy(&buf[sizeof("toe")], &toe_le, sizeof(u32));
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len);
if (ret < 0) {
- BRCMF_ERROR(("%s: could not set toe: ret=%d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), ret));
+ brcmf_dbg(ERROR, "%s: could not set toe: ret=%d\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx), ret);
return ret;
}
return 0;
}
-static void brcmf_ethtool_get_drvinfo(struct net_device *net,
+static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info)
{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
sprintf(info->driver, KBUILD_MODNAME);
sprintf(info->version, "%lu", drvr_priv->pub.drv_version);
sprintf(info->fw_version, "%s", BCM4329_FW_NAME);
sprintf(info->bus_info, "%s",
- dev_name(&brcmf_cfg80211_get_sdio_func()->dev));
+ dev_name(brcmf_bus_get_device(drvr_priv->pub.bus)));
}
-struct ethtool_ops brcmf_ethtool_ops = {
+static struct ethtool_ops brcmf_ethtool_ops = {
.get_drvinfo = brcmf_ethtool_get_drvinfo
};
-static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr)
+static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
{
struct ethtool_drvinfo info;
char drvname[sizeof(info.driver)];
@@ -938,7 +660,7 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr)
u32 toe_cmpnt, csum_dir;
int ret;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
/* all ethtool calls start with a cmd word */
if (copy_from_user(&cmd, uaddr, sizeof(u32)))
@@ -964,7 +686,7 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr)
/* otherwise, require dongle to be up */
else if (!drvr_priv->pub.up) {
- BRCMF_ERROR(("%s: dongle is not up\n", __func__));
+ brcmf_dbg(ERROR, "dongle is not up\n");
return -ENODEV;
}
@@ -977,8 +699,8 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr)
sprintf(info.version, "%lu", drvr_priv->pub.drv_version);
if (copy_to_user(uaddr, &info, sizeof(info)))
return -EFAULT;
- BRCMF_CTL(("%s: given %*s, returning %s\n", __func__,
- (int)sizeof(drvname), drvname, info.driver));
+ brcmf_dbg(CTL, "given %*s, returning %s\n",
+ (int)sizeof(drvname), drvname, info.driver);
break;
/* Get toe offload components from dongle */
@@ -1024,10 +746,10 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr)
/* If setting TX checksum mode, tell Linux the new mode */
if (cmd == ETHTOOL_STXCSUM) {
if (edata.data)
- drvr_priv->iflist[0]->net->features |=
+ drvr_priv->iflist[0]->ndev->features |=
NETIF_F_IP_CSUM;
else
- drvr_priv->iflist[0]->net->features &=
+ drvr_priv->iflist[0]->ndev->features &=
~NETIF_F_IP_CSUM;
}
@@ -1040,180 +762,131 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr)
return 0;
}
-static int brcmf_netdev_ioctl_entry(struct net_device *net, struct ifreq *ifr,
+static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
int cmd)
{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
- struct brcmf_c_ioctl ioc;
- int bcmerror = 0;
- int buflen = 0;
- void *buf = NULL;
- uint driver = 0;
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
int ifidx;
- bool is_set_key_cmd;
- ifidx = brcmf_net2idx(drvr_priv, net);
- BRCMF_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __func__, ifidx, cmd));
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
+ brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd);
if (ifidx == BRCMF_BAD_IF)
return -1;
if (cmd == SIOCETHTOOL)
- return brcmf_ethtool(drvr_priv, (void *)ifr->ifr_data);
-
- if (cmd != SIOCDEVPRIVATE)
- return -EOPNOTSUPP;
-
- memset(&ioc, 0, sizeof(ioc));
+ return brcmf_ethtool(drvr_priv, ifr->ifr_data);
- /* Copy the ioc control structure part of ioctl request */
- if (copy_from_user(&ioc, ifr->ifr_data, sizeof(struct brcmf_ioctl))) {
- bcmerror = -EINVAL;
- goto done;
- }
+ return -EOPNOTSUPP;
+}
- /* Copy out any buffer passed */
- if (ioc.buf) {
- buflen = min_t(int, ioc.len, BRCMF_IOCTL_MAXLEN);
- /* optimization for direct ioctl calls from kernel */
- /*
- if (segment_eq(get_fs(), KERNEL_DS)) {
- buf = ioc.buf;
- } else {
- */
- {
- buf = kmalloc(buflen, GFP_ATOMIC);
- if (!buf) {
- bcmerror = -ENOMEM;
- goto done;
- }
- if (copy_from_user(buf, ioc.buf, buflen)) {
- bcmerror = -EINVAL;
- goto done;
- }
- }
- }
+/* called only from within this driver. Sends a command to the dongle. */
+s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
+{
+ struct brcmf_dcmd dcmd;
+ s32 err = 0;
+ int buflen = 0;
+ bool is_set_key_cmd;
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
+ int ifidx;
- /* To differentiate read 4 more byes */
- if ((copy_from_user(&driver, (char *)ifr->ifr_data +
- sizeof(struct brcmf_ioctl), sizeof(uint)) != 0)) {
- bcmerror = -EINVAL;
- goto done;
- }
+ memset(&dcmd, 0, sizeof(dcmd));
+ dcmd.cmd = cmd;
+ dcmd.buf = arg;
+ dcmd.len = len;
- if (!capable(CAP_NET_ADMIN)) {
- bcmerror = -EPERM;
- goto done;
- }
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
- /* check for local brcmf ioctl and handle it */
- if (driver == BRCMF_IOCTL_MAGIC) {
- bcmerror = brcmf_c_ioctl((void *)&drvr_priv->pub, &ioc, buf, buflen);
- if (bcmerror)
- drvr_priv->pub.bcmerror = bcmerror;
- goto done;
- }
+ if (dcmd.buf != NULL)
+ buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN);
/* send to dongle (must be up, and wl) */
if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) {
- BRCMF_ERROR(("%s DONGLE_DOWN,__func__\n", __func__));
- bcmerror = -EIO;
+ brcmf_dbg(ERROR, "DONGLE_DOWN\n");
+ err = -EIO;
goto done;
}
if (!drvr_priv->pub.iswl) {
- bcmerror = -EIO;
+ err = -EIO;
goto done;
}
/*
- * Intercept BRCMF_C_SET_KEY IOCTL - serialize M4 send and
- * set key IOCTL to prevent M4 encryption.
+ * Intercept BRCMF_C_SET_KEY CMD - serialize M4 send and
+ * set key CMD to prevent M4 encryption.
*/
- is_set_key_cmd = ((ioc.cmd == BRCMF_C_SET_KEY) ||
- ((ioc.cmd == BRCMF_C_SET_VAR) &&
- !(strncmp("wsec_key", ioc.buf, 9))) ||
- ((ioc.cmd == BRCMF_C_SET_VAR) &&
- !(strncmp("bsscfg:wsec_key", ioc.buf, 15))));
+ is_set_key_cmd = ((dcmd.cmd == BRCMF_C_SET_KEY) ||
+ ((dcmd.cmd == BRCMF_C_SET_VAR) &&
+ !(strncmp("wsec_key", dcmd.buf, 9))) ||
+ ((dcmd.cmd == BRCMF_C_SET_VAR) &&
+ !(strncmp("bsscfg:wsec_key", dcmd.buf, 15))));
if (is_set_key_cmd)
- brcmf_netdev_wait_pend8021x(net);
+ brcmf_netdev_wait_pend8021x(ndev);
- bcmerror =
- brcmf_proto_ioctl(&drvr_priv->pub, ifidx, (struct brcmf_ioctl *)&ioc,
- buf, buflen);
+ err = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, buflen);
done:
- if (!bcmerror && buf && ioc.buf) {
- if (copy_to_user(ioc.buf, buf, buflen))
- bcmerror = -EFAULT;
- }
-
- kfree(buf);
-
- if (bcmerror > 0)
- bcmerror = 0;
+ if (err > 0)
+ err = 0;
- return bcmerror;
+ return err;
}
-static int brcmf_netdev_stop(struct net_device *net)
+static int brcmf_netdev_stop(struct net_device *ndev)
{
-#if !defined(IGNORE_ETH0_DOWN)
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
+ struct brcmf_pub *drvr = *(struct brcmf_pub **) netdev_priv(ndev);
- BRCMF_TRACE(("%s: Enter\n", __func__));
- brcmf_cfg80211_down();
- if (drvr_priv->pub.up == 0)
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_cfg80211_down(drvr->config);
+ if (drvr->up == 0)
return 0;
/* Set state and stop OS transmissions */
- drvr_priv->pub.up = 0;
- netif_stop_queue(net);
-#else
- BRCMF_ERROR(("BYPASS %s:due to BRCM compilation: under investigation\n",
- __func__));
-#endif /* !defined(IGNORE_ETH0_DOWN) */
+ drvr->up = 0;
+ netif_stop_queue(ndev);
return 0;
}
-static int brcmf_netdev_open(struct net_device *net)
+static int brcmf_netdev_open(struct net_device *ndev)
{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
u32 toe_ol;
- int ifidx = brcmf_net2idx(drvr_priv, net);
+ int ifidx = brcmf_net2idx(drvr_priv, ndev);
s32 ret = 0;
- BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx));
+ brcmf_dbg(TRACE, "ifidx %d\n", ifidx);
if (ifidx == 0) { /* do it only for primary eth0 */
/* try to bring up bus */
ret = brcmf_bus_start(&drvr_priv->pub);
if (ret != 0) {
- BRCMF_ERROR(("%s: failed with code %d\n",
- __func__, ret));
+ brcmf_dbg(ERROR, "failed with code %d\n", ret);
return -1;
}
atomic_set(&drvr_priv->pend_8021x_cnt, 0);
- memcpy(net->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
+ memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
/* Get current TOE mode from dongle */
if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0
&& (toe_ol & TOE_TX_CSUM_OL) != 0)
- drvr_priv->iflist[ifidx]->net->features |=
+ drvr_priv->iflist[ifidx]->ndev->features |=
NETIF_F_IP_CSUM;
else
- drvr_priv->iflist[ifidx]->net->features &=
+ drvr_priv->iflist[ifidx]->ndev->features &=
~NETIF_F_IP_CSUM;
}
/* Allow transmit calls */
- netif_start_queue(net);
+ netif_start_queue(ndev);
drvr_priv->pub.up = 1;
- if (unlikely(brcmf_cfg80211_up())) {
- BRCMF_ERROR(("%s: failed to bring up cfg80211\n",
- __func__));
+ if (brcmf_cfg80211_up(drvr_priv->pub.config)) {
+ brcmf_dbg(ERROR, "failed to bring up cfg80211\n");
return -1;
}
@@ -1221,35 +894,74 @@ static int brcmf_netdev_open(struct net_device *net)
}
int
-brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle, char *name,
- u8 *mac_addr, u32 flags, u8 bssidx)
+brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, struct net_device *ndev,
+ char *name, u8 *mac_addr, u32 flags, u8 bssidx)
{
struct brcmf_if *ifp;
+ int ret = 0, err = 0;
- BRCMF_TRACE(("%s: idx %d, handle->%p\n", __func__, ifidx, handle));
+ brcmf_dbg(TRACE, "idx %d, handle->%p\n", ifidx, ndev);
ifp = drvr_priv->iflist[ifidx];
if (!ifp) {
ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC);
- if (!ifp) {
- BRCMF_ERROR(("%s: OOM - struct brcmf_if\n", __func__));
+ if (!ifp)
return -ENOMEM;
- }
}
memset(ifp, 0, sizeof(struct brcmf_if));
ifp->info = drvr_priv;
drvr_priv->iflist[ifidx] = ifp;
- strlcpy(ifp->name, name, IFNAMSIZ);
if (mac_addr != NULL)
memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
- if (handle == NULL) {
+ if (ndev == NULL) {
ifp->state = BRCMF_E_IF_ADD;
ifp->idx = ifidx;
- up(&drvr_priv->sysioc_sem);
+ /*
+ * Delete the existing interface before overwriting it
+ * in case we missed the BRCMF_E_IF_DEL event.
+ */
+ if (ifp->ndev != NULL) {
+ brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
+ ifp->ndev->name);
+ netif_stop_queue(ifp->ndev);
+ unregister_netdev(ifp->ndev);
+ free_netdev(ifp->ndev);
+ }
+
+ /* Allocate netdev, including space for private structure */
+ ifp->ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d",
+ ether_setup);
+ if (!ifp->ndev) {
+ brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
+ ret = -ENOMEM;
+ }
+
+ if (ret == 0) {
+ memcpy(netdev_priv(ifp->ndev), &drvr_priv,
+ sizeof(drvr_priv));
+ err = brcmf_net_attach(&drvr_priv->pub, ifp->idx);
+ if (err != 0) {
+ brcmf_dbg(ERROR, "brcmf_net_attach failed, err %d\n",
+ err);
+ ret = -EOPNOTSUPP;
+ } else {
+ brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
+ current->pid, ifp->ndev->name);
+ ifp->state = 0;
+ }
+ }
+
+ if (ret < 0) {
+ if (ifp->ndev)
+ free_netdev(ifp->ndev);
+
+ drvr_priv->iflist[ifp->idx] = NULL;
+ kfree(ifp);
+ }
} else
- ifp->net = (struct net_device *)handle;
+ ifp->ndev = ndev;
return 0;
}
@@ -1258,65 +970,55 @@ void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
{
struct brcmf_if *ifp;
- BRCMF_TRACE(("%s: idx %d\n", __func__, ifidx));
+ brcmf_dbg(TRACE, "idx %d\n", ifidx);
ifp = drvr_priv->iflist[ifidx];
if (!ifp) {
- BRCMF_ERROR(("%s: Null interface\n", __func__));
+ brcmf_dbg(ERROR, "Null interface\n");
return;
}
ifp->state = BRCMF_E_IF_DEL;
ifp->idx = ifidx;
- up(&drvr_priv->sysioc_sem);
+ if (ifp->ndev != NULL) {
+ netif_stop_queue(ifp->ndev);
+ unregister_netdev(ifp->ndev);
+ free_netdev(ifp->ndev);
+ drvr_priv->iflist[ifidx] = NULL;
+ kfree(ifp);
+ }
}
struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
{
struct brcmf_info *drvr_priv = NULL;
- struct net_device *net;
+ struct net_device *ndev;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
- /* Allocate etherdev, including space for private structure */
- net = alloc_etherdev(sizeof(drvr_priv));
- if (!net) {
- BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
+ /* Allocate netdev, including space for private structure */
+ ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", ether_setup);
+ if (!ndev) {
+ brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
goto fail;
}
/* Allocate primary brcmf_info */
drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC);
- if (!drvr_priv) {
- BRCMF_ERROR(("%s: OOM - alloc brcmf_info\n", __func__));
+ if (!drvr_priv)
goto fail;
- }
/*
* Save the brcmf_info into the priv
*/
- memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv));
-
- /* Set network interface name if it was provided as module parameter */
- if (iface_name[0]) {
- int len;
- char ch;
- strncpy(net->name, iface_name, IFNAMSIZ);
- net->name[IFNAMSIZ - 1] = 0;
- len = strlen(net->name);
- ch = net->name[len - 1];
- if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2))
- strcat(net->name, "%d");
- }
+ memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv));
- if (brcmf_add_if(drvr_priv, 0, (void *)net, net->name, NULL, 0, 0) ==
+ if (brcmf_add_if(drvr_priv, 0, ndev, ndev->name, NULL, 0, 0) ==
BRCMF_BAD_IF)
goto fail;
- net->netdev_ops = NULL;
- sema_init(&drvr_priv->proto_sem, 1);
- /* Initialize other structure content */
- init_waitqueue_head(&drvr_priv->ioctl_resp_wait);
+ ndev->netdev_ops = NULL;
+ mutex_init(&drvr_priv->proto_block);
/* Link to info module */
drvr_priv->pub.info = drvr_priv;
@@ -1327,41 +1029,33 @@ struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
/* Attach and link in the protocol */
if (brcmf_proto_attach(&drvr_priv->pub) != 0) {
- BRCMF_ERROR(("brcmf_prot_attach failed\n"));
+ brcmf_dbg(ERROR, "brcmf_prot_attach failed\n");
goto fail;
}
/* Attach and link in the cfg80211 */
- if (unlikely(brcmf_cfg80211_attach(net, &drvr_priv->pub))) {
- BRCMF_ERROR(("wl_cfg80211_attach failed\n"));
+ drvr_priv->pub.config =
+ brcmf_cfg80211_attach(ndev,
+ brcmf_bus_get_device(bus),
+ &drvr_priv->pub);
+ if (drvr_priv->pub.config == NULL) {
+ brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
goto fail;
}
- if (brcmf_sysioc) {
- sema_init(&drvr_priv->sysioc_sem, 0);
- drvr_priv->sysioc_tsk = kthread_run(_brcmf_sysioc_thread, drvr_priv,
- "_brcmf_sysioc");
- if (IS_ERR(drvr_priv->sysioc_tsk)) {
- printk(KERN_WARNING
- "_brcmf_sysioc thread failed to start\n");
- drvr_priv->sysioc_tsk = NULL;
- }
- } else
- drvr_priv->sysioc_tsk = NULL;
+ INIT_WORK(&drvr_priv->setmacaddr_work, _brcmf_set_mac_address);
+ INIT_WORK(&drvr_priv->multicast_work, _brcmf_set_multicast_list);
/*
* Save the brcmf_info into the priv
*/
- memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv));
+ memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv));
-#if defined(CONFIG_PM_SLEEP)
- atomic_set(&brcmf_mmc_suspend, false);
-#endif /* defined(CONFIG_PM_SLEEP) */
return &drvr_priv->pub;
fail:
- if (net)
- free_netdev(net);
+ if (ndev)
+ free_netdev(ndev);
if (drvr_priv)
brcmf_detach(&drvr_priv->pub);
@@ -1375,25 +1069,24 @@ int brcmf_bus_start(struct brcmf_pub *drvr)
/* Room for "event_msgs" + '\0' + bitvec */
char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
- BRCMF_TRACE(("%s:\n", __func__));
+ brcmf_dbg(TRACE, "\n");
/* Bring up the bus */
- ret = brcmf_sdbrcm_bus_init(&drvr_priv->pub, true);
+ ret = brcmf_sdbrcm_bus_init(&drvr_priv->pub);
if (ret != 0) {
- BRCMF_ERROR(("%s, brcmf_sdbrcm_bus_init failed %d\n", __func__,
- ret));
+ brcmf_dbg(ERROR, "brcmf_sdbrcm_bus_init failed %d\n", ret);
return ret;
}
/* If bus is not ready, can't come up */
if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) {
- BRCMF_ERROR(("%s failed bus is not ready\n", __func__));
+ brcmf_dbg(ERROR, "failed bus is not ready\n");
return -ENODEV;
}
- brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
+ brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR, iovbuf,
+ brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf,
sizeof(iovbuf));
memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
@@ -1437,20 +1130,20 @@ static struct net_device_ops brcmf_netdev_ops_pri = {
.ndo_do_ioctl = brcmf_netdev_ioctl_entry,
.ndo_start_xmit = brcmf_netdev_start_xmit,
.ndo_set_mac_address = brcmf_netdev_set_mac_address,
- .ndo_set_multicast_list = brcmf_netdev_set_multicast_list
+ .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
};
int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
{
struct brcmf_info *drvr_priv = drvr->info;
- struct net_device *net;
+ struct net_device *ndev;
u8 temp_addr[ETH_ALEN] = {
0x00, 0x90, 0x4c, 0x11, 0x22, 0x33};
- BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx));
+ brcmf_dbg(TRACE, "ifidx %d\n", ifidx);
- net = drvr_priv->iflist[ifidx]->net;
- net->netdev_ops = &brcmf_netdev_ops_pri;
+ ndev = drvr_priv->iflist[ifidx]->ndev;
+ ndev->netdev_ops = &brcmf_netdev_ops_pri;
/*
* We have to use the primary MAC for virtual interfaces
@@ -1462,32 +1155,31 @@ int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
}
if (ifidx == 1) {
- BRCMF_TRACE(("%s ACCESS POINT MAC:\n", __func__));
+ brcmf_dbg(TRACE, "ACCESS POINT MAC:\n");
/* ACCESSPOINT INTERFACE CASE */
temp_addr[0] |= 0X02; /* set bit 2 ,
- Locally Administered address */
}
- net->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen;
- net->ethtool_ops = &brcmf_ethtool_ops;
+ ndev->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen;
+ ndev->ethtool_ops = &brcmf_ethtool_ops;
- drvr_priv->pub.rxsz = net->mtu + net->hard_header_len +
- drvr_priv->pub.hdrlen;
+ drvr_priv->pub.rxsz = ndev->mtu + ndev->hard_header_len +
+ drvr_priv->pub.hdrlen;
- memcpy(net->dev_addr, temp_addr, ETH_ALEN);
+ memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
- if (register_netdev(net) != 0) {
- BRCMF_ERROR(("%s: couldn't register the net device\n",
- __func__));
+ if (register_netdev(ndev) != 0) {
+ brcmf_dbg(ERROR, "couldn't register the net device\n");
goto fail;
}
- BRCMF_INFO(("%s: Broadcom Dongle Host Driver\n", net->name));
+ brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
return 0;
fail:
- net->netdev_ops = NULL;
+ ndev->netdev_ops = NULL;
return -EBADE;
}
@@ -1495,7 +1187,7 @@ static void brcmf_bus_detach(struct brcmf_pub *drvr)
{
struct brcmf_info *drvr_priv;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
if (drvr) {
drvr_priv = drvr->info;
@@ -1504,7 +1196,7 @@ static void brcmf_bus_detach(struct brcmf_pub *drvr)
brcmf_proto_stop(&drvr_priv->pub);
/* Stop the bus module */
- brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus, true);
+ brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus);
}
}
}
@@ -1513,7 +1205,7 @@ void brcmf_detach(struct brcmf_pub *drvr)
{
struct brcmf_info *drvr_priv;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
if (drvr) {
drvr_priv = drvr->info;
@@ -1526,25 +1218,24 @@ void brcmf_detach(struct brcmf_pub *drvr)
brcmf_del_if(drvr_priv, i);
ifp = drvr_priv->iflist[0];
- if (ifp->net->netdev_ops == &brcmf_netdev_ops_pri) {
- brcmf_netdev_stop(ifp->net);
- unregister_netdev(ifp->net);
+ if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
+ rtnl_lock();
+ brcmf_netdev_stop(ifp->ndev);
+ rtnl_unlock();
+ unregister_netdev(ifp->ndev);
}
- if (drvr_priv->sysioc_tsk) {
- send_sig(SIGTERM, drvr_priv->sysioc_tsk, 1);
- kthread_stop(drvr_priv->sysioc_tsk);
- drvr_priv->sysioc_tsk = NULL;
- }
+ cancel_work_sync(&drvr_priv->setmacaddr_work);
+ cancel_work_sync(&drvr_priv->multicast_work);
brcmf_bus_detach(drvr);
if (drvr->prot)
brcmf_proto_detach(drvr);
- brcmf_cfg80211_detach();
+ brcmf_cfg80211_detach(drvr->config);
- free_netdev(ifp->net);
+ free_netdev(ifp->ndev);
kfree(ifp);
kfree(drvr_priv);
}
@@ -1553,7 +1244,7 @@ void brcmf_detach(struct brcmf_pub *drvr)
static void __exit brcmf_module_cleanup(void)
{
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
brcmf_bus_unregister();
}
@@ -1562,12 +1253,12 @@ static int __init brcmf_module_init(void)
{
int error;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
error = brcmf_bus_register();
if (error) {
- BRCMF_ERROR(("%s: brcmf_bus_register failed\n", __func__));
+ brcmf_dbg(ERROR, "brcmf_bus_register failed\n");
goto failed;
}
return 0;
@@ -1584,7 +1275,7 @@ int brcmf_os_proto_block(struct brcmf_pub *drvr)
struct brcmf_info *drvr_priv = drvr->info;
if (drvr_priv) {
- down(&drvr_priv->proto_sem);
+ mutex_lock(&drvr_priv->proto_block);
return 1;
}
return 0;
@@ -1595,84 +1286,13 @@ int brcmf_os_proto_unblock(struct brcmf_pub *drvr)
struct brcmf_info *drvr_priv = drvr->info;
if (drvr_priv) {
- up(&drvr_priv->proto_sem);
+ mutex_unlock(&drvr_priv->proto_block);
return 1;
}
return 0;
}
-unsigned int brcmf_os_get_ioctl_resp_timeout(void)
-{
- return (unsigned int)brcmf_ioctl_timeout_msec;
-}
-
-void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec)
-{
- brcmf_ioctl_timeout_msec = (int)timeout_msec;
-}
-
-int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition,
- bool *pending)
-{
- struct brcmf_info *drvr_priv = drvr->info;
- DECLARE_WAITQUEUE(wait, current);
- int timeout = brcmf_ioctl_timeout_msec;
-
- /* Convert timeout in millsecond to jiffies */
- timeout = timeout * HZ / 1000;
-
- /* Wait until control frame is available */
- add_wait_queue(&drvr_priv->ioctl_resp_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
-
- while (!(*condition) && (!signal_pending(current) && timeout))
- timeout = schedule_timeout(timeout);
-
- if (signal_pending(current))
- *pending = true;
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&drvr_priv->ioctl_resp_wait, &wait);
-
- return timeout;
-}
-
-int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr)
-{
- struct brcmf_info *drvr_priv = drvr->info;
-
- if (waitqueue_active(&drvr_priv->ioctl_resp_wait))
- wake_up_interruptible(&drvr_priv->ioctl_resp_wait);
-
- return 0;
-}
-
-static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
- struct brcmf_event_msg *event, void **data)
-{
- int bcmerror = 0;
-
- bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data);
- if (bcmerror != 0)
- return bcmerror;
-
- if (drvr_priv->iflist[*ifidx]->net)
- brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->net,
- event, *data);
-
- return bcmerror;
-}
-
-int brcmf_netdev_reset(struct net_device *dev, u8 flag)
-{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev);
-
- brcmf_bus_devreset(&drvr_priv->pub, flag);
-
- return 1;
-}
-
static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
{
return atomic_read(&drvr_priv->pend_8021x_cnt);
@@ -1680,9 +1300,9 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
#define MAX_WAIT_FOR_8021X_TX 10
-int brcmf_netdev_wait_pend8021x(struct net_device *dev)
+int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev);
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(ndev);
int timeout = 10 * HZ / 1000;
int ntimes = MAX_WAIT_FOR_8021X_TX;
int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
@@ -1700,7 +1320,7 @@ int brcmf_netdev_wait_pend8021x(struct net_device *dev)
}
#ifdef BCMDBG
-int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size)
+int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size)
{
int ret = 0;
struct file *fp;
@@ -1714,13 +1334,13 @@ int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size)
/* open file to write */
fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640);
if (!fp) {
- BRCMF_ERROR(("%s: open file error\n", __func__));
+ brcmf_dbg(ERROR, "open file error\n");
ret = -1;
goto exit;
}
/* Write buf to file */
- fp->f_op->write(fp, buf, size, &pos);
+ fp->f_op->write(fp, (char __user *)buf, size, &pos);
exit:
/* free buf before return */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h b/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
index ff788b37afdc..4ee1ea846f6d 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
@@ -17,14 +17,6 @@
#ifndef _BRCMF_PROTO_H_
#define _BRCMF_PROTO_H_
-#ifndef IOCTL_RESP_TIMEOUT
-#define IOCTL_RESP_TIMEOUT 2000 /* In milli second */
-#endif
-
-#ifndef IOCTL_CHIP_ACTIVE_TIMEOUT
-#define IOCTL_CHIP_ACTIVE_TIMEOUT 10 /* In milli second */
-#endif
-
/*
* Exported from the brcmf protocol module (brcmf_cdc)
*/
@@ -53,23 +45,16 @@ extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
extern int brcmf_proto_hdrpull(struct brcmf_pub *, int *ifidx,
struct sk_buff *rxp);
-/* Use protocol to issue ioctl to dongle */
-extern int brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx,
- struct brcmf_ioctl *ioc, void *buf, int len);
-
-/* Add prot dump output to a buffer */
-extern void brcmf_proto_dump(struct brcmf_pub *drvr,
- struct brcmu_strbuf *strbuf);
+/* Use protocol to issue command to dongle */
+extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx,
+ struct brcmf_dcmd *dcmd, int len);
/* Update local copy of dongle statistics */
extern void brcmf_proto_dstats(struct brcmf_pub *drvr);
-extern int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc,
- void *buf, uint buflen);
-
-extern int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr);
+extern int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr);
-extern int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx,
+extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx,
uint cmd, void *buf, uint len);
#endif /* _BRCMF_PROTO_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
index 7fa95b6213c5..b716e3124330 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
@@ -24,8 +24,10 @@
#include <linux/sched.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
#include <linux/semaphore.h>
#include <linux/firmware.h>
+#include <linux/module.h>
#include <asm/unaligned.h>
#include <defs.h>
#include <brcmu_wifi.h>
@@ -34,85 +36,18 @@
#include <soc.h>
#include "sdio_host.h"
-/* register access macros */
-#ifndef __BIG_ENDIAN
-#ifndef __mips__
-#define R_REG(r, typ) \
- brcmf_sdcard_reg_read(NULL, (r), sizeof(typ))
-#else /* __mips__ */
-#define R_REG(r, typ) \
- ({ \
- __typeof(*(r)) __osl_v; \
- __asm__ __volatile__("sync"); \
- __osl_v = brcmf_sdcard_reg_read(NULL, (r),\
- sizeof(typ)); \
- __asm__ __volatile__("sync"); \
- __osl_v; \
- })
-#endif /* __mips__ */
-
-#else /* __BIG_ENDIAN */
-#define R_REG(r, typ) \
- brcmf_sdcard_reg_read(NULL, (r), sizeof(typ))
-#endif /* __BIG_ENDIAN */
-
-#define OR_REG(r, v, typ) \
- brcmf_sdcard_reg_write(NULL, (r), sizeof(typ), R_REG(r, typ) | (v))
+#define DCMD_RESP_TIMEOUT 2000 /* In milli second */
#ifdef BCMDBG
-/* ARM trap handling */
-
-/* Trap types defined by ARM (see arminc.h) */
-
-#if defined(__ARM_ARCH_4T__)
-#define MAX_TRAP_TYPE (TR_FIQ + 1)
-#elif defined(__ARM_ARCH_7M__)
-#define MAX_TRAP_TYPE (TR_ISR + ARMCM3_NUMINTS)
-#endif /* __ARM_ARCH_7M__ */
-
-/* The trap structure is defined here as offsets for assembly */
-#define TR_TYPE 0x00
-#define TR_EPC 0x04
-#define TR_CPSR 0x08
-#define TR_SPSR 0x0c
-#define TR_REGS 0x10
-#define TR_REG(n) (TR_REGS + (n) * 4)
-#define TR_SP TR_REG(13)
-#define TR_LR TR_REG(14)
-#define TR_PC TR_REG(15)
-
-#define TRAP_T_SIZE 80
-
-struct brcmf_trap {
- u32 type;
- u32 epc;
- u32 cpsr;
- u32 spsr;
- u32 r0;
- u32 r1;
- u32 r2;
- u32 r3;
- u32 r4;
- u32 r5;
- u32 r6;
- u32 r7;
- u32 r8;
- u32 r9;
- u32 r10;
- u32 r11;
- u32 r12;
- u32 r13;
- u32 r14;
- u32 pc;
-};
+#define BRCMF_TRAP_INFO_SIZE 80
#define CBUF_LEN (128)
-struct rte_log {
- u32 buf; /* Can't be pointer on (64-bit) hosts */
- uint buf_size;
- uint idx;
+struct rte_log_le {
+ __le32 buf; /* Can't be pointer on (64-bit) hosts */
+ __le32 buf_size;
+ __le32 idx;
char *_buf_compat; /* Redundant pointer for backward compat. */
};
@@ -126,8 +61,8 @@ struct rte_console {
* (at risk of conflicting with
* the real UART). vcons_out is currently unused.
*/
- volatile uint vcons_in;
- volatile uint vcons_out;
+ uint vcons_in;
+ uint vcons_out;
/* Output (logging) buffer
* Console output is written to a ring buffer log_buf at index log_idx.
@@ -135,7 +70,7 @@ struct rte_console {
* Output will be lost if the output wraps around faster than the host
* polls.
*/
- struct rte_log log;
+ struct rte_log_le log_le;
/* Console input line buffer
* Characters are read one at a time into cbuf
@@ -176,57 +111,67 @@ struct rte_console {
#define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold
biggest possible glom */
-#ifndef BRCMF_FIRSTREAD
-#define BRCMF_FIRSTREAD 32
-#endif
+#define BRCMF_FIRSTREAD (1 << 6)
-#if !ISPOWEROF2(BRCMF_FIRSTREAD)
-#error BRCMF_FIRSTREAD is not a power of 2!
-#endif
/* SBSDIO_DEVICE_CTL */
-#define SBSDIO_DEVCTL_SETBUSY 0x01 /* 1: device will assert busy signal when
- * receiving CMD53
- */
-#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 /* 1: assertion of sdio interrupt is
- * synchronous to the sdio clock
- */
-#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 /* 1: mask all interrupts to host
- * except the chipActive (rev 8)
- */
-#define SBSDIO_DEVCTL_PADS_ISO 0x08 /* 1: isolate internal sdio signals, put
- * external pads in tri-state; requires
- * sdio bus power cycle to clear (rev 9)
- */
-#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 /* Force SD->SB reset mapping (rev 11) */
-#define SBSDIO_DEVCTL_RST_CORECTL 0x00 /* Determined by CoreControl bit */
-#define SBSDIO_DEVCTL_RST_BPRESET 0x10 /* Force backplane reset */
-#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 /* Force no backplane reset */
+
+/* 1: device will assert busy signal when receiving CMD53 */
+#define SBSDIO_DEVCTL_SETBUSY 0x01
+/* 1: assertion of sdio interrupt is synchronous to the sdio clock */
+#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02
+/* 1: mask all interrupts to host except the chipActive (rev 8) */
+#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04
+/* 1: isolate internal sdio signals, put external pads in tri-state; requires
+ * sdio bus power cycle to clear (rev 9) */
+#define SBSDIO_DEVCTL_PADS_ISO 0x08
+/* Force SD->SB reset mapping (rev 11) */
+#define SBSDIO_DEVCTL_SB_RST_CTL 0x30
+/* Determined by CoreControl bit */
+#define SBSDIO_DEVCTL_RST_CORECTL 0x00
+/* Force backplane reset */
+#define SBSDIO_DEVCTL_RST_BPRESET 0x10
+/* Force no backplane reset */
+#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20
/* SBSDIO_FUNC1_CHIPCLKCSR */
-#define SBSDIO_FORCE_ALP 0x01 /* Force ALP request to backplane */
-#define SBSDIO_FORCE_HT 0x02 /* Force HT request to backplane */
-#define SBSDIO_FORCE_ILP 0x04 /* Force ILP request to backplane */
-#define SBSDIO_ALP_AVAIL_REQ 0x08 /* Make ALP ready (power up xtal) */
-#define SBSDIO_HT_AVAIL_REQ 0x10 /* Make HT ready (power up PLL) */
-#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 /* Squelch clock requests from HW */
-#define SBSDIO_ALP_AVAIL 0x40 /* Status: ALP is ready */
-#define SBSDIO_HT_AVAIL 0x80 /* Status: HT is ready */
-
-#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
-#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS)
-#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
-#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
-#define SBSDIO_CLKAV(regval, alponly) (SBSDIO_ALPAV(regval) && \
- (alponly ? 1 : SBSDIO_HTAV(regval)))
+
+/* Force ALP request to backplane */
+#define SBSDIO_FORCE_ALP 0x01
+/* Force HT request to backplane */
+#define SBSDIO_FORCE_HT 0x02
+/* Force ILP request to backplane */
+#define SBSDIO_FORCE_ILP 0x04
+/* Make ALP ready (power up xtal) */
+#define SBSDIO_ALP_AVAIL_REQ 0x08
+/* Make HT ready (power up PLL) */
+#define SBSDIO_HT_AVAIL_REQ 0x10
+/* Squelch clock requests from HW */
+#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20
+/* Status: ALP is ready */
+#define SBSDIO_ALP_AVAIL 0x40
+/* Status: HT is ready */
+#define SBSDIO_HT_AVAIL 0x80
+
+#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
+#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS)
+#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
+#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
+
+#define SBSDIO_CLKAV(regval, alponly) \
+ (SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval)))
+
/* direct(mapped) cis space */
-#define SBSDIO_CIS_BASE_COMMON 0x1000 /* MAPPED common CIS address */
-#define SBSDIO_CIS_SIZE_LIMIT 0x200 /* maximum bytes in one CIS */
-#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF /* cis offset addr is < 17 bits */
-#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 /* manfid tuple length, include tuple,
- * link bytes
- */
+/* MAPPED common CIS address */
+#define SBSDIO_CIS_BASE_COMMON 0x1000
+/* maximum bytes in one CIS */
+#define SBSDIO_CIS_SIZE_LIMIT 0x200
+/* cis offset addr is < 17 bits */
+#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF
+
+/* manfid tuple length, include tuple, link bytes */
+#define SBSDIO_CIS_MANFID_TUPLE_LEN 6
/* intstatus */
#define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */
@@ -282,11 +227,7 @@ struct rte_console {
/* Total length of frame header for dongle protocol */
#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
-#ifdef SDTEST
-#define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN)
-#else
#define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN)
-#endif
/*
* Software allocation of To SB Mailbox resources
@@ -362,29 +303,6 @@ struct rte_console {
#define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80)
-/* For TEST_CHANNEL packets, define another 4-byte header */
-#define SDPCM_TEST_HDRLEN 4 /*
- * Generally: Cmd(1), Ext(1), Len(2);
- * Semantics of Ext byte depend on
- * command. Len is current or requested
- * frame length, not including test
- * header; sent little-endian.
- */
-#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext:pattern id. */
-#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext:pattern id. */
-#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext:pattern id. */
-#define SDPCM_TEST_BURST 0x04 /*
- * Receiver to send a burst.
- * Ext is a frame count
- */
-#define SDPCM_TEST_SEND 0x05 /*
- * Receiver sets send mode.
- * Ext is boolean on/off
- */
-
-/* Handy macro for filling in datagen packets with a pattern */
-#define SDPCM_TEST_FILL(byteno, id) ((u8)(id + byteno))
-
/*
* Shared structure between dongle and the host.
* The structure contains pointers to trap or assert information.
@@ -395,15 +313,8 @@ struct rte_console {
#define SDPCM_SHARED_ASSERT 0x0200
#define SDPCM_SHARED_TRAP 0x0400
-
/* Space for header read, limit for data packets */
-#ifndef MAX_HDR_READ
-#define MAX_HDR_READ 32
-#endif
-#if !ISPOWEROF2(MAX_HDR_READ)
-#error MAX_HDR_READ is not a power of 2!
-#endif
-
+#define MAX_HDR_READ (1 << 6)
#define MAX_RX_DATASZ 2048
/* Maximum milliseconds to wait for F2 to come up */
@@ -414,10 +325,8 @@ struct rte_console {
* for HT availability, it could take a couple hundred ms more, so
* max out at a 1 second (1000000us).
*/
-#if (PMU_MAX_TRANSITION_DLY <= 1000000)
#undef PMU_MAX_TRANSITION_DLY
#define PMU_MAX_TRANSITION_DLY 1000000
-#endif
/* Value for ChipClockCSR during initial setup */
#define BRCMF_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | \
@@ -433,12 +342,18 @@ struct rte_console {
#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */
/* sbtmstatelow */
-#define SBTML_RESET 0x0001 /* reset */
-#define SBTML_REJ_MASK 0x0006 /* reject field */
-#define SBTML_REJ 0x0002 /* reject */
-#define SBTML_TMPREJ 0x0004 /* temporary reject, for error recovery */
-#define SBTML_SICF_SHIFT 16 /* Shift to locate the SI control flags in sbtml */
+/* reset */
+#define SBTML_RESET 0x0001
+/* reject field */
+#define SBTML_REJ_MASK 0x0006
+/* reject */
+#define SBTML_REJ 0x0002
+/* temporary reject, for error recovery */
+#define SBTML_TMPREJ 0x0004
+
+/* Shift to locate the SI control flags in sbtml */
+#define SBTML_SICF_SHIFT 16
/* sbtmstatehigh */
#define SBTMH_SERR 0x0001 /* serror */
@@ -446,7 +361,8 @@ struct rte_console {
#define SBTMH_BUSY 0x0004 /* busy */
#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */
-#define SBTMH_SISF_SHIFT 16 /* Shift to locate the SI status flags in sbtmh */
+/* Shift to locate the SI status flags in sbtmh */
+#define SBTMH_SISF_SHIFT 16
/* sbidlow */
#define SBIDL_INIT 0x80 /* initiator */
@@ -456,7 +372,8 @@ struct rte_console {
#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */
#define SBIDH_RCE_SHIFT 8
#define SBCOREREV(sbidh) \
- ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK))
+ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | \
+ ((sbidh) & SBIDH_RC_MASK))
#define SBIDH_CC_MASK 0x8ff0 /* core code */
#define SBIDH_CC_SHIFT 4
#define SBIDH_VC_MASK 0xffff0000 /* vendor code */
@@ -465,17 +382,18 @@ struct rte_console {
/*
* Conversion of 802.1D priority to precedence level
*/
-#define PRIO2PREC(prio) \
- (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \
- ((prio^2)) : (prio))
-
-BRCMF_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
+static uint prio2prec(u32 prio)
+{
+ return (prio == PRIO_8021D_NONE || prio == PRIO_8021D_BE) ?
+ (prio^2) : prio;
+}
/*
* Core reg address translation.
* Both macro's returns a 32 bits byte address on the backplane bus.
*/
-#define CORE_CC_REG(base, field) (base + offsetof(chipcregs_t, field))
+#define CORE_CC_REG(base, field) \
+ (base + offsetof(struct chipcregs, field))
#define CORE_BUS_REG(base, field) \
(base + offsetof(struct sdpcmd_regs, field))
#define CORE_SB(base, field) \
@@ -575,7 +493,7 @@ struct sdpcmd_regs {
struct brcmf_console {
uint count; /* Poll interval msec counter */
uint log_addr; /* Log struct address (fixed) */
- struct rte_log log; /* Log struct (host copy) */
+ struct rte_log_le log_le; /* Log struct (host copy) */
uint bufsize; /* Size of log buffer */
u8 *buf; /* Log buffer (host copy) */
uint last; /* Last buffer read index */
@@ -593,6 +511,17 @@ struct sdpcm_shared {
u8 tag[32];
};
+struct sdpcm_shared_le {
+ __le32 flags;
+ __le32 trap_addr;
+ __le32 assert_exp_addr;
+ __le32 assert_file_addr;
+ __le32 assert_line;
+ __le32 console_addr; /* Address of struct rte_console */
+ __le32 msgtrace_addr;
+ u8 tag[32];
+};
+
/* misc chip info needed by some of the routines */
struct chip_info {
@@ -614,22 +543,18 @@ struct chip_info {
struct brcmf_bus {
struct brcmf_pub *drvr;
- struct brcmf_sdio_card *card; /* Handle for sdio card calls */
+ struct brcmf_sdio_dev *sdiodev; /* sdio device handler */
struct chip_info *ci; /* Chip info struct */
char *vars; /* Variables (from CIS and/or other) */
uint varsz; /* Size of variables buffer */
u32 ramsize; /* Size of RAM in SOCRAM (bytes) */
- u32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */
- u32 bus; /* gSPI or SDIO bus */
u32 hostintmask; /* Copy of Host Interrupt Mask */
u32 intstatus; /* Intstatus bits (events) pending */
bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
bool fcstate; /* State of dongle flow-control */
- u16 cl_devid; /* cached devid for brcmf_sdio_probe_attach() */
-
uint blocksize; /* Block size of SDIO transfers */
uint roundup; /* Max roundup limit */
@@ -644,6 +569,10 @@ struct brcmf_bus {
u8 rx_seq; /* Receive sequence number (expected) */
bool rxskip; /* Skip receive (awaiting NAK ACK) */
+ uint rxbound; /* Rx frames to read before resched */
+ uint txbound; /* Tx frames to send before resched */
+ uint txminmax;
+
struct sk_buff *glomd; /* Packet containing glomming descriptor */
struct sk_buff *glom; /* Packet chain for glommed superframe */
uint glomerr; /* Glom packet read errors */
@@ -660,7 +589,6 @@ struct brcmf_bus {
bool intr; /* Use interrupts */
bool poll; /* Use polling */
bool ipend; /* Device interrupt is pending */
- bool intdis; /* Interrupts disabled by isr */
uint intrcount; /* Count of device interrupt callbacks */
uint lastintrs; /* Count as of last watchdog timer */
uint spurious; /* Count of spurious interrupts */
@@ -669,6 +597,7 @@ struct brcmf_bus {
uint pollcnt; /* Count of active polls */
#ifdef BCMDBG
+ uint console_interval;
struct brcmf_console console; /* Console output polling support */
uint console_addr; /* Console address from shared struct */
#endif /* BCMDBG */
@@ -689,30 +618,6 @@ struct brcmf_bus {
/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
bool usebufpool;
-#ifdef SDTEST
- /* external loopback */
- bool ext_loop;
- u8 loopid;
-
- /* pktgen configuration */
- uint pktgen_freq; /* Ticks between bursts */
- uint pktgen_count; /* Packets to send each burst */
- uint pktgen_print; /* Bursts between count displays */
- uint pktgen_total; /* Stop after this many */
- uint pktgen_minlen; /* Minimum packet data len */
- uint pktgen_maxlen; /* Maximum packet data len */
- uint pktgen_mode; /* Configured mode: tx, rx, or echo */
- uint pktgen_stop; /* Number of tx failures causing stop */
-
- /* active pktgen fields */
- uint pktgen_tick; /* Tick counter for bursts */
- uint pktgen_ptick; /* Burst counter for printing */
- uint pktgen_sent; /* Number of test packets generated */
- uint pktgen_rcvd; /* Number of test packets received */
- uint pktgen_fail; /* Number of failed send attempts */
- u16 pktgen_len; /* Length of next packet to send */
-#endif /* SDTEST */
-
/* Some additional counters */
uint tx_sderrs; /* Count of tx attempts with sd errors */
uint fcqueued; /* Tx packets that got queued */
@@ -739,19 +644,18 @@ struct brcmf_bus {
spinlock_t txqlock;
wait_queue_head_t ctrl_wait;
+ wait_queue_head_t dcmd_resp_wait;
struct timer_list timer;
struct completion watchdog_wait;
struct task_struct *watchdog_tsk;
bool wd_timer_valid;
+ uint save_ms;
- struct tasklet_struct tasklet;
struct task_struct *dpc_tsk;
struct completion dpc_wait;
- bool threads_only;
struct semaphore sdsem;
- spinlock_t sdlock;
const char *fw_name;
const struct firmware *firmware;
@@ -805,82 +709,39 @@ struct sbconfig {
#define CLK_PENDING 2 /* Not used yet */
#define CLK_AVAIL 3
-#define BRCMF_NOPMU(brcmf) (false)
-
#ifdef BCMDBG
static int qcount[NUMPRIO];
static int tx_packets[NUMPRIO];
#endif /* BCMDBG */
-/* Deferred transmit */
-uint brcmf_deferred_tx = 1;
-module_param(brcmf_deferred_tx, uint, 0);
+#define SDIO_DRIVE_STRENGTH 6 /* in milliamps */
-/* Watchdog thread priority, -1 to use kernel timer */
-int brcmf_watchdog_prio = 97;
-module_param(brcmf_watchdog_prio, int, 0);
-
-/* Watchdog interval */
-uint brcmf_watchdog_ms = 10;
-module_param(brcmf_watchdog_ms, uint, 0);
-
-/* DPC thread priority, -1 to use tasklet */
-int brcmf_dpc_prio = 98;
-module_param(brcmf_dpc_prio, int, 0);
-
-#ifdef BCMDBG
-/* Console poll interval */
-uint brcmf_console_ms;
-module_param(brcmf_console_ms, uint, 0);
-#endif /* BCMDBG */
-
-/* Tx/Rx bounds */
-uint brcmf_txbound;
-uint brcmf_rxbound;
-uint brcmf_txminmax;
-
-/* override the RAM size if possible */
-#define DONGLE_MIN_MEMSIZE (128 * 1024)
-int brcmf_dongle_memsize;
-
-static bool brcmf_alignctl;
-
-static bool sd1idle;
-
-static bool retrydata;
-#define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
-
-static const uint watermark = 8;
-static const uint firstread = BRCMF_FIRSTREAD;
+#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL)
/* Retry count for register access failures */
static const uint retry_limit = 2;
-/* Force even SD lengths (some host controllers mess up on odd bytes) */
-static bool forcealign;
-
-#define ALIGNMENT 4
-
-#define PKTALIGN(_p, _len, _align) \
- do { \
- uint datalign; \
- datalign = (unsigned long)((_p)->data); \
- datalign = roundup(datalign, (_align)) - datalign; \
- if (datalign) \
- skb_pull((_p), datalign); \
- __skb_trim((_p), (_len)); \
- } while (0)
-
/* Limit on rounding up frames */
static const uint max_roundup = 512;
-/* Try doing readahead */
-static bool brcmf_readahead;
+#define ALIGNMENT 4
+
+static void pkt_align(struct sk_buff *p, int len, int align)
+{
+ uint datalign;
+ datalign = (unsigned long)(p->data);
+ datalign = roundup(datalign, (align)) - datalign;
+ if (datalign)
+ skb_pull(p, datalign);
+ __skb_trim(p, len);
+}
/* To check if there's window offered */
-#define DATAOK(bus) \
- (((u8)(bus->tx_max - bus->tx_seq) != 0) && \
- (((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
+static bool data_ok(struct brcmf_bus *bus)
+{
+ return (u8)(bus->tx_max - bus->tx_seq) != 0 &&
+ ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
+}
/*
* Reads a register in the SDIO hardware block. This block occupies a series of
@@ -891,13 +752,14 @@ r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
{
*retryvar = 0;
do {
- *regvar = R_REG(bus->ci->buscorebase + reg_offset, u32);
- } while (brcmf_sdcard_regfail(bus->card) &&
+ *regvar = brcmf_sdcard_reg_read(bus->sdiodev,
+ bus->ci->buscorebase + reg_offset, sizeof(u32));
+ } while (brcmf_sdcard_regfail(bus->sdiodev) &&
(++(*retryvar) <= retry_limit));
if (*retryvar) {
bus->regfails += (*retryvar-1);
if (*retryvar > retry_limit) {
- BRCMF_ERROR(("FAILED READ %Xh\n", reg_offset));
+ brcmf_dbg(ERROR, "FAILED READ %Xh\n", reg_offset);
*regvar = 0;
}
}
@@ -908,133 +770,42 @@ w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar)
{
*retryvar = 0;
do {
- brcmf_sdcard_reg_write(NULL, bus->ci->buscorebase + reg_offset,
+ brcmf_sdcard_reg_write(bus->sdiodev,
+ bus->ci->buscorebase + reg_offset,
sizeof(u32), regval);
- } while (brcmf_sdcard_regfail(bus->card) &&
+ } while (brcmf_sdcard_regfail(bus->sdiodev) &&
(++(*retryvar) <= retry_limit));
if (*retryvar) {
bus->regfails += (*retryvar-1);
if (*retryvar > retry_limit)
- BRCMF_ERROR(("FAILED REGISTER WRITE"
- " %Xh\n", reg_offset));
+ brcmf_dbg(ERROR, "FAILED REGISTER WRITE %Xh\n",
+ reg_offset);
}
}
-#define BRCMF_BUS SDIO_BUS
-
#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
-#ifdef SDTEST
-static void brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, void *pkt, uint seq);
-static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start);
-#endif
-
-#ifdef BCMDBG
-static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr,
- unsigned char *msg, uint msglen);
-static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size);
-static int brcmf_sdbrcm_mem_dump(struct brcmf_bus *bus);
-#endif /* BCMDBG */
-static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter);
-
-static void brcmf_sdbrcm_release(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_disconnect(void *ptr);
-static bool brcmf_sdbrcm_chipmatch(u16 chipid);
-static bool brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card,
- u32 regsva, u16 devid);
-static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card);
-static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card);
-static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus);
-
-static uint brcmf_process_nvram_vars(char *varbuf, uint len);
-
-static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size);
-static int brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn,
- uint flags, u8 *buf, uint nbytes,
- struct sk_buff *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle);
-
-static bool brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card);
-static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus);
-
-static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus);
-static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus);
-
-static void
-brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase);
-
-static int brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs);
-
-static void
-brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase);
-
-static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus,
- u32 drivestrength);
-static void brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar);
-static void brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_watchdog(unsigned long data);
-static int brcmf_sdbrcm_watchdog_thread(void *data);
-static int brcmf_sdbrcm_dpc_thread(void *data);
-static void brcmf_sdbrcm_dpc_tasklet(unsigned long data);
-static void brcmf_sdbrcm_sched_dpc(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_sdlock(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_sdunlock(struct brcmf_bus *bus);
-static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus);
-
/* Packet free applicable unconditionally for sdio and sdspi.
* Conditional if bufpool was present for gspi bus.
*/
static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt)
{
- if ((bus->bus != SPI_BUS) || bus->usebufpool)
+ if (bus->usebufpool)
brcmu_pkt_buf_free_skb(pkt);
}
-static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size)
-{
- s32 min_size = DONGLE_MIN_MEMSIZE;
- /* Restrict the memsize to user specified limit */
- BRCMF_ERROR(("user: Restrict the dongle ram size to %d, min %d\n",
- brcmf_dongle_memsize, min_size));
- if ((brcmf_dongle_memsize > min_size) &&
- (brcmf_dongle_memsize < (s32) bus->orig_ramsize))
- bus->ramsize = brcmf_dongle_memsize;
-}
-
-static int brcmf_sdbrcm_set_siaddr_window(struct brcmf_bus *bus, u32 address)
-{
- int err = 0;
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
- (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
- if (!err)
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_SBADDRMID,
- (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
- if (!err)
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_SBADDRHIGH,
- (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
- &err);
- return err;
-}
-
/* Turn backplane clock on or off */
static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
{
int err;
u8 clkctl, clkreq, devctl;
- struct brcmf_sdio_card *card;
+ unsigned long timeout;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
clkctl = 0;
- card = bus->card;
if (on) {
/* Request HT Avail */
@@ -1045,11 +816,10 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
&& (bus->ci->chiprev == 0))
clkreq |= SBSDIO_FORCE_ALP;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
if (err) {
- BRCMF_ERROR(("%s: HT Avail request error: %d\n",
- __func__, err));
+ brcmf_dbg(ERROR, "HT Avail request error: %d\n", err);
return -EBADE;
}
@@ -1062,74 +832,73 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
}
/* Check current status */
- clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (err) {
- BRCMF_ERROR(("%s: HT Avail read error: %d\n",
- __func__, err));
+ brcmf_dbg(ERROR, "HT Avail read error: %d\n", err);
return -EBADE;
}
/* Go to pending and await interrupt if appropriate */
if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
/* Allow only clock-available interrupt */
- devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
SBSDIO_DEVICE_CTL, &err);
if (err) {
- BRCMF_ERROR(("%s: Devctl error setting CA:"
- " %d\n", __func__, err));
+ brcmf_dbg(ERROR, "Devctl error setting CA: %d\n",
+ err);
return -EBADE;
}
devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_DEVICE_CTL, devctl, &err);
- BRCMF_INFO(("CLKCTL: set PENDING\n"));
+ brcmf_dbg(INFO, "CLKCTL: set PENDING\n");
bus->clkstate = CLK_PENDING;
return 0;
} else if (bus->clkstate == CLK_PENDING) {
/* Cancel CA-only interrupt filter */
devctl =
- brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_DEVICE_CTL, &err);
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_DEVICE_CTL, devctl, &err);
}
/* Otherwise, wait here (polling) for HT Avail */
- if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
- BRCMF_SPINWAIT_SLEEP(sdioh_spinwait_sleep,
- ((clkctl =
- brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- &err)),
- !SBSDIO_CLKAV(clkctl, bus->alp_only)),
- PMU_MAX_TRANSITION_DLY);
+ timeout = jiffies +
+ msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000);
+ while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
+ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ &err);
+ if (time_after(jiffies, timeout))
+ break;
+ else
+ usleep_range(5000, 10000);
}
if (err) {
- BRCMF_ERROR(("%s: HT Avail request error: %d\n",
- __func__, err));
+ brcmf_dbg(ERROR, "HT Avail request error: %d\n", err);
return -EBADE;
}
if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
- BRCMF_ERROR(("%s: HT Avail timeout (%d): "
- "clkctl 0x%02x\n", __func__,
- PMU_MAX_TRANSITION_DLY, clkctl));
+ brcmf_dbg(ERROR, "HT Avail timeout (%d): clkctl 0x%02x\n",
+ PMU_MAX_TRANSITION_DLY, clkctl);
return -EBADE;
}
/* Mark clock available */
bus->clkstate = CLK_AVAIL;
- BRCMF_INFO(("CLKCTL: turned ON\n"));
+ brcmf_dbg(INFO, "CLKCTL: turned ON\n");
#if defined(BCMDBG)
if (bus->alp_only != true) {
- if (SBSDIO_ALPONLY(clkctl)) {
- BRCMF_ERROR(("%s: HT Clock should be on.\n",
- __func__));
- }
+ if (SBSDIO_ALPONLY(clkctl))
+ brcmf_dbg(ERROR, "HT Clock should be on\n");
}
#endif /* defined (BCMDBG) */
@@ -1139,20 +908,21 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
if (bus->clkstate == CLK_PENDING) {
/* Cancel CA-only interrupt filter */
- devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
SBSDIO_DEVICE_CTL, &err);
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_DEVICE_CTL, devctl, &err);
}
bus->clkstate = CLK_SDONLY;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
- BRCMF_INFO(("CLKCTL: turned OFF\n"));
+ brcmf_dbg(INFO, "CLKCTL: turned OFF\n");
if (err) {
- BRCMF_ERROR(("%s: Failed access turning clock off:"
- " %d\n", __func__, err));
+ brcmf_dbg(ERROR, "Failed access turning clock off: %d\n",
+ err);
return -EBADE;
}
}
@@ -1162,7 +932,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
/* Change idle/active SD state */
static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on)
{
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
if (on)
bus->clkstate = CLK_SDONLY;
@@ -1179,12 +949,12 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok)
uint oldstate = bus->clkstate;
#endif /* BCMDBG */
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
/* Early exit if we're already there */
if (bus->clkstate == target) {
if (target == CLK_AVAIL) {
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
bus->activity = true;
}
return 0;
@@ -1197,7 +967,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok)
brcmf_sdbrcm_sdclk(bus, true);
/* Now request HT Avail on the backplane */
brcmf_sdbrcm_htclk(bus, true, pendok);
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
bus->activity = true;
break;
@@ -1208,9 +978,9 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok)
else if (bus->clkstate == CLK_AVAIL)
brcmf_sdbrcm_htclk(bus, false, false);
else
- BRCMF_ERROR(("brcmf_sdbrcm_clkctl: request for %d -> %d"
- "\n", bus->clkstate, target));
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
+ brcmf_dbg(ERROR, "request for %d -> %d\n",
+ bus->clkstate, target);
+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
break;
case CLK_NONE:
@@ -1223,21 +993,19 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok)
break;
}
#ifdef BCMDBG
- BRCMF_INFO(("brcmf_sdbrcm_clkctl: %d -> %d\n",
- oldstate, bus->clkstate));
+ brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate);
#endif /* BCMDBG */
return 0;
}
-int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
+static int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
{
- struct brcmf_sdio_card *card = bus->card;
uint retries = 0;
- BRCMF_INFO(("brcmf_sdbrcm_bussleep: request %s (currently %s)\n",
- (sleep ? "SLEEP" : "WAKE"),
- (bus->sleeping ? "SLEEP" : "WAKE")));
+ brcmf_dbg(INFO, "request %s (currently %s)\n",
+ sleep ? "SLEEP" : "WAKE",
+ bus->sleeping ? "SLEEP" : "WAKE");
/* Done if we're already in the requested state */
if (sleep == bus->sleeping)
@@ -1249,9 +1017,6 @@ int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
return -EBUSY;
- /* Disable SDIO interrupts (no longer interested) */
- brcmf_sdcard_intr_disable(bus->card);
-
/* Make sure the controller has the bus up */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
@@ -1259,20 +1024,18 @@ int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
w_sdreg32(bus, SMB_USE_OOB,
offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
if (retries > retry_limit)
- BRCMF_ERROR(("CANNOT SIGNAL CHIP, "
- "WILL NOT WAKE UP!!\n"));
+ brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n");
/* Turn off our contribution to the HT clock request */
brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR,
SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
/* Isolate the bus */
- if (bus->ci->chip != BCM4329_CHIP_ID
- && bus->ci->chip != BCM4319_CHIP_ID) {
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ if (bus->ci->chip != BCM4329_CHIP_ID) {
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_DEVICE_CTL,
SBSDIO_DEVCTL_PADS_ISO, NULL);
}
@@ -1283,14 +1046,14 @@ int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
} else {
/* Waking up: bus power up is ok, set local state */
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
/* Force pad isolation off if possible
(in case power never toggled) */
if ((bus->ci->buscoretype == PCMCIA_CORE_ID)
&& (bus->ci->buscorerev >= 10))
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_DEVICE_CTL, 0, NULL);
/* Make sure the controller has the bus up */
@@ -1305,2142 +1068,124 @@ int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
&retries);
if (retries > retry_limit)
- BRCMF_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
+ brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n");
/* Make sure we have SD bus access */
brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
/* Change state */
bus->sleeping = false;
-
- /* Enable interrupts again */
- if (bus->intr && (bus->drvr->busstate == BRCMF_BUS_DATA)) {
- bus->intdis = false;
- brcmf_sdcard_intr_enable(bus->card);
- }
}
return 0;
}
-#define BUS_WAKE(bus) \
- do { \
- if ((bus)->sleeping) \
- brcmf_sdbrcm_bussleep((bus), false); \
- } while (0);
-
-/* Writes a HW/SW header into the packet and sends it. */
-/* Assumes: (a) header space already there, (b) caller holds lock */
-static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, uint chan,
- bool free_pkt)
+static void bus_wake(struct brcmf_bus *bus)
{
- int ret;
- u8 *frame;
- u16 len, pad = 0;
- u32 swheader;
- uint retries = 0;
- struct brcmf_sdio_card *card;
- struct sk_buff *new;
- int i;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- card = bus->card;
-
- if (bus->drvr->dongle_reset) {
- ret = -EPERM;
- goto done;
- }
-
- frame = (u8 *) (pkt->data);
-
- /* Add alignment padding, allocate new packet if needed */
- pad = ((unsigned long)frame % BRCMF_SDALIGN);
- if (pad) {
- if (skb_headroom(pkt) < pad) {
- BRCMF_INFO(("%s: insufficient headroom %d for %d pad\n",
- __func__, skb_headroom(pkt), pad));
- bus->drvr->tx_realloc++;
- new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN);
- if (!new) {
- BRCMF_ERROR(("%s: couldn't allocate new "
- "%d-byte packet\n", __func__,
- pkt->len + BRCMF_SDALIGN));
- ret = -ENOMEM;
- goto done;
- }
-
- PKTALIGN(new, pkt->len, BRCMF_SDALIGN);
- memcpy(new->data, pkt->data, pkt->len);
- if (free_pkt)
- brcmu_pkt_buf_free_skb(pkt);
- /* free the pkt if canned one is not used */
- free_pkt = true;
- pkt = new;
- frame = (u8 *) (pkt->data);
- /* precondition: (frame % BRCMF_SDALIGN) == 0) */
- pad = 0;
- } else {
- skb_push(pkt, pad);
- frame = (u8 *) (pkt->data);
- /* precondition: pad + SDPCM_HDRLEN <= pkt->len */
- memset(frame, 0, pad + SDPCM_HDRLEN);
- }
- }
- /* precondition: pad < BRCMF_SDALIGN */
-
- /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
- len = (u16) (pkt->len);
- *(u16 *) frame = cpu_to_le16(len);
- *(((u16 *) frame) + 1) = cpu_to_le16(~len);
-
- /* Software tag: channel, sequence number, data offset */
- swheader =
- ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
- (((pad +
- SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
-
- put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
- put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
-
-#ifdef BCMDBG
- tx_packets[pkt->priority]++;
- if (BRCMF_BYTES_ON() &&
- (((BRCMF_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
- (BRCMF_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
- printk(KERN_DEBUG "Tx Frame:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len);
- } else if (BRCMF_HDRS_ON()) {
- printk(KERN_DEBUG "TxHdr:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- frame, min_t(u16, len, 16));
- }
-#endif
-
- /* Raise len to next SDIO block to eliminate tail command */
- if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
- u16 pad = bus->blocksize - (len % bus->blocksize);
- if ((pad <= bus->roundup) && (pad < bus->blocksize))
- len += pad;
- } else if (len % BRCMF_SDALIGN) {
- len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
- }
-
- /* Some controllers have trouble with odd bytes -- round to even */
- if (forcealign && (len & (ALIGNMENT - 1))) {
- len = roundup(len, ALIGNMENT);
- }
-
- do {
- ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2, F2SYNC, frame, len, pkt, NULL, NULL);
- bus->f2txdata++;
-
- if (ret < 0) {
- /* On failure, abort the command
- and terminate the frame */
- BRCMF_INFO(("%s: sdio error %d, abort command and "
- "terminate frame.\n", __func__, ret));
- bus->tx_sderrs++;
-
- brcmf_sdcard_abort(card, SDIO_FUNC_2);
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
- NULL);
- bus->f1regdata++;
-
- for (i = 0; i < 3; i++) {
- u8 hi, lo;
- hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_WFRAMEBCHI,
- NULL);
- lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_WFRAMEBCLO,
- NULL);
- bus->f1regdata += 2;
- if ((hi == 0) && (lo == 0))
- break;
- }
-
- }
- if (ret == 0)
- bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
-
- } while ((ret < 0) && retrydata && retries++ < TXRETRIES);
-
-done:
- /* restore pkt buffer pointer before calling tx complete routine */
- skb_pull(pkt, SDPCM_HDRLEN + pad);
- brcmf_sdbrcm_sdunlock(bus);
- brcmf_txcomplete(bus->drvr, pkt, ret != 0);
- brcmf_sdbrcm_sdlock(bus);
-
- if (free_pkt)
- brcmu_pkt_buf_free_skb(pkt);
-
- return ret;
-}
-
-int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt)
-{
- int ret = -EBADE;
- uint datalen, prec;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- datalen = pkt->len;
-
-#ifdef SDTEST
- /* Push the test header if doing loopback */
- if (bus->ext_loop) {
- u8 *data;
- skb_push(pkt, SDPCM_TEST_HDRLEN);
- data = pkt->data;
- *data++ = SDPCM_TEST_ECHOREQ;
- *data++ = (u8) bus->loopid++;
- *data++ = (datalen >> 0);
- *data++ = (datalen >> 8);
- datalen += SDPCM_TEST_HDRLEN;
- }
-#endif /* SDTEST */
-
- /* Add space for the header */
- skb_push(pkt, SDPCM_HDRLEN);
- /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */
-
- prec = PRIO2PREC((pkt->priority & PRIOMASK));
-
- /* Check for existing queue, current flow-control,
- pending event, or pending clock */
- if (brcmf_deferred_tx || bus->fcstate || pktq_len(&bus->txq)
- || bus->dpc_sched || (!DATAOK(bus))
- || (bus->flowcontrol & NBITVAL(prec))
- || (bus->clkstate != CLK_AVAIL)) {
- BRCMF_TRACE(("%s: deferring pktq len %d\n", __func__,
- pktq_len(&bus->txq)));
- bus->fcqueued++;
-
- /* Priority based enq */
- spin_lock_bh(&bus->txqlock);
- if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) {
- skb_pull(pkt, SDPCM_HDRLEN);
- brcmf_txcomplete(bus->drvr, pkt, false);
- brcmu_pkt_buf_free_skb(pkt);
- BRCMF_ERROR(("%s: out of bus->txq !!!\n", __func__));
- ret = -ENOSR;
- } else {
- ret = 0;
- }
- spin_unlock_bh(&bus->txqlock);
-
- if (pktq_len(&bus->txq) >= TXHI)
- brcmf_txflowcontrol(bus->drvr, 0, ON);
-
-#ifdef BCMDBG
- if (pktq_plen(&bus->txq, prec) > qcount[prec])
- qcount[prec] = pktq_plen(&bus->txq, prec);
-#endif
- /* Schedule DPC if needed to send queued packet(s) */
- if (brcmf_deferred_tx && !bus->dpc_sched) {
- bus->dpc_sched = true;
- brcmf_sdbrcm_sched_dpc(bus);
- }
- } else {
- /* Lock: we're about to use shared data/code (and SDIO) */
- brcmf_sdbrcm_sdlock(bus);
-
- /* Otherwise, send it now */
- BUS_WAKE(bus);
- /* Make sure back plane ht clk is on, no pending allowed */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
-
-#ifndef SDTEST
- BRCMF_TRACE(("%s: calling txpkt\n", __func__));
- ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
-#else
- ret = brcmf_sdbrcm_txpkt(bus, pkt,
- (bus->ext_loop ? SDPCM_TEST_CHANNEL :
- SDPCM_DATA_CHANNEL), true);
-#endif
- if (ret)
- bus->drvr->tx_errors++;
- else
- bus->drvr->dstats.tx_bytes += datalen;
-
- if (bus->idletime == BRCMF_IDLE_IMMEDIATE &&
- !bus->dpc_sched) {
- bus->activity = false;
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
- }
-
- brcmf_sdbrcm_sdunlock(bus);
- }
-
- return ret;
+ if (bus->sleeping)
+ brcmf_sdbrcm_bussleep(bus, false);
}
-static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes)
+static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus)
{
- struct sk_buff *pkt;
u32 intstatus = 0;
+ u32 hmb_data;
+ u8 fcbits;
uint retries = 0;
- int ret = 0, prec_out;
- uint cnt = 0;
- uint datalen;
- u8 tx_prec_map;
-
- struct brcmf_pub *drvr = bus->drvr;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- tx_prec_map = ~bus->flowcontrol;
-
- /* Send frames until the limit or some other event */
- for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) {
- spin_lock_bh(&bus->txqlock);
- pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
- if (pkt == NULL) {
- spin_unlock_bh(&bus->txqlock);
- break;
- }
- spin_unlock_bh(&bus->txqlock);
- datalen = pkt->len - SDPCM_HDRLEN;
-
-#ifndef SDTEST
- ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
-#else
- ret = brcmf_sdbrcm_txpkt(bus, pkt,
- (bus->ext_loop ? SDPCM_TEST_CHANNEL :
- SDPCM_DATA_CHANNEL), true);
-#endif
- if (ret)
- bus->drvr->tx_errors++;
- else
- bus->drvr->dstats.tx_bytes += datalen;
-
- /* In poll mode, need to check for other events */
- if (!bus->intr && cnt) {
- /* Check device status, signal pending interrupt */
- r_sdreg32(bus, &intstatus,
- offsetof(struct sdpcmd_regs, intstatus),
- &retries);
- bus->f2txdata++;
- if (brcmf_sdcard_regfail(bus->card))
- break;
- if (intstatus & bus->hostintmask)
- bus->ipend = true;
- }
- }
-
- /* Deflow-control stack if needed */
- if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) &&
- drvr->txoff && (pktq_len(&bus->txq) < TXLOW))
- brcmf_txflowcontrol(drvr, 0, OFF);
-
- return cnt;
-}
-
-int
-brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
-{
- u8 *frame;
- u16 len;
- u32 swheader;
- uint retries = 0;
- struct brcmf_sdio_card *card = bus->card;
- u8 doff = 0;
- int ret = -1;
- int i;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (bus->drvr->dongle_reset)
- return -EIO;
-
- /* Back the pointer to make a room for bus header */
- frame = msg - SDPCM_HDRLEN;
- len = (msglen += SDPCM_HDRLEN);
-
- /* Add alignment padding (optional for ctl frames) */
- if (brcmf_alignctl) {
- doff = ((unsigned long)frame % BRCMF_SDALIGN);
- if (doff) {
- frame -= doff;
- len += doff;
- msglen += doff;
- memset(frame, 0, doff + SDPCM_HDRLEN);
- }
- /* precondition: doff < BRCMF_SDALIGN */
- }
- doff += SDPCM_HDRLEN;
-
- /* Round send length to next SDIO block */
- if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
- u16 pad = bus->blocksize - (len % bus->blocksize);
- if ((pad <= bus->roundup) && (pad < bus->blocksize))
- len += pad;
- } else if (len % BRCMF_SDALIGN) {
- len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
- }
-
- /* Satisfy length-alignment requirements */
- if (forcealign && (len & (ALIGNMENT - 1)))
- len = roundup(len, ALIGNMENT);
-
- /* precondition: IS_ALIGNED((unsigned long)frame, 2) */
-
- /* Need to lock here to protect txseq and SDIO tx calls */
- brcmf_sdbrcm_sdlock(bus);
-
- BUS_WAKE(bus);
-
- /* Make sure backplane clock is on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
- *(u16 *) frame = cpu_to_le16((u16) msglen);
- *(((u16 *) frame) + 1) = cpu_to_le16(~msglen);
-
- /* Software tag: channel, sequence number, data offset */
- swheader =
- ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) &
- SDPCM_CHANNEL_MASK)
- | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) &
- SDPCM_DOFFSET_MASK);
- put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
- put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
-
- if (!DATAOK(bus)) {
- BRCMF_INFO(("%s: No bus credit bus->tx_max %d,"
- " bus->tx_seq %d\n", __func__,
- bus->tx_max, bus->tx_seq));
- bus->ctrl_frame_stat = true;
- /* Send from dpc */
- bus->ctrl_frame_buf = frame;
- bus->ctrl_frame_len = len;
-
- brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat);
-
- if (bus->ctrl_frame_stat == false) {
- BRCMF_INFO(("%s: ctrl_frame_stat == false\n",
- __func__));
- ret = 0;
- } else {
- BRCMF_INFO(("%s: ctrl_frame_stat == true\n", __func__));
- ret = -1;
- }
- }
-
- if (ret == -1) {
-#ifdef BCMDBG
- if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
- printk(KERN_DEBUG "Tx Frame:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- frame, len);
- } else if (BRCMF_HDRS_ON()) {
- printk(KERN_DEBUG "TxHdr:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- frame, min_t(u16, len, 16));
- }
-#endif
-
- do {
- bus->ctrl_frame_stat = false;
- ret = brcmf_sdbrcm_send_buf(bus,
- brcmf_sdcard_cur_sbwad(card), SDIO_FUNC_2,
- F2SYNC, frame, len, NULL, NULL, NULL);
-
- if (ret < 0) {
- /* On failure, abort the command and
- terminate the frame */
- BRCMF_INFO(("%s: sdio error %d, abort command "
- "and terminate frame.\n",
- __func__, ret));
- bus->tx_sderrs++;
-
- brcmf_sdcard_abort(card, SDIO_FUNC_2);
-
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_FRAMECTRL,
- SFC_WF_TERM, NULL);
- bus->f1regdata++;
-
- for (i = 0; i < 3; i++) {
- u8 hi, lo;
- hi = brcmf_sdcard_cfg_read(card,
- SDIO_FUNC_1,
- SBSDIO_FUNC1_WFRAMEBCHI,
- NULL);
- lo = brcmf_sdcard_cfg_read(card,
- SDIO_FUNC_1,
- SBSDIO_FUNC1_WFRAMEBCLO,
- NULL);
- bus->f1regdata += 2;
- if ((hi == 0) && (lo == 0))
- break;
- }
-
- }
- if (ret == 0) {
- bus->tx_seq =
- (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
- }
- } while ((ret < 0) && retries++ < TXRETRIES);
- }
-
- if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
- bus->activity = false;
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
- }
-
- brcmf_sdbrcm_sdunlock(bus);
-
- if (ret)
- bus->drvr->tx_ctlerrs++;
- else
- bus->drvr->tx_ctlpkts++;
-
- return ret ? -EIO : 0;
-}
-
-int brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
-{
- int timeleft;
- uint rxlen = 0;
- bool pending;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (bus->drvr->dongle_reset)
- return -EIO;
-
- /* Wait until control frame is available */
- timeleft = brcmf_os_ioctl_resp_wait(bus->drvr, &bus->rxlen, &pending);
-
- brcmf_sdbrcm_sdlock(bus);
- rxlen = bus->rxlen;
- memcpy(msg, bus->rxctl, min(msglen, rxlen));
- bus->rxlen = 0;
- brcmf_sdbrcm_sdunlock(bus);
-
- if (rxlen) {
- BRCMF_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
- __func__, rxlen, msglen));
- } else if (timeleft == 0) {
- BRCMF_ERROR(("%s: resumed on timeout\n", __func__));
-#ifdef BCMDBG
- brcmf_sdbrcm_sdlock(bus);
- brcmf_sdbrcm_checkdied(bus, NULL, 0);
- brcmf_sdbrcm_sdunlock(bus);
-#endif /* BCMDBG */
- } else if (pending == true) {
- BRCMF_CTL(("%s: cancelled\n", __func__));
- return -ERESTARTSYS;
- } else {
- BRCMF_CTL(("%s: resumed for unknown reason?\n", __func__));
-#ifdef BCMDBG
- brcmf_sdbrcm_sdlock(bus);
- brcmf_sdbrcm_checkdied(bus, NULL, 0);
- brcmf_sdbrcm_sdunlock(bus);
-#endif /* BCMDBG */
- }
-
- if (rxlen)
- bus->drvr->rx_ctlpkts++;
- else
- bus->drvr->rx_ctlerrs++;
-
- return rxlen ? (int)rxlen : -ETIMEDOUT;
-}
-
-/* IOVar table */
-enum {
- IOV_INTR = 1,
- IOV_POLLRATE,
- IOV_SDREG,
- IOV_SBREG,
- IOV_SDCIS,
- IOV_MEMBYTES,
- IOV_MEMSIZE,
-#ifdef BCMDBG
- IOV_CHECKDIED,
- IOV_CONS,
- IOV_DCONSOLE_POLL,
-#endif
- IOV_DOWNLOAD,
- IOV_FORCEEVEN,
- IOV_SDIOD_DRIVE,
- IOV_READAHEAD,
- IOV_SDRXCHAIN,
- IOV_ALIGNCTL,
- IOV_SDALIGN,
- IOV_DEVRESET,
- IOV_CPU,
-#ifdef SDTEST
- IOV_PKTGEN,
- IOV_EXTLOOP,
-#endif /* SDTEST */
- IOV_SPROM,
- IOV_TXBOUND,
- IOV_RXBOUND,
- IOV_TXMINMAX,
- IOV_IDLETIME,
- IOV_IDLECLOCK,
- IOV_SD1IDLE,
- IOV_SLEEP,
- IOV_WDTICK,
- IOV_VARS
-};
-
-const struct brcmu_iovar brcmf_sdio_iovars[] = {
- {"intr", IOV_INTR, 0, IOVT_BOOL, 0},
- {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0},
- {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0},
- {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0},
- {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0},
- {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0},
- {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int)},
- {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0},
- {"download", IOV_DOWNLOAD, 0, IOVT_BOOL, 0},
- {"vars", IOV_VARS, 0, IOVT_BUFFER, 0},
- {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0},
- {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0},
- {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0},
- {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0},
- {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0},
- {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0},
- {"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0},
-#ifdef BCMDBG
- {"cons", IOV_CONS, 0, IOVT_BUFFER, 0}
- ,
- {"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0}
- ,
- {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
- ,
- {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
- ,
- {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN}
- ,
- {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0}
- ,
- {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0}
- ,
- {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0}
- ,
- {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0}
- ,
- {"cpu", IOV_CPU, 0, IOVT_BOOL, 0}
- ,
- {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0}
- ,
-#endif /* BCMDBG */
-#ifdef SDTEST
- {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0}
- ,
- {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(struct brcmf_pktgen)}
- ,
-#endif /* SDTEST */
-
- {NULL, 0, 0, 0, 0}
-};
-
-static void
-brcmf_dump_pct(struct brcmu_strbuf *strbuf, char *desc, uint num, uint div)
-{
- uint q1, q2;
-
- if (!div) {
- brcmu_bprintf(strbuf, "%s N/A", desc);
- } else {
- q1 = num / div;
- q2 = (100 * (num - (q1 * div))) / div;
- brcmu_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
- }
-}
-void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf)
-{
- struct brcmf_bus *bus = drvr->bus;
-
- brcmu_bprintf(strbuf, "Bus SDIO structure:\n");
- brcmu_bprintf(strbuf,
- "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
- bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
- brcmu_bprintf(strbuf,
- "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n",
- bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max,
- bus->rxskip, bus->rxlen, bus->rx_seq);
- brcmu_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n",
- bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
- brcmu_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n",
- bus->pollrate, bus->pollcnt, bus->regfails);
-
- brcmu_bprintf(strbuf, "\nAdditional counters:\n");
- brcmu_bprintf(strbuf,
- "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n",
- bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
- bus->rxc_errors);
- brcmu_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n",
- bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
- brcmu_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n",
- bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
- brcmu_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n",
- bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
- brcmu_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs"
- " %d\n",
- (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs,
- bus->f2rxdata, bus->f2txdata, bus->f1regdata);
- {
- brcmf_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->drvr->rx_packets,
- (bus->f2rxhdrs + bus->f2rxdata));
- brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->rx_packets,
- bus->f1regdata);
- brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->rx_packets,
- (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
- brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->rx_packets,
- bus->intrcount);
- brcmu_bprintf(strbuf, "\n");
-
- brcmf_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
- bus->drvr->rx_packets);
- brcmf_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts,
- bus->rxglomframes);
- brcmu_bprintf(strbuf, "\n");
-
- brcmf_dump_pct(strbuf, "Tx: pkts/f2wr", bus->drvr->tx_packets,
- bus->f2txdata);
- brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->tx_packets,
- bus->f1regdata);
- brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->tx_packets,
- (bus->f2txdata + bus->f1regdata));
- brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->tx_packets,
- bus->intrcount);
- brcmu_bprintf(strbuf, "\n");
-
- brcmf_dump_pct(strbuf, "Total: pkts/f2rw",
- (bus->drvr->tx_packets + bus->drvr->rx_packets),
- (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
- brcmf_dump_pct(strbuf, ", pkts/f1sd",
- (bus->drvr->tx_packets + bus->drvr->rx_packets),
- bus->f1regdata);
- brcmf_dump_pct(strbuf, ", pkts/sd",
- (bus->drvr->tx_packets + bus->drvr->rx_packets),
- (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata +
- bus->f1regdata));
- brcmf_dump_pct(strbuf, ", pkts/int",
- (bus->drvr->tx_packets + bus->drvr->rx_packets),
- bus->intrcount);
- brcmu_bprintf(strbuf, "\n\n");
- }
-
-#ifdef SDTEST
- if (bus->pktgen_count) {
- brcmu_bprintf(strbuf, "pktgen config and count:\n");
- brcmu_bprintf(strbuf,
- "freq %d count %d print %d total %d min %d len %d\n",
- bus->pktgen_freq, bus->pktgen_count,
- bus->pktgen_print, bus->pktgen_total,
- bus->pktgen_minlen, bus->pktgen_maxlen);
- brcmu_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n",
- bus->pktgen_sent, bus->pktgen_rcvd,
- bus->pktgen_fail);
- }
-#endif /* SDTEST */
-#ifdef BCMDBG
- brcmu_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
- bus->dpc_sched, " not ");
- brcmu_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize,
- bus->roundup);
-#endif /* BCMDBG */
- brcmu_bprintf(strbuf,
- "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
- bus->clkstate, bus->activity, bus->idletime, bus->idlecount,
- bus->sleeping);
-}
-
-void brcmf_bus_clearcounts(struct brcmf_pub *drvr)
-{
- struct brcmf_bus *bus = (struct brcmf_bus *) drvr->bus;
-
- bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
- bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
- bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
- bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
- bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
- bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
-}
+ brcmf_dbg(TRACE, "Enter\n");
-#ifdef SDTEST
-static int brcmf_sdbrcm_pktgen_get(struct brcmf_bus *bus, u8 *arg)
-{
- struct brcmf_pktgen pktgen;
-
- pktgen.version = BRCMF_PKTGEN_VERSION;
- pktgen.freq = bus->pktgen_freq;
- pktgen.count = bus->pktgen_count;
- pktgen.print = bus->pktgen_print;
- pktgen.total = bus->pktgen_total;
- pktgen.minlen = bus->pktgen_minlen;
- pktgen.maxlen = bus->pktgen_maxlen;
- pktgen.numsent = bus->pktgen_sent;
- pktgen.numrcvd = bus->pktgen_rcvd;
- pktgen.numfail = bus->pktgen_fail;
- pktgen.mode = bus->pktgen_mode;
- pktgen.stop = bus->pktgen_stop;
-
- memcpy(arg, &pktgen, sizeof(pktgen));
-
- return 0;
-}
-
-static int brcmf_sdbrcm_pktgen_set(struct brcmf_bus *bus, u8 *arg)
-{
- struct brcmf_pktgen pktgen;
- uint oldcnt, oldmode;
-
- memcpy(&pktgen, arg, sizeof(pktgen));
- if (pktgen.version != BRCMF_PKTGEN_VERSION)
- return -EINVAL;
-
- oldcnt = bus->pktgen_count;
- oldmode = bus->pktgen_mode;
-
- bus->pktgen_freq = pktgen.freq;
- bus->pktgen_count = pktgen.count;
- bus->pktgen_print = pktgen.print;
- bus->pktgen_total = pktgen.total;
- bus->pktgen_minlen = pktgen.minlen;
- bus->pktgen_maxlen = pktgen.maxlen;
- bus->pktgen_mode = pktgen.mode;
- bus->pktgen_stop = pktgen.stop;
-
- bus->pktgen_tick = bus->pktgen_ptick = 0;
- bus->pktgen_len = max(bus->pktgen_len, bus->pktgen_minlen);
- bus->pktgen_len = min(bus->pktgen_len, bus->pktgen_maxlen);
-
- /* Clear counts for a new pktgen (mode change, or was stopped) */
- if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode))
- bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0;
-
- return 0;
-}
-#endif /* SDTEST */
-
-static int
-brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data,
- uint size)
-{
- int bcmerror = 0;
- u32 sdaddr;
- uint dsize;
-
- /* Determine initial transfer parameters */
- sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
- if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
- dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
- else
- dsize = size;
-
- /* Set the backplane window to include the start address */
- bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address);
- if (bcmerror) {
- BRCMF_ERROR(("%s: window change failed\n", __func__));
- goto xfer_done;
- }
+ /* Read mailbox data and ack that we did so */
+ r_sdreg32(bus, &hmb_data,
+ offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries);
- /* Do the transfer(s) */
- while (size) {
- BRCMF_INFO(("%s: %s %d bytes at offset 0x%08x in window"
- " 0x%08x\n", __func__, (write ? "write" : "read"),
- dsize, sdaddr, (address & SBSDIO_SBWINDOW_MASK)));
- bcmerror =
- brcmf_sdcard_rwdata(bus->card, write, sdaddr, data, dsize);
- if (bcmerror) {
- BRCMF_ERROR(("%s: membytes transfer failed\n",
- __func__));
- break;
- }
+ if (retries <= retry_limit)
+ w_sdreg32(bus, SMB_INT_ACK,
+ offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
+ bus->f1regdata += 2;
- /* Adjust for next transfer (if any) */
- size -= dsize;
- if (size) {
- data += dsize;
- address += dsize;
- bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address);
- if (bcmerror) {
- BRCMF_ERROR(("%s: window change failed\n",
- __func__));
- break;
- }
- sdaddr = 0;
- dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
- }
- }
+ /* Dongle recomposed rx frames, accept them again */
+ if (hmb_data & HMB_DATA_NAKHANDLED) {
+ brcmf_dbg(INFO, "Dongle reports NAK handled, expect rtx of %d\n",
+ bus->rx_seq);
+ if (!bus->rxskip)
+ brcmf_dbg(ERROR, "unexpected NAKHANDLED!\n");
-xfer_done:
- /* Return the window to backplane enumeration space for core access */
- if (brcmf_sdbrcm_set_siaddr_window(bus,
- brcmf_sdcard_cur_sbwad(bus->card))) {
- BRCMF_ERROR(("%s: FAILED to set window back to 0x%x\n",
- __func__, brcmf_sdcard_cur_sbwad(bus->card)));
+ bus->rxskip = false;
+ intstatus |= I_HMB_FRAME_IND;
}
- return bcmerror;
-}
-
-#ifdef BCMDBG
-static int brcmf_sdbrcm_readshared(struct brcmf_bus *bus, struct sdpcm_shared *sh)
-{
- u32 addr;
- int rv;
-
- /* Read last word in memory to determine address of
- sdpcm_shared structure */
- rv = brcmf_sdbrcm_membytes(bus, false, bus->ramsize - 4, (u8 *)&addr,
- 4);
- if (rv < 0)
- return rv;
-
- addr = le32_to_cpu(addr);
-
- BRCMF_INFO(("sdpcm_shared address 0x%08X\n", addr));
-
/*
- * Check if addr is valid.
- * NVRAM length at the end of memory should have been overwritten.
+ * DEVREADY does not occur with gSPI.
*/
- if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
- BRCMF_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
- __func__, addr));
- return -EBADE;
- }
-
- /* Read rte_shared structure */
- rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *) sh,
- sizeof(struct sdpcm_shared));
- if (rv < 0)
- return rv;
-
- /* Endianness */
- sh->flags = le32_to_cpu(sh->flags);
- sh->trap_addr = le32_to_cpu(sh->trap_addr);
- sh->assert_exp_addr = le32_to_cpu(sh->assert_exp_addr);
- sh->assert_file_addr = le32_to_cpu(sh->assert_file_addr);
- sh->assert_line = le32_to_cpu(sh->assert_line);
- sh->console_addr = le32_to_cpu(sh->console_addr);
- sh->msgtrace_addr = le32_to_cpu(sh->msgtrace_addr);
-
- if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
- BRCMF_ERROR(("%s: sdpcm_shared version %d in brcmf "
- "is different than sdpcm_shared version %d in dongle\n",
- __func__, SDPCM_SHARED_VERSION,
- sh->flags & SDPCM_SHARED_VERSION_MASK));
- return -EBADE;
- }
-
- return 0;
-}
-
-static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size)
-{
- int bcmerror = 0;
- uint msize = 512;
- char *mbuffer = NULL;
- uint maxstrlen = 256;
- char *str = NULL;
- struct brcmf_trap tr;
- struct sdpcm_shared sdpcm_shared;
- struct brcmu_strbuf strbuf;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (data == NULL) {
- /*
- * Called after a rx ctrl timeout. "data" is NULL.
- * allocate memory to trace the trap or assert.
- */
- size = msize;
- mbuffer = data = kmalloc(msize, GFP_ATOMIC);
- if (mbuffer == NULL) {
- BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__,
- msize));
- bcmerror = -ENOMEM;
- goto done;
- }
- }
-
- str = kmalloc(maxstrlen, GFP_ATOMIC);
- if (str == NULL) {
- BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__, maxstrlen));
- bcmerror = -ENOMEM;
- goto done;
- }
-
- bcmerror = brcmf_sdbrcm_readshared(bus, &sdpcm_shared);
- if (bcmerror < 0)
- goto done;
-
- brcmu_binit(&strbuf, data, size);
-
- brcmu_bprintf(&strbuf,
- "msgtrace address : 0x%08X\nconsole address : 0x%08X\n",
- sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
-
- if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
- /* NOTE: Misspelled assert is intentional - DO NOT FIX.
- * (Avoids conflict with real asserts for programmatic
- * parsing of output.)
- */
- brcmu_bprintf(&strbuf, "Assrt not built in dongle\n");
- }
-
- if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) ==
- 0) {
- /* NOTE: Misspelled assert is intentional - DO NOT FIX.
- * (Avoids conflict with real asserts for programmatic
- * parsing of output.)
- */
- brcmu_bprintf(&strbuf, "No trap%s in dongle",
- (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
- ? "/assrt" : "");
- } else {
- if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
- /* Download assert */
- brcmu_bprintf(&strbuf, "Dongle assert");
- if (sdpcm_shared.assert_exp_addr != 0) {
- str[0] = '\0';
- bcmerror = brcmf_sdbrcm_membytes(bus, false,
- sdpcm_shared.assert_exp_addr,
- (u8 *) str, maxstrlen);
- if (bcmerror < 0)
- goto done;
-
- str[maxstrlen - 1] = '\0';
- brcmu_bprintf(&strbuf, " expr \"%s\"", str);
- }
-
- if (sdpcm_shared.assert_file_addr != 0) {
- str[0] = '\0';
- bcmerror = brcmf_sdbrcm_membytes(bus, false,
- sdpcm_shared.assert_file_addr,
- (u8 *) str, maxstrlen);
- if (bcmerror < 0)
- goto done;
-
- str[maxstrlen - 1] = '\0';
- brcmu_bprintf(&strbuf, " file \"%s\"", str);
- }
-
- brcmu_bprintf(&strbuf, " line %d ",
- sdpcm_shared.assert_line);
- }
-
- if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
- bcmerror = brcmf_sdbrcm_membytes(bus, false,
- sdpcm_shared.trap_addr, (u8 *)&tr,
- sizeof(struct brcmf_trap));
- if (bcmerror < 0)
- goto done;
-
- brcmu_bprintf(&strbuf,
- "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
- "lp 0x%x, rpc 0x%x Trap offset 0x%x, "
- "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n",
- tr.type, tr.epc, tr.cpsr, tr.spsr, tr.r13,
- tr.r14, tr.pc, sdpcm_shared.trap_addr,
- tr.r0, tr.r1, tr.r2, tr.r3, tr.r4, tr.r5,
- tr.r6, tr.r7);
- }
- }
-
- if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP))
- BRCMF_ERROR(("%s: %s\n", __func__, strbuf.origbuf));
-
-#ifdef BCMDBG
- if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
- /* Mem dump to a file on device */
- brcmf_sdbrcm_mem_dump(bus);
- }
-#endif /* BCMDBG */
-
-done:
- kfree(mbuffer);
- kfree(str);
-
- return bcmerror;
-}
-
-static int brcmf_sdbrcm_mem_dump(struct brcmf_bus *bus)
-{
- int ret = 0;
- int size; /* Full mem size */
- int start = 0; /* Start address */
- int read_size = 0; /* Read size of each iteration */
- u8 *buf = NULL, *databuf = NULL;
-
- /* Get full mem size */
- size = bus->ramsize;
- buf = kmalloc(size, GFP_ATOMIC);
- if (!buf) {
- BRCMF_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size));
- return -1;
- }
-
- /* Read mem content */
- printk(KERN_DEBUG "Dump dongle memory");
- databuf = buf;
- while (size) {
- read_size = min(MEMBLOCK, size);
- ret = brcmf_sdbrcm_membytes(bus, false, start, databuf,
- read_size);
- if (ret) {
- BRCMF_ERROR(("%s: Error membytes %d\n", __func__, ret));
- kfree(buf);
- return -1;
- }
- printk(".");
-
- /* Decrement size and increment start address */
- size -= read_size;
- start += read_size;
- databuf += read_size;
- }
- printk(KERN_DEBUG "Done\n");
-
- /* free buf before return !!! */
- if (brcmf_write_to_file(bus->drvr, buf, bus->ramsize)) {
- BRCMF_ERROR(("%s: Error writing to files\n", __func__));
- return -1;
- }
-
- /* buf free handled in brcmf_write_to_file, not here */
- return 0;
-}
-
-#define CONSOLE_LINE_MAX 192
-
-static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus)
-{
- struct brcmf_console *c = &bus->console;
- u8 line[CONSOLE_LINE_MAX], ch;
- u32 n, idx, addr;
- int rv;
-
- /* Don't do anything until FWREADY updates console address */
- if (bus->console_addr == 0)
- return 0;
-
- /* Read console log struct */
- addr = bus->console_addr + offsetof(struct rte_console, log);
- rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log,
- sizeof(c->log));
- if (rv < 0)
- return rv;
-
- /* Allocate console buffer (one time only) */
- if (c->buf == NULL) {
- c->bufsize = le32_to_cpu(c->log.buf_size);
- c->buf = kmalloc(c->bufsize, GFP_ATOMIC);
- if (c->buf == NULL)
- return -ENOMEM;
- }
-
- idx = le32_to_cpu(c->log.idx);
-
- /* Protect against corrupt value */
- if (idx > c->bufsize)
- return -EBADE;
-
- /* Skip reading the console buffer if the index pointer
- has not moved */
- if (idx == c->last)
- return 0;
-
- /* Read the console buffer */
- addr = le32_to_cpu(c->log.buf);
- rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize);
- if (rv < 0)
- return rv;
-
- while (c->last != idx) {
- for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
- if (c->last == idx) {
- /* This would output a partial line.
- * Instead, back up
- * the buffer pointer and output this
- * line next time around.
- */
- if (c->last >= n)
- c->last -= n;
- else
- c->last = c->bufsize - n;
- goto break2;
- }
- ch = c->buf[c->last];
- c->last = (c->last + 1) % c->bufsize;
- if (ch == '\n')
- break;
- line[n] = ch;
- }
-
- if (n > 0) {
- if (line[n - 1] == '\r')
- n--;
- line[n] = 0;
- printk(KERN_DEBUG "CONSOLE: %s\n", line);
- }
- }
-break2:
-
- return 0;
-}
-#endif /* BCMDBG */
-
-int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len)
-{
- int bcmerror = 0;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* Basic sanity checks */
- if (bus->drvr->up) {
- bcmerror = -EISCONN;
- goto err;
- }
- if (!len) {
- bcmerror = -EOVERFLOW;
- goto err;
- }
-
- /* Free the old ones and replace with passed variables */
- kfree(bus->vars);
-
- bus->vars = kmalloc(len, GFP_ATOMIC);
- bus->varsz = bus->vars ? len : 0;
- if (bus->vars == NULL) {
- bcmerror = -ENOMEM;
- goto err;
- }
-
- /* Copy the passed variables, which should include the
- terminating double-null */
- memcpy(bus->vars, arg, bus->varsz);
-err:
- return bcmerror;
-}
-
-static int
-brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, const struct brcmu_iovar *vi, u32 actionid,
- const char *name, void *params, int plen, void *arg, int len,
- int val_size)
-{
- int bcmerror = 0;
- s32 int_val = 0;
- bool bool_val = 0;
-
- BRCMF_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p "
- "len %d val_size %d\n", __func__, actionid, name, params,
- plen, arg, len, val_size));
-
- bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
- if (bcmerror != 0)
- goto exit;
-
- if (plen >= (int)sizeof(int_val))
- memcpy(&int_val, params, sizeof(int_val));
-
- bool_val = (int_val != 0) ? true : false;
-
- /* Some ioctls use the bus */
- brcmf_sdbrcm_sdlock(bus);
-
- /* Check if dongle is in reset. If so, only allow DEVRESET iovars */
- if (bus->drvr->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
- actionid == IOV_GVAL(IOV_DEVRESET))) {
- bcmerror = -EPERM;
- goto exit;
- }
-
- /* Handle sleep stuff before any clock mucking */
- if (vi->varid == IOV_SLEEP) {
- if (IOV_ISSET(actionid)) {
- bcmerror = brcmf_sdbrcm_bussleep(bus, bool_val);
- } else {
- int_val = (s32) bus->sleeping;
- memcpy(arg, &int_val, val_size);
- }
- goto exit;
- }
-
- /* Request clock to allow SDIO accesses */
- if (!bus->drvr->dongle_reset) {
- BUS_WAKE(bus);
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- }
-
- switch (actionid) {
- case IOV_GVAL(IOV_INTR):
- int_val = (s32) bus->intr;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_INTR):
- bus->intr = bool_val;
- bus->intdis = false;
- if (bus->drvr->up) {
- BRCMF_INTR(("%s: %s SDIO interrupts\n", __func__,
- bus->intr ? "enable" : "disable"));
- if (bus->intr) {
- brcmf_sdcard_intr_enable(bus->card);
- } else {
- brcmf_sdcard_intr_disable(bus->card);
- }
- }
- break;
-
- case IOV_GVAL(IOV_POLLRATE):
- int_val = (s32) bus->pollrate;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_POLLRATE):
- bus->pollrate = (uint) int_val;
- bus->poll = (bus->pollrate != 0);
- break;
-
- case IOV_GVAL(IOV_IDLETIME):
- int_val = bus->idletime;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_IDLETIME):
- if ((int_val < 0) && (int_val != BRCMF_IDLE_IMMEDIATE))
- bcmerror = -EINVAL;
- else
- bus->idletime = int_val;
- break;
-
- case IOV_GVAL(IOV_IDLECLOCK):
- int_val = (s32) bus->idleclock;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_IDLECLOCK):
- bus->idleclock = int_val;
- break;
-
- case IOV_GVAL(IOV_SD1IDLE):
- int_val = (s32) sd1idle;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_SD1IDLE):
- sd1idle = bool_val;
- break;
-
- case IOV_SVAL(IOV_MEMBYTES):
- case IOV_GVAL(IOV_MEMBYTES):
- {
- u32 address;
- uint size, dsize;
- u8 *data;
-
- bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
-
- address = (u32) int_val;
- memcpy(&int_val, (char *)params + sizeof(int_val),
- sizeof(int_val));
- size = (uint) int_val;
-
- /* Do some validation */
- dsize = set ? plen - (2 * sizeof(int)) : len;
- if (dsize < size) {
- BRCMF_ERROR(("%s: error on %s membytes, addr "
- "0x%08x size %d dsize %d\n",
- __func__, (set ? "set" : "get"),
- address, size, dsize));
- bcmerror = -EINVAL;
- break;
- }
-
- BRCMF_INFO(("%s: Request to %s %d bytes at address "
- "0x%08x\n", __func__,
- (set ? "write" : "read"), size, address));
-
- /* If we know about SOCRAM, check for a fit */
- if ((bus->orig_ramsize) &&
- ((address > bus->orig_ramsize)
- || (address + size > bus->orig_ramsize))) {
- BRCMF_ERROR(("%s: ramsize 0x%08x doesn't have"
- " %d bytes at 0x%08x\n", __func__,
- bus->orig_ramsize, size, address));
- bcmerror = -EINVAL;
- break;
- }
-
- /* Generate the actual data pointer */
- data =
- set ? (u8 *) params +
- 2 * sizeof(int) : (u8 *) arg;
-
- /* Call to do the transfer */
- bcmerror = brcmf_sdbrcm_membytes(bus, set, address,
- data, size);
-
- break;
- }
-
- case IOV_GVAL(IOV_MEMSIZE):
- int_val = (s32) bus->ramsize;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_GVAL(IOV_SDIOD_DRIVE):
- int_val = (s32) brcmf_sdiod_drive_strength;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_SDIOD_DRIVE):
- brcmf_sdiod_drive_strength = int_val;
- brcmf_sdbrcm_sdiod_drive_strength_init(bus,
- brcmf_sdiod_drive_strength);
- break;
-
- case IOV_SVAL(IOV_DOWNLOAD):
- bcmerror = brcmf_sdbrcm_download_state(bus, bool_val);
- break;
-
- case IOV_SVAL(IOV_VARS):
- bcmerror = brcmf_sdbrcm_downloadvars(bus, arg, len);
- break;
-
- case IOV_GVAL(IOV_READAHEAD):
- int_val = (s32) brcmf_readahead;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_READAHEAD):
- if (bool_val && !brcmf_readahead)
- bus->nextlen = 0;
- brcmf_readahead = bool_val;
- break;
-
- case IOV_GVAL(IOV_SDRXCHAIN):
- int_val = (s32) bus->use_rxchain;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_SDRXCHAIN):
- if (bool_val && !bus->sd_rxchain)
- bcmerror = -ENOTSUPP;
- else
- bus->use_rxchain = bool_val;
- break;
- case IOV_GVAL(IOV_ALIGNCTL):
- int_val = (s32) brcmf_alignctl;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_ALIGNCTL):
- brcmf_alignctl = bool_val;
- break;
-
- case IOV_GVAL(IOV_SDALIGN):
- int_val = BRCMF_SDALIGN;
- memcpy(arg, &int_val, val_size);
- break;
-
-#ifdef BCMDBG
- case IOV_GVAL(IOV_VARS):
- if (bus->varsz < (uint) len)
- memcpy(arg, bus->vars, bus->varsz);
+ if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
+ bus->sdpcm_ver =
+ (hmb_data & HMB_DATA_VERSION_MASK) >>
+ HMB_DATA_VERSION_SHIFT;
+ if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
+ brcmf_dbg(ERROR, "Version mismatch, dongle reports %d, "
+ "expecting %d\n",
+ bus->sdpcm_ver, SDPCM_PROT_VERSION);
else
- bcmerror = -EOVERFLOW;
- break;
-#endif /* BCMDBG */
-
-#ifdef BCMDBG
- case IOV_GVAL(IOV_DCONSOLE_POLL):
- int_val = (s32) brcmf_console_ms;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_DCONSOLE_POLL):
- brcmf_console_ms = (uint) int_val;
- break;
-
- case IOV_SVAL(IOV_CONS):
- if (len > 0)
- bcmerror = brcmf_sdbrcm_bus_console_in(bus->drvr,
- arg, len - 1);
- break;
-
- case IOV_GVAL(IOV_SDREG):
- {
- struct brcmf_sdreg *sd_ptr;
- u32 addr, size;
-
- sd_ptr = (struct brcmf_sdreg *) params;
-
- addr = bus->ci->buscorebase + sd_ptr->offset;
- size = sd_ptr->func;
- int_val = (s32) brcmf_sdcard_reg_read(bus->card, addr,
- size);
- if (brcmf_sdcard_regfail(bus->card))
- bcmerror = -EIO;
- memcpy(arg, &int_val, sizeof(s32));
- break;
- }
-
- case IOV_SVAL(IOV_SDREG):
- {
- struct brcmf_sdreg *sd_ptr;
- u32 addr, size;
-
- sd_ptr = (struct brcmf_sdreg *) params;
-
- addr = bus->ci->buscorebase + sd_ptr->offset;
- size = sd_ptr->func;
- brcmf_sdcard_reg_write(bus->card, addr, size,
- sd_ptr->value);
- if (brcmf_sdcard_regfail(bus->card))
- bcmerror = -EIO;
- break;
- }
-
- /* Same as above, but offset is not backplane
- (not SDIO core) */
- case IOV_GVAL(IOV_SBREG):
- {
- struct brcmf_sdreg sdreg;
- u32 addr, size;
-
- memcpy(&sdreg, params, sizeof(sdreg));
-
- addr = SI_ENUM_BASE + sdreg.offset;
- size = sdreg.func;
- int_val = (s32) brcmf_sdcard_reg_read(bus->card, addr,
- size);
- if (brcmf_sdcard_regfail(bus->card))
- bcmerror = -EIO;
- memcpy(arg, &int_val, sizeof(s32));
- break;
- }
-
- case IOV_SVAL(IOV_SBREG):
- {
- struct brcmf_sdreg sdreg;
- u32 addr, size;
-
- memcpy(&sdreg, params, sizeof(sdreg));
-
- addr = SI_ENUM_BASE + sdreg.offset;
- size = sdreg.func;
- brcmf_sdcard_reg_write(bus->card, addr, size,
- sdreg.value);
- if (brcmf_sdcard_regfail(bus->card))
- bcmerror = -EIO;
- break;
- }
-
- case IOV_GVAL(IOV_SDCIS):
- {
- *(char *)arg = 0;
-
- strcat(arg, "\nFunc 0\n");
- brcmf_sdcard_cis_read(bus->card, 0x10,
- (u8 *) arg + strlen(arg),
- SBSDIO_CIS_SIZE_LIMIT);
- strcat(arg, "\nFunc 1\n");
- brcmf_sdcard_cis_read(bus->card, 0x11,
- (u8 *) arg + strlen(arg),
- SBSDIO_CIS_SIZE_LIMIT);
- strcat(arg, "\nFunc 2\n");
- brcmf_sdcard_cis_read(bus->card, 0x12,
- (u8 *) arg + strlen(arg),
- SBSDIO_CIS_SIZE_LIMIT);
- break;
- }
-
- case IOV_GVAL(IOV_FORCEEVEN):
- int_val = (s32) forcealign;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_FORCEEVEN):
- forcealign = bool_val;
- break;
-
- case IOV_GVAL(IOV_TXBOUND):
- int_val = (s32) brcmf_txbound;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_TXBOUND):
- brcmf_txbound = (uint) int_val;
- break;
-
- case IOV_GVAL(IOV_RXBOUND):
- int_val = (s32) brcmf_rxbound;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_RXBOUND):
- brcmf_rxbound = (uint) int_val;
- break;
-
- case IOV_GVAL(IOV_TXMINMAX):
- int_val = (s32) brcmf_txminmax;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_TXMINMAX):
- brcmf_txminmax = (uint) int_val;
- break;
-#endif /* BCMDBG */
-
-#ifdef SDTEST
- case IOV_GVAL(IOV_EXTLOOP):
- int_val = (s32) bus->ext_loop;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_EXTLOOP):
- bus->ext_loop = bool_val;
- break;
-
- case IOV_GVAL(IOV_PKTGEN):
- bcmerror = brcmf_sdbrcm_pktgen_get(bus, arg);
- break;
-
- case IOV_SVAL(IOV_PKTGEN):
- bcmerror = brcmf_sdbrcm_pktgen_set(bus, arg);
- break;
-#endif /* SDTEST */
-
- case IOV_SVAL(IOV_DEVRESET):
- BRCMF_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d "
- "busstate=%d\n",
- __func__, bool_val, bus->drvr->dongle_reset,
- bus->drvr->busstate));
-
- brcmf_bus_devreset(bus->drvr, (u8) bool_val);
-
- break;
-
- case IOV_GVAL(IOV_DEVRESET):
- BRCMF_TRACE(("%s: Called get IOV_DEVRESET\n", __func__));
-
- /* Get its status */
- int_val = (bool) bus->drvr->dongle_reset;
- memcpy(arg, &int_val, val_size);
-
- break;
-
- case IOV_GVAL(IOV_WDTICK):
- int_val = (s32) brcmf_watchdog_ms;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_WDTICK):
- if (!bus->drvr->up) {
- bcmerror = -ENOLINK;
- break;
- }
- brcmf_sdbrcm_wd_timer(bus, (uint) int_val);
- break;
-
- default:
- bcmerror = -ENOTSUPP;
- break;
+ brcmf_dbg(INFO, "Dongle ready, protocol version %d\n",
+ bus->sdpcm_ver);
}
-exit:
- if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
- bus->activity = false;
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
- }
-
- brcmf_sdbrcm_sdunlock(bus);
-
- if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == false)
- brcmf_c_preinit_ioctls(bus->drvr);
-
- return bcmerror;
-}
-
-static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus)
-{
- int bcmerror = 0;
- u32 varsize;
- u32 varaddr;
- u8 *vbuffer;
- u32 varsizew;
-#ifdef BCMDBG
- char *nvram_ularray;
-#endif /* BCMDBG */
-
- /* Even if there are no vars are to be written, we still
- need to set the ramsize. */
- varsize = bus->varsz ? roundup(bus->varsz, 4) : 0;
- varaddr = (bus->ramsize - 4) - varsize;
-
- if (bus->vars) {
- vbuffer = kzalloc(varsize, GFP_ATOMIC);
- if (!vbuffer)
- return -ENOMEM;
-
- memcpy(vbuffer, bus->vars, bus->varsz);
-
- /* Write the vars list */
- bcmerror =
- brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize);
-#ifdef BCMDBG
- /* Verify NVRAM bytes */
- BRCMF_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
- nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
- if (!nvram_ularray)
- return -ENOMEM;
-
- /* Upload image to verify downloaded contents. */
- memset(nvram_ularray, 0xaa, varsize);
-
- /* Read the vars list to temp buffer for comparison */
- bcmerror =
- brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray,
- varsize);
- if (bcmerror) {
- BRCMF_ERROR(("%s: error %d on reading %d nvram bytes"
- " at 0x%08x\n", __func__, bcmerror,
- varsize, varaddr));
- }
- /* Compare the org NVRAM with the one read from RAM */
- if (memcmp(vbuffer, nvram_ularray, varsize)) {
- BRCMF_ERROR(("%s: Downloaded NVRAM image is "
- "corrupted.\n", __func__));
- } else
- BRCMF_ERROR(("%s: Download/Upload/Compare of"
- " NVRAM ok.\n", __func__));
-
- kfree(nvram_ularray);
-#endif /* BCMDBG */
-
- kfree(vbuffer);
- }
-
- /* adjust to the user specified RAM */
- BRCMF_INFO(("Physical memory size: %d, usable memory size: %d\n",
- bus->orig_ramsize, bus->ramsize));
- BRCMF_INFO(("Vars are at %d, orig varsize is %d\n", varaddr, varsize));
- varsize = ((bus->orig_ramsize - 4) - varaddr);
-
/*
- * Determine the length token:
- * Varsize, converted to words, in lower 16-bits, checksum
- * in upper 16-bits.
- */
- if (bcmerror) {
- varsizew = 0;
- } else {
- varsizew = varsize / 4;
- varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
- varsizew = cpu_to_le32(varsizew);
- }
-
- BRCMF_INFO(("New varsize is %d, length token=0x%08x\n", varsize,
- varsizew));
-
- /* Write the length token to the last word */
- bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->orig_ramsize - 4),
- (u8 *)&varsizew, 4);
-
- return bcmerror;
-}
-
-static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
-{
- uint retries;
- u32 regdata;
- int bcmerror = 0;
-
- /* To enter download state, disable ARM and reset SOCRAM.
- * To exit download state, simply reset ARM (default is RAM boot).
- */
- if (enter) {
- bus->alp_only = true;
-
- brcmf_sdbrcm_chip_disablecore(bus->card, bus->ci->armcorebase);
-
- brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->ramcorebase);
-
- /* Clear the top bit of memory */
- if (bus->ramsize) {
- u32 zeros = 0;
- brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4,
- (u8 *)&zeros, 4);
- }
- } else {
- regdata = brcmf_sdcard_reg_read(bus->card,
- CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4);
- regdata &= (SBTML_RESET | SBTML_REJ_MASK |
- (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
- if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) {
- BRCMF_ERROR(("%s: SOCRAM core is down after reset?\n",
- __func__));
- bcmerror = -EBADE;
- goto fail;
- }
-
- bcmerror = brcmf_sdbrcm_write_vars(bus);
- if (bcmerror) {
- BRCMF_ERROR(("%s: no vars written to RAM\n", __func__));
- bcmerror = 0;
- }
-
- w_sdreg32(bus, 0xFFFFFFFF,
- offsetof(struct sdpcmd_regs, intstatus), &retries);
-
- brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->armcorebase);
-
- /* Allow HT Clock now that the ARM is running. */
- bus->alp_only = false;
-
- bus->drvr->busstate = BRCMF_BUS_LOAD;
- }
-fail:
- return bcmerror;
-}
-
-int
-brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name,
- void *params, int plen, void *arg, int len, bool set)
-{
- struct brcmf_bus *bus = drvr->bus;
- const struct brcmu_iovar *vi = NULL;
- int bcmerror = 0;
- int val_size;
- u32 actionid;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (name == NULL || len <= 0)
- return -EINVAL;
-
- /* Set does not take qualifiers */
- if (set && (params || plen))
- return -EINVAL;
-
- /* Get must have return space;*/
- if (!set && !(arg && len))
- return -EINVAL;
-
- /* Look up var locally; if not found pass to host driver */
- vi = brcmu_iovar_lookup(brcmf_sdio_iovars, name);
- if (vi == NULL) {
- brcmf_sdbrcm_sdlock(bus);
-
- BUS_WAKE(bus);
-
- /* Turn on clock in case SD command needs backplane */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- bcmerror = brcmf_sdcard_iovar_op(bus->card, name, params, plen,
- arg, len, set);
-
- /* Similar check for blocksize change */
- if (set && strcmp(name, "sd_blocksize") == 0) {
- s32 fnum = 2;
- if (brcmf_sdcard_iovar_op
- (bus->card, "sd_blocksize", &fnum, sizeof(s32),
- &bus->blocksize, sizeof(s32),
- false) != 0) {
- bus->blocksize = 0;
- BRCMF_ERROR(("%s: fail on %s get\n", __func__,
- "sd_blocksize"));
- } else {
- BRCMF_INFO(("%s: noted sd_blocksize update,"
- " value now %d\n", __func__,
- bus->blocksize));
- }
- }
- bus->roundup = min(max_roundup, bus->blocksize);
-
- if (bus->idletime == BRCMF_IDLE_IMMEDIATE &&
- !bus->dpc_sched) {
- bus->activity = false;
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
- }
-
- brcmf_sdbrcm_sdunlock(bus);
- goto exit;
- }
-
- BRCMF_CTL(("%s: %s %s, len %d plen %d\n", __func__,
- name, (set ? "set" : "get"), len, plen));
-
- /* set up 'params' pointer in case this is a set command so that
- * the convenience int and bool code can be common to set and get
+ * Flow Control has been moved into the RX headers and this out of band
+ * method isn't used any more.
+ * remaining backward compatible with older dongles.
*/
- if (params == NULL) {
- params = arg;
- plen = len;
- }
-
- if (vi->type == IOVT_VOID)
- val_size = 0;
- else if (vi->type == IOVT_BUFFER)
- val_size = len;
- else
- /* all other types are integer sized */
- val_size = sizeof(int);
-
- actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
- bcmerror = brcmf_sdbrcm_doiovar(bus, vi, actionid, name, params, plen,
- arg, len, val_size);
-
-exit:
- return bcmerror;
-}
-
-void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex)
-{
- u32 local_hostintmask;
- u8 saveclk;
- uint retries;
- int err;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (enforce_mutex)
- brcmf_sdbrcm_sdlock(bus);
-
- BUS_WAKE(bus);
-
- /* Enable clock for device interrupts */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- if (bus->watchdog_tsk) {
- send_sig(SIGTERM, bus->watchdog_tsk, 1);
- kthread_stop(bus->watchdog_tsk);
- bus->watchdog_tsk = NULL;
- }
-
- if (bus->dpc_tsk) {
- send_sig(SIGTERM, bus->dpc_tsk, 1);
- kthread_stop(bus->dpc_tsk);
- bus->dpc_tsk = NULL;
- } else
- tasklet_kill(&bus->tasklet);
-
- /* Disable and clear interrupts at the chip level also */
- w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries);
- local_hostintmask = bus->hostintmask;
- bus->hostintmask = 0;
-
- /* Change our idea of bus state */
- bus->drvr->busstate = BRCMF_BUS_DOWN;
-
- /* Force clocks on backplane to be sure F2 interrupt propagates */
- saveclk = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (!err) {
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- (saveclk | SBSDIO_FORCE_HT), &err);
- }
- if (err) {
- BRCMF_ERROR(("%s: Failed to force clock for F2: err %d\n",
- __func__, err));
- }
-
- /* Turn off the bus (F2), free any pending packets */
- BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
- brcmf_sdcard_intr_disable(bus->card);
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
- SDIO_FUNC_ENABLE_1, NULL);
-
- /* Clear any pending interrupts now that F2 is disabled */
- w_sdreg32(bus, local_hostintmask,
- offsetof(struct sdpcmd_regs, intstatus), &retries);
-
- /* Turn off the backplane clock (only) */
- brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
-
- /* Clear the data packet queues */
- brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
-
- /* Clear any held glomming stuff */
- if (bus->glomd)
- brcmu_pkt_buf_free_skb(bus->glomd);
-
- if (bus->glom)
- brcmu_pkt_buf_free_skb(bus->glom);
-
- bus->glom = bus->glomd = NULL;
-
- /* Clear rx control and wake any waiters */
- bus->rxlen = 0;
- brcmf_os_ioctl_resp_wake(bus->drvr);
-
- /* Reset some F2 state stuff */
- bus->rxskip = false;
- bus->tx_seq = bus->rx_seq = 0;
-
- if (enforce_mutex)
- brcmf_sdbrcm_sdunlock(bus);
-}
-
-int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex)
-{
- struct brcmf_bus *bus = drvr->bus;
- struct brcmf_timeout tmo;
- uint retries = 0;
- u8 ready, enable;
- int err, ret = 0;
- u8 saveclk;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* try to download image and nvram to the dongle */
- if (drvr->busstate == BRCMF_BUS_DOWN) {
- if (!(brcmf_sdbrcm_download_firmware(bus, bus->card)))
- return -1;
- }
-
- if (!bus->drvr)
- return 0;
-
- /* Start the watchdog timer */
- bus->drvr->tickcnt = 0;
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
-
- if (enforce_mutex)
- brcmf_sdbrcm_sdlock(bus);
-
- /* Make sure backplane clock is on, needed to generate F2 interrupt */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- if (bus->clkstate != CLK_AVAIL)
- goto exit;
-
- /* Force clocks on backplane to be sure F2 interrupt propagates */
- saveclk =
- brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (!err) {
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- (saveclk | SBSDIO_FORCE_HT), &err);
- }
- if (err) {
- BRCMF_ERROR(("%s: Failed to force clock for F2: err %d\n",
- __func__, err));
- goto exit;
- }
-
- /* Enable function 2 (frame transfers) */
- w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
- offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries);
- enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
-
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx, enable,
- NULL);
-
- /* Give the dongle some time to do its thing and set IOR2 */
- brcmf_timeout_start(&tmo, BRCMF_WAIT_F2RDY * 1000);
-
- ready = 0;
- while (ready != enable && !brcmf_timeout_expired(&tmo))
- ready = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_0,
- SDIO_CCCR_IORx, NULL);
-
- BRCMF_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
- __func__, enable, ready, tmo.elapsed));
-
- /* If F2 successfully enabled, set core and enable interrupts */
- if (ready == enable) {
- /* Set up the interrupt mask and enable interrupts */
- bus->hostintmask = HOSTINTMASK;
- w_sdreg32(bus, bus->hostintmask,
- offsetof(struct sdpcmd_regs, hostintmask), &retries);
-
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_WATERMARK,
- (u8) watermark, &err);
-
- /* Set bus state according to enable result */
- drvr->busstate = BRCMF_BUS_DATA;
-
- bus->intdis = false;
- if (bus->intr) {
- BRCMF_INTR(("%s: enable SDIO device interrupts\n",
- __func__));
- brcmf_sdcard_intr_enable(bus->card);
- } else {
- BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
- brcmf_sdcard_intr_disable(bus->card);
- }
-
- }
+ if (hmb_data & HMB_DATA_FC) {
+ fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >>
+ HMB_DATA_FCDATA_SHIFT;
- else {
- /* Disable F2 again */
- enable = SDIO_FUNC_ENABLE_1;
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
- enable, NULL);
- }
+ if (fcbits & ~bus->flowcontrol)
+ bus->fc_xoff++;
- /* Restore previous clock setting */
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- saveclk, &err);
+ if (bus->flowcontrol & ~fcbits)
+ bus->fc_xon++;
-#if defined(OOB_INTR_ONLY)
- /* Host registration for OOB interrupt */
- if (brcmf_sdio_register_oob_intr(bus->dhd)) {
- brcmf_sdbrcm_wd_timer(bus, 0);
- BRCMF_ERROR(("%s Host failed to resgister for OOB\n",
- __func__));
- ret = -ENODEV;
- goto exit;
+ bus->fc_rcvd++;
+ bus->flowcontrol = fcbits;
}
- /* Enable oob at firmware */
- brcmf_sdbrcm_enable_oob_intr(bus, true);
-#endif /* defined(OOB_INTR_ONLY) */
-
- /* If we didn't come up, turn off backplane clock */
- if (drvr->busstate != BRCMF_BUS_DATA)
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
-
-exit:
- if (enforce_mutex)
- brcmf_sdbrcm_sdunlock(bus);
+ /* Shouldn't be any others */
+ if (hmb_data & ~(HMB_DATA_DEVREADY |
+ HMB_DATA_NAKHANDLED |
+ HMB_DATA_FC |
+ HMB_DATA_FWREADY |
+ HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK))
+ brcmf_dbg(ERROR, "Unknown mailbox data content: 0x%02x\n",
+ hmb_data);
- return ret;
+ return intstatus;
}
static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
{
- struct brcmf_sdio_card *card = bus->card;
uint retries = 0;
u16 lastrbc;
u8 hi, lo;
int err;
- BRCMF_ERROR(("%s: %sterminate frame%s\n", __func__,
- (abort ? "abort command, " : ""),
- (rtx ? ", send NAK" : "")));
+ brcmf_dbg(ERROR, "%sterminate frame%s\n",
+ abort ? "abort command, " : "",
+ rtx ? ", send NAK" : "");
if (abort)
- brcmf_sdcard_abort(card, SDIO_FUNC_2);
+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_FRAMECTRL,
SFC_RF_TERM, &err);
bus->f1regdata++;
/* Wait until the packet has been flushed (device/FIFO stable) */
for (lastrbc = retries = 0xffff; retries > 0; retries--) {
- hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_RFRAMEBCHI, NULL);
- lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_RFRAMEBCLO, NULL);
bus->f1regdata += 2;
@@ -3448,20 +1193,16 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
break;
if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
- BRCMF_ERROR(("%s: count growing: last 0x%04x now "
- "0x%04x\n",
- __func__, lastrbc, ((hi << 8) + lo)));
+ brcmf_dbg(ERROR, "count growing: last 0x%04x now 0x%04x\n",
+ lastrbc, (hi << 8) + lo);
}
lastrbc = (hi << 8) + lo;
}
- if (!retries) {
- BRCMF_ERROR(("%s: count never zeroed: last 0x%04x\n",
- __func__, lastrbc));
- } else {
- BRCMF_INFO(("%s: flush took %d iterations\n", __func__,
- (0xffff - retries)));
- }
+ if (!retries)
+ brcmf_dbg(ERROR, "count never zeroed: last 0x%04x\n", lastrbc);
+ else
+ brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries);
if (rtx) {
bus->rxrtx++;
@@ -3477,113 +1218,10 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
bus->nextlen = 0;
/* If we can't reach the device, signal failure */
- if (err || brcmf_sdcard_regfail(card))
+ if (err || brcmf_sdcard_regfail(bus->sdiodev))
bus->drvr->busstate = BRCMF_BUS_DOWN;
}
-static void
-brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff)
-{
- struct brcmf_sdio_card *card = bus->card;
- uint rdlen, pad;
-
- int sdret;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* Control data already received in aligned rxctl */
- if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
- goto gotpkt;
-
- /* Set rxctl for frame (w/optional alignment) */
- bus->rxctl = bus->rxbuf;
- if (brcmf_alignctl) {
- bus->rxctl += firstread;
- pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN);
- if (pad)
- bus->rxctl += (BRCMF_SDALIGN - pad);
- bus->rxctl -= firstread;
- }
-
- /* Copy the already-read portion over */
- memcpy(bus->rxctl, hdr, firstread);
- if (len <= firstread)
- goto gotpkt;
-
- /* Copy the full data pkt in gSPI case and process ioctl. */
- if (bus->bus == SPI_BUS) {
- memcpy(bus->rxctl, hdr, len);
- goto gotpkt;
- }
-
- /* Raise rdlen to next SDIO block to avoid tail command */
- rdlen = len - firstread;
- if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
- pad = bus->blocksize - (rdlen % bus->blocksize);
- if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
- ((len + pad) < bus->drvr->maxctl))
- rdlen += pad;
- } else if (rdlen % BRCMF_SDALIGN) {
- rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
- }
-
- /* Satisfy length-alignment requirements */
- if (forcealign && (rdlen & (ALIGNMENT - 1)))
- rdlen = roundup(rdlen, ALIGNMENT);
-
- /* Drop if the read is too big or it exceeds our maximum */
- if ((rdlen + firstread) > bus->drvr->maxctl) {
- BRCMF_ERROR(("%s: %d-byte control read exceeds %d-byte"
- " buffer\n", __func__, rdlen, bus->drvr->maxctl));
- bus->drvr->rx_errors++;
- brcmf_sdbrcm_rxfail(bus, false, false);
- goto done;
- }
-
- if ((len - doff) > bus->drvr->maxctl) {
- BRCMF_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds "
- "%d-byte limit\n",
- __func__, len, (len - doff), bus->drvr->maxctl));
- bus->drvr->rx_errors++;
- bus->rx_toolong++;
- brcmf_sdbrcm_rxfail(bus, false, false);
- goto done;
- }
-
- /* Read remainder of frame body into the rxctl buffer */
- sdret = brcmf_sdcard_recv_buf(card, brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2,
- F2SYNC, (bus->rxctl + firstread), rdlen,
- NULL, NULL, NULL);
- bus->f2rxdata++;
-
- /* Control frame failures need retransmission */
- if (sdret < 0) {
- BRCMF_ERROR(("%s: read %d control bytes failed: %d\n",
- __func__, rdlen, sdret));
- bus->rxc_errors++;
- brcmf_sdbrcm_rxfail(bus, true, true);
- goto done;
- }
-
-gotpkt:
-
-#ifdef BCMDBG
- if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
- printk(KERN_DEBUG "RxCtrl:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len);
- }
-#endif
-
- /* Point to valid data and indicate its length */
- bus->rxctl += doff;
- bus->rxlen = len - doff;
-
-done:
- /* Awake any waiters */
- brcmf_os_ioctl_resp_wake(bus->drvr);
-}
-
static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
{
u16 dlen, totlen;
@@ -3602,8 +1240,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
/* If packets, issue read(s) and send up packet chain */
/* Return sequence numbers consumed? */
- BRCMF_TRACE(("brcmf_sdbrcm_rxglom: start: glomd %p glom %p\n",
- bus->glomd, bus->glom));
+ brcmf_dbg(TRACE, "start: glomd %p glom %p\n", bus->glomd, bus->glom);
/* If there's a descriptor, generate the packet chain */
if (bus->glomd) {
@@ -3611,9 +1248,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
dlen = (u16) (bus->glomd->len);
dptr = bus->glomd->data;
if (!dlen || (dlen & 1)) {
- BRCMF_ERROR(("%s: bad glomd len(%d),"
- " ignore descriptor\n",
- __func__, dlen));
+ brcmf_dbg(ERROR, "bad glomd len(%d), ignore descriptor\n",
+ dlen);
dlen = 0;
}
@@ -3624,15 +1260,14 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
dptr += sizeof(u16);
if ((sublen < SDPCM_HDRLEN) ||
((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
- BRCMF_ERROR(("%s: descriptor len %d bad: %d\n",
- __func__, num, sublen));
+ brcmf_dbg(ERROR, "descriptor len %d bad: %d\n",
+ num, sublen);
pnext = NULL;
break;
}
if (sublen % BRCMF_SDALIGN) {
- BRCMF_ERROR(("%s: sublen %d not multiple of"
- " %d\n", __func__, sublen,
- BRCMF_SDALIGN));
+ brcmf_dbg(ERROR, "sublen %d not multiple of %d\n",
+ sublen, BRCMF_SDALIGN);
usechain = false;
}
totlen += sublen;
@@ -3648,9 +1283,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
/* Allocate/chain packet for next subframe */
pnext = brcmu_pkt_buf_get_skb(sublen + BRCMF_SDALIGN);
if (pnext == NULL) {
- BRCMF_ERROR(("%s: bcm_pkt_buf_get_skb failed, "
- "num %d len %d\n", __func__,
- num, sublen));
+ brcmf_dbg(ERROR, "bcm_pkt_buf_get_skb failed, num %d len %d\n",
+ num, sublen);
break;
}
if (!pfirst) {
@@ -3661,22 +1295,18 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
}
/* Adhere to start alignment requirements */
- PKTALIGN(pnext, sublen, BRCMF_SDALIGN);
+ pkt_align(pnext, sublen, BRCMF_SDALIGN);
}
/* If all allocations succeeded, save packet chain
in bus structure */
if (pnext) {
- BRCMF_GLOM(("%s: allocated %d-byte packet chain for %d "
- "subframes\n", __func__, totlen, num));
- if (BRCMF_GLOM_ON() && bus->nextlen) {
- if (totlen != bus->nextlen) {
- BRCMF_GLOM(("%s: glomdesc mismatch: "
- "nextlen %d glomdesc %d "
- "rxseq %d\n", __func__,
- bus->nextlen,
- totlen, rxseq));
- }
+ brcmf_dbg(GLOM, "allocated %d-byte packet chain for %d subframes\n",
+ totlen, num);
+ if (BRCMF_GLOM_ON() && bus->nextlen &&
+ totlen != bus->nextlen) {
+ brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n",
+ bus->nextlen, totlen, rxseq);
}
bus->glom = pfirst;
pfirst = pnext = NULL;
@@ -3697,12 +1327,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
or had one from before */
if (bus->glom) {
if (BRCMF_GLOM_ON()) {
- BRCMF_GLOM(("%s: try superframe read, packet chain:\n",
- __func__));
+ brcmf_dbg(GLOM, "try superframe read, packet chain:\n");
for (pnext = bus->glom; pnext; pnext = pnext->next) {
- BRCMF_GLOM((" %p: %p len 0x%04x (%d)\n",
- pnext, (u8 *) (pnext->data),
- pnext->len, pnext->len));
+ brcmf_dbg(GLOM, " %p: %p len 0x%04x (%d)\n",
+ pnext, (u8 *) (pnext->data),
+ pnext->len, pnext->len);
}
}
@@ -3714,37 +1343,36 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
* packet and and copy into the chain.
*/
if (usechain) {
- errcode = brcmf_sdcard_recv_buf(bus->card,
- brcmf_sdcard_cur_sbwad(bus->card),
+ errcode = brcmf_sdcard_recv_buf(bus->sdiodev,
+ bus->sdiodev->sbwad,
SDIO_FUNC_2,
F2SYNC, (u8 *) pfirst->data, dlen,
- pfirst, NULL, NULL);
+ pfirst);
} else if (bus->dataptr) {
- errcode = brcmf_sdcard_recv_buf(bus->card,
- brcmf_sdcard_cur_sbwad(bus->card),
+ errcode = brcmf_sdcard_recv_buf(bus->sdiodev,
+ bus->sdiodev->sbwad,
SDIO_FUNC_2,
F2SYNC, bus->dataptr, dlen,
- NULL, NULL, NULL);
+ NULL);
sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen,
bus->dataptr);
if (sublen != dlen) {
- BRCMF_ERROR(("%s: FAILED TO COPY, dlen %d "
- "sublen %d\n",
- __func__, dlen, sublen));
+ brcmf_dbg(ERROR, "FAILED TO COPY, dlen %d sublen %d\n",
+ dlen, sublen);
errcode = -1;
}
pnext = NULL;
} else {
- BRCMF_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, "
- "FORCE FAILURE\n", dlen));
+ brcmf_dbg(ERROR, "COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n",
+ dlen);
errcode = -1;
}
bus->f2rxdata++;
/* On failure, kill the superframe, allow a couple retries */
if (errcode < 0) {
- BRCMF_ERROR(("%s: glom read of %d bytes failed: %d\n",
- __func__, dlen, errcode));
+ brcmf_dbg(ERROR, "glom read of %d bytes failed: %d\n",
+ dlen, errcode);
bus->drvr->rx_errors++;
if (bus->glomerr++ < 3) {
@@ -3775,8 +1403,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
- BRCMF_INFO(("%s: nextlen too large (%d) seq %d\n",
- __func__, bus->nextlen, seq));
+ brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n",
+ bus->nextlen, seq);
bus->nextlen = 0;
}
doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
@@ -3784,48 +1412,42 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
errcode = 0;
if ((u16)~(sublen ^ check)) {
- BRCMF_ERROR(("%s (superframe): HW hdr error: len/check "
- "0x%04x/0x%04x\n", __func__, sublen,
- check));
+ brcmf_dbg(ERROR, "(superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
+ sublen, check);
errcode = -1;
} else if (roundup(sublen, bus->blocksize) != dlen) {
- BRCMF_ERROR(("%s (superframe): len 0x%04x, rounded "
- "0x%04x, expect 0x%04x\n",
- __func__, sublen,
- roundup(sublen, bus->blocksize), dlen));
+ brcmf_dbg(ERROR, "(superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
+ sublen, roundup(sublen, bus->blocksize),
+ dlen);
errcode = -1;
} else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) !=
SDPCM_GLOM_CHANNEL) {
- BRCMF_ERROR(("%s (superframe): bad channel %d\n",
- __func__,
- SDPCM_PACKET_CHANNEL(&dptr
- [SDPCM_FRAMETAG_LEN])));
+ brcmf_dbg(ERROR, "(superframe): bad channel %d\n",
+ SDPCM_PACKET_CHANNEL(
+ &dptr[SDPCM_FRAMETAG_LEN]));
errcode = -1;
} else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
- BRCMF_ERROR(("%s (superframe): got 2nd descriptor?\n",
- __func__));
+ brcmf_dbg(ERROR, "(superframe): got 2nd descriptor?\n");
errcode = -1;
} else if ((doff < SDPCM_HDRLEN) ||
(doff > (pfirst->len - SDPCM_HDRLEN))) {
- BRCMF_ERROR(("%s (superframe): Bad data offset %d: "
- "HW %d pkt %d min %d\n",
- __func__, doff, sublen,
- pfirst->len, SDPCM_HDRLEN));
+ brcmf_dbg(ERROR, "(superframe): Bad data offset %d: HW %d pkt %d min %d\n",
+ doff, sublen, pfirst->len, SDPCM_HDRLEN);
errcode = -1;
}
/* Check sequence number of superframe SW header */
if (rxseq != seq) {
- BRCMF_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
- __func__, seq, rxseq));
+ brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n",
+ seq, rxseq);
bus->rx_badseq++;
rxseq = seq;
}
/* Check window for sanity */
if ((u8) (txmax - bus->tx_seq) > 0x40) {
- BRCMF_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
- __func__, txmax, bus->tx_seq));
+ brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n",
+ txmax, bus->tx_seq);
txmax = bus->tx_seq + 2;
}
bus->tx_max = txmax;
@@ -3852,25 +1474,21 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
#endif
if ((u16)~(sublen ^ check)) {
- BRCMF_ERROR(("%s (subframe %d): HW hdr error: "
- "len/check 0x%04x/0x%04x\n",
- __func__, num, sublen, check));
+ brcmf_dbg(ERROR, "(subframe %d): HW hdr error: len/check 0x%04x/0x%04x\n",
+ num, sublen, check);
errcode = -1;
} else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
- BRCMF_ERROR(("%s (subframe %d): length mismatch"
- ": len 0x%04x, expect 0x%04x\n",
- __func__, num, sublen, dlen));
+ brcmf_dbg(ERROR, "(subframe %d): length mismatch: len 0x%04x, expect 0x%04x\n",
+ num, sublen, dlen);
errcode = -1;
} else if ((chan != SDPCM_DATA_CHANNEL) &&
(chan != SDPCM_EVENT_CHANNEL)) {
- BRCMF_ERROR(("%s (subframe %d): bad channel"
- " %d\n", __func__, num, chan));
+ brcmf_dbg(ERROR, "(subframe %d): bad channel %d\n",
+ num, chan);
errcode = -1;
} else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
- BRCMF_ERROR(("%s (subframe %d): Bad data offset"
- " %d: HW %d min %d\n",
- __func__, num, doff, sublen,
- SDPCM_HDRLEN));
+ brcmf_dbg(ERROR, "(subframe %d): Bad data offset %d: HW %d min %d\n",
+ num, doff, sublen, SDPCM_HDRLEN);
errcode = -1;
}
}
@@ -3908,17 +1526,16 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
- BRCMF_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d "
- "chan %d seq %d\n",
- __func__, num, pfirst, pfirst->data,
- pfirst->len, sublen, chan, seq));
+ brcmf_dbg(GLOM, "Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
+ num, pfirst, pfirst->data,
+ pfirst->len, sublen, chan, seq);
/* precondition: chan == SDPCM_DATA_CHANNEL ||
chan == SDPCM_EVENT_CHANNEL */
if (rxseq != seq) {
- BRCMF_GLOM(("%s: rx_seq %d, expected %d\n",
- __func__, seq, rxseq));
+ brcmf_dbg(GLOM, "rx_seq %d, expected %d\n",
+ seq, rxseq);
bus->rx_badseq++;
rxseq = seq;
}
@@ -3935,23 +1552,22 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
if (pfirst->len == 0) {
brcmu_pkt_buf_free_skb(pfirst);
- if (plast) {
+ if (plast)
plast->next = pnext;
- } else {
+ else
save_pfirst = pnext;
- }
+
continue;
- } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pfirst)
- != 0) {
- BRCMF_ERROR(("%s: rx protocol error\n",
- __func__));
+ } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx,
+ pfirst) != 0) {
+ brcmf_dbg(ERROR, "rx protocol error\n");
bus->drvr->rx_errors++;
brcmu_pkt_buf_free_skb(pfirst);
- if (plast) {
+ if (plast)
plast->next = pnext;
- } else {
+ else
save_pfirst = pnext;
- }
+
continue;
}
@@ -3963,11 +1579,10 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
#ifdef BCMDBG
if (BRCMF_GLOM_ON()) {
- BRCMF_GLOM(("%s subframe %d to stack, %p"
- "(%p/%d) nxt/lnk %p/%p\n",
- __func__, num, pfirst, pfirst->data,
- pfirst->len, pfirst->next,
- pfirst->prev));
+ brcmf_dbg(GLOM, "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n",
+ num, pfirst, pfirst->data,
+ pfirst->len, pfirst->next,
+ pfirst->prev);
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
pfirst->data,
min_t(int, pfirst->len, 32));
@@ -3975,9 +1590,9 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
#endif /* BCMDBG */
}
if (num) {
- brcmf_sdbrcm_sdunlock(bus);
+ up(&bus->sdsem);
brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num);
- brcmf_sdbrcm_sdlock(bus);
+ down(&bus->sdsem);
}
bus->rxglomframes++;
@@ -3986,12 +1601,230 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
return num;
}
+static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_bus *bus, uint *condition,
+ bool *pending)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int timeout = msecs_to_jiffies(DCMD_RESP_TIMEOUT);
+
+ /* Wait until control frame is available */
+ add_wait_queue(&bus->dcmd_resp_wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ while (!(*condition) && (!signal_pending(current) && timeout))
+ timeout = schedule_timeout(timeout);
+
+ if (signal_pending(current))
+ *pending = true;
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&bus->dcmd_resp_wait, &wait);
+
+ return timeout;
+}
+
+static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_bus *bus)
+{
+ if (waitqueue_active(&bus->dcmd_resp_wait))
+ wake_up_interruptible(&bus->dcmd_resp_wait);
+
+ return 0;
+}
+static void
+brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff)
+{
+ uint rdlen, pad;
+
+ int sdret;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Set rxctl for frame (w/optional alignment) */
+ bus->rxctl = bus->rxbuf;
+ bus->rxctl += BRCMF_FIRSTREAD;
+ pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN);
+ if (pad)
+ bus->rxctl += (BRCMF_SDALIGN - pad);
+ bus->rxctl -= BRCMF_FIRSTREAD;
+
+ /* Copy the already-read portion over */
+ memcpy(bus->rxctl, hdr, BRCMF_FIRSTREAD);
+ if (len <= BRCMF_FIRSTREAD)
+ goto gotpkt;
+
+ /* Raise rdlen to next SDIO block to avoid tail command */
+ rdlen = len - BRCMF_FIRSTREAD;
+ if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
+ pad = bus->blocksize - (rdlen % bus->blocksize);
+ if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
+ ((len + pad) < bus->drvr->maxctl))
+ rdlen += pad;
+ } else if (rdlen % BRCMF_SDALIGN) {
+ rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
+ }
+
+ /* Satisfy length-alignment requirements */
+ if (rdlen & (ALIGNMENT - 1))
+ rdlen = roundup(rdlen, ALIGNMENT);
+
+ /* Drop if the read is too big or it exceeds our maximum */
+ if ((rdlen + BRCMF_FIRSTREAD) > bus->drvr->maxctl) {
+ brcmf_dbg(ERROR, "%d-byte control read exceeds %d-byte buffer\n",
+ rdlen, bus->drvr->maxctl);
+ bus->drvr->rx_errors++;
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ goto done;
+ }
+
+ if ((len - doff) > bus->drvr->maxctl) {
+ brcmf_dbg(ERROR, "%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
+ len, len - doff, bus->drvr->maxctl);
+ bus->drvr->rx_errors++;
+ bus->rx_toolong++;
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ goto done;
+ }
+
+ /* Read remainder of frame body into the rxctl buffer */
+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
+ bus->sdiodev->sbwad,
+ SDIO_FUNC_2,
+ F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen,
+ NULL);
+ bus->f2rxdata++;
+
+ /* Control frame failures need retransmission */
+ if (sdret < 0) {
+ brcmf_dbg(ERROR, "read %d control bytes failed: %d\n",
+ rdlen, sdret);
+ bus->rxc_errors++;
+ brcmf_sdbrcm_rxfail(bus, true, true);
+ goto done;
+ }
+
+gotpkt:
+
+#ifdef BCMDBG
+ if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
+ printk(KERN_DEBUG "RxCtrl:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len);
+ }
+#endif
+
+ /* Point to valid data and indicate its length */
+ bus->rxctl += doff;
+ bus->rxlen = len - doff;
+
+done:
+ /* Awake any waiters */
+ brcmf_sdbrcm_dcmd_resp_wake(bus);
+}
+
+/* Pad read to blocksize for efficiency */
+static void brcmf_pad(struct brcmf_bus *bus, u16 *pad, u16 *rdlen)
+{
+ if (bus->roundup && bus->blocksize && *rdlen > bus->blocksize) {
+ *pad = bus->blocksize - (*rdlen % bus->blocksize);
+ if (*pad <= bus->roundup && *pad < bus->blocksize &&
+ *rdlen + *pad + BRCMF_FIRSTREAD < MAX_RX_DATASZ)
+ *rdlen += *pad;
+ } else if (*rdlen % BRCMF_SDALIGN) {
+ *rdlen += BRCMF_SDALIGN - (*rdlen % BRCMF_SDALIGN);
+ }
+}
+
+static void
+brcmf_alloc_pkt_and_read(struct brcmf_bus *bus, u16 rdlen,
+ struct sk_buff **pkt, u8 **rxbuf)
+{
+ int sdret; /* Return code from calls */
+
+ *pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN);
+ if (*pkt == NULL)
+ return;
+
+ pkt_align(*pkt, rdlen, BRCMF_SDALIGN);
+ *rxbuf = (u8 *) ((*pkt)->data);
+ /* Read the entire frame */
+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad,
+ SDIO_FUNC_2, F2SYNC,
+ *rxbuf, rdlen, *pkt);
+ bus->f2rxdata++;
+
+ if (sdret < 0) {
+ brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n",
+ rdlen, sdret);
+ brcmu_pkt_buf_free_skb(*pkt);
+ bus->drvr->rx_errors++;
+ /* Force retry w/normal header read.
+ * Don't attempt NAK for
+ * gSPI
+ */
+ brcmf_sdbrcm_rxfail(bus, true, true);
+ *pkt = NULL;
+ }
+}
+
+/* Checks the header */
+static int
+brcmf_check_rxbuf(struct brcmf_bus *bus, struct sk_buff *pkt, u8 *rxbuf,
+ u8 rxseq, u16 nextlen, u16 *len)
+{
+ u16 check;
+ bool len_consistent; /* Result of comparing readahead len and
+ len from hw-hdr */
+
+ memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN);
+
+ /* Extract hardware header fields */
+ *len = get_unaligned_le16(bus->rxhdr);
+ check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
+
+ /* All zeros means readahead info was bad */
+ if (!(*len | check)) {
+ brcmf_dbg(INFO, "(nextlen): read zeros in HW header???\n");
+ goto fail;
+ }
+
+ /* Validate check bytes */
+ if ((u16)~(*len ^ check)) {
+ brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n",
+ nextlen, *len, check);
+ bus->rx_badhdr++;
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ goto fail;
+ }
+
+ /* Validate frame length */
+ if (*len < SDPCM_HDRLEN) {
+ brcmf_dbg(ERROR, "(nextlen): HW hdr length invalid: %d\n",
+ *len);
+ goto fail;
+ }
+
+ /* Check for consistency with readahead info */
+ len_consistent = (nextlen != (roundup(*len, 16) >> 4));
+ if (len_consistent) {
+ /* Mismatch, force retry w/normal
+ header (may be >4K) */
+ brcmf_dbg(ERROR, "(nextlen): mismatch, nextlen %d len %d rnd %d; expected rxseq %d\n",
+ nextlen, *len, roundup(*len, 16),
+ rxseq);
+ brcmf_sdbrcm_rxfail(bus, true, true);
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ brcmf_sdbrcm_pktfree2(bus, pkt);
+ return -EINVAL;
+}
+
/* Return true if there may be more frames to read */
static uint
brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
{
- struct brcmf_sdio_card *card = bus->card;
-
u16 len, check; /* Extracted hardware header fields */
u8 chan, seq, doff; /* Extracted software header fields */
u8 fcbits; /* Extracted fcbits from software header */
@@ -4003,25 +1836,11 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
uint rxleft = 0; /* Remaining number of frames allowed */
int sdret; /* Return code from calls */
u8 txmax; /* Maximum tx sequence offered */
- bool len_consistent; /* Result of comparing readahead len and
- len from hw-hdr */
u8 *rxbuf;
int ifidx = 0;
uint rxcount = 0; /* Total frames read */
-#if defined(BCMDBG) || defined(SDTEST)
- bool sdtest = false; /* To limit message spew from test mode */
-#endif
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
-#ifdef SDTEST
- /* Allow pktgen to override maxframes */
- if (bus->pktgen_count && (bus->pktgen_mode == BRCMF_PKTGEN_RECV)) {
- maxframes = bus->pktgen_count;
- sdtest = true;
- }
-#endif
+ brcmf_dbg(TRACE, "Enter\n");
/* Not finished unless we encounter no more frames indication */
*finished = false;
@@ -4033,185 +1852,39 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
/* Handle glomming separately */
if (bus->glom || bus->glomd) {
u8 cnt;
- BRCMF_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
- __func__, bus->glomd, bus->glom));
+ brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n",
+ bus->glomd, bus->glom);
cnt = brcmf_sdbrcm_rxglom(bus, rxseq);
- BRCMF_GLOM(("%s: rxglom returned %d\n", __func__, cnt));
+ brcmf_dbg(GLOM, "rxglom returned %d\n", cnt);
rxseq += cnt - 1;
rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
continue;
}
/* Try doing single read if we can */
- if (brcmf_readahead && bus->nextlen) {
+ if (bus->nextlen) {
u16 nextlen = bus->nextlen;
bus->nextlen = 0;
- if (bus->bus == SPI_BUS) {
- rdlen = len = nextlen;
- } else {
- rdlen = len = nextlen << 4;
-
- /* Pad read to blocksize for efficiency */
- if (bus->roundup && bus->blocksize
- && (rdlen > bus->blocksize)) {
- pad =
- bus->blocksize -
- (rdlen % bus->blocksize);
- if ((pad <= bus->roundup)
- && (pad < bus->blocksize)
- && ((rdlen + pad + firstread) <
- MAX_RX_DATASZ))
- rdlen += pad;
- } else if (rdlen % BRCMF_SDALIGN) {
- rdlen +=
- BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
- }
- }
+ rdlen = len = nextlen << 4;
+ brcmf_pad(bus, &pad, &rdlen);
- /* We use bus->rxctl buffer in WinXP for initial
- * control pkt receives.
- * Later we use buffer-poll for data as well
- * as control packets.
- * This is required because dhd receives full
- * frame in gSPI unlike SDIO.
+ /*
* After the frame is received we have to
* distinguish whether it is data
* or non-data frame.
*/
- /* Allocate a packet buffer */
- pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN);
- if (!pkt) {
- if (bus->bus == SPI_BUS) {
- bus->usebufpool = false;
- bus->rxctl = bus->rxbuf;
- if (brcmf_alignctl) {
- bus->rxctl += firstread;
- pad = ((unsigned long)bus->rxctl %
- BRCMF_SDALIGN);
- if (pad)
- bus->rxctl +=
- (BRCMF_SDALIGN - pad);
- bus->rxctl -= firstread;
- }
- rxbuf = bus->rxctl;
- /* Read the entire frame */
- sdret = brcmf_sdcard_recv_buf(card,
- brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2, F2SYNC,
- rxbuf, rdlen,
- NULL, NULL, NULL);
- bus->f2rxdata++;
-
- /* Control frame failures need
- retransmission */
- if (sdret < 0) {
- BRCMF_ERROR(("%s: read %d "
- "control bytes "
- "failed: %d\n",
- __func__,
- rdlen, sdret));
- /* dhd.rx_ctlerrs is higher */
- bus->rxc_errors++;
- brcmf_sdbrcm_rxfail(bus, true,
- (bus->bus ==
- SPI_BUS) ? false
- : true);
- continue;
- }
- } else {
- /* Give up on data,
- request rtx of events */
- BRCMF_ERROR(("%s (nextlen): "
- "brcmu_pkt_buf_get_skb "
- "failed:"
- " len %d rdlen %d expected"
- " rxseq %d\n", __func__,
- len, rdlen, rxseq));
- continue;
- }
- } else {
- if (bus->bus == SPI_BUS)
- bus->usebufpool = true;
-
- PKTALIGN(pkt, rdlen, BRCMF_SDALIGN);
- rxbuf = (u8 *) (pkt->data);
- /* Read the entire frame */
- sdret = brcmf_sdcard_recv_buf(card,
- brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2, F2SYNC,
- rxbuf, rdlen,
- pkt, NULL, NULL);
- bus->f2rxdata++;
-
- if (sdret < 0) {
- BRCMF_ERROR(("%s (nextlen): read %d"
- " bytes failed: %d\n",
- __func__, rdlen, sdret));
- brcmu_pkt_buf_free_skb(pkt);
- bus->drvr->rx_errors++;
- /* Force retry w/normal header read.
- * Don't attempt NAK for
- * gSPI
- */
- brcmf_sdbrcm_rxfail(bus, true,
- (bus->bus ==
- SPI_BUS) ? false :
- true);
- continue;
- }
- }
-
- /* Now check the header */
- memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN);
-
- /* Extract hardware header fields */
- len = get_unaligned_le16(bus->rxhdr);
- check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
-
- /* All zeros means readahead info was bad */
- if (!(len | check)) {
- BRCMF_INFO(("%s (nextlen): read zeros in HW "
- "header???\n", __func__));
- brcmf_sdbrcm_pktfree2(bus, pkt);
- continue;
- }
-
- /* Validate check bytes */
- if ((u16)~(len ^ check)) {
- BRCMF_ERROR(("%s (nextlen): HW hdr error:"
- " nextlen/len/check"
- " 0x%04x/0x%04x/0x%04x\n",
- __func__, nextlen, len, check));
- bus->rx_badhdr++;
- brcmf_sdbrcm_rxfail(bus, false, false);
- brcmf_sdbrcm_pktfree2(bus, pkt);
+ brcmf_alloc_pkt_and_read(bus, rdlen, &pkt, &rxbuf);
+ if (pkt == NULL) {
+ /* Give up on data, request rtx of events */
+ brcmf_dbg(ERROR, "(nextlen): brcmf_alloc_pkt_and_read failed: len %d rdlen %d expected rxseq %d\n",
+ len, rdlen, rxseq);
continue;
}
- /* Validate frame length */
- if (len < SDPCM_HDRLEN) {
- BRCMF_ERROR(("%s (nextlen): HW hdr length "
- "invalid: %d\n", __func__, len));
- brcmf_sdbrcm_pktfree2(bus, pkt);
+ if (brcmf_check_rxbuf(bus, pkt, rxbuf, rxseq, nextlen,
+ &len) < 0)
continue;
- }
-
- /* Check for consistency withreadahead info */
- len_consistent = (nextlen != (roundup(len, 16) >> 4));
- if (len_consistent) {
- /* Mismatch, force retry w/normal
- header (may be >4K) */
- BRCMF_ERROR(("%s (nextlen): mismatch, "
- "nextlen %d len %d rnd %d; "
- "expected rxseq %d\n",
- __func__, nextlen,
- len, roundup(len, 16), rxseq));
- brcmf_sdbrcm_rxfail(bus, true,
- bus->bus != SPI_BUS);
- brcmf_sdbrcm_pktfree2(bus, pkt);
- continue;
- }
/* Extract software header fields */
chan = SDPCM_PACKET_CHANNEL(
@@ -4227,9 +1900,8 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
bus->rxhdr[SDPCM_FRAMETAG_LEN +
SDPCM_NEXTLEN_OFFSET];
if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
- BRCMF_INFO(("%s (nextlen): got frame w/nextlen"
- " too large (%d), seq %d\n",
- __func__, bus->nextlen, seq));
+ brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n",
+ bus->nextlen, seq);
bus->nextlen = 0;
}
@@ -4252,17 +1924,16 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
/* Check and update sequence number */
if (rxseq != seq) {
- BRCMF_INFO(("%s (nextlen): rx_seq %d, expected "
- "%d\n", __func__, seq, rxseq));
+ brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n",
+ seq, rxseq);
bus->rx_badseq++;
rxseq = seq;
}
/* Check window for sanity */
if ((u8) (txmax - bus->tx_seq) > 0x40) {
- BRCMF_ERROR(("%s: got unlikely tx max %d with "
- "tx_seq %d\n",
- __func__, txmax, bus->tx_seq));
+ brcmf_dbg(ERROR, "got unlikely tx max %d with tx_seq %d\n",
+ txmax, bus->tx_seq);
txmax = bus->tx_seq + 2;
}
bus->tx_max = txmax;
@@ -4280,34 +1951,19 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
#endif
if (chan == SDPCM_CONTROL_CHANNEL) {
- if (bus->bus == SPI_BUS) {
- brcmf_sdbrcm_read_control(bus, rxbuf,
- len, doff);
- } else {
- BRCMF_ERROR(("%s (nextlen): readahead"
- " on control packet %d?\n",
- __func__, seq));
- /* Force retry w/normal header read */
- bus->nextlen = 0;
- brcmf_sdbrcm_rxfail(bus, false, true);
- }
+ brcmf_dbg(ERROR, "(nextlen): readahead on control packet %d?\n",
+ seq);
+ /* Force retry w/normal header read */
+ bus->nextlen = 0;
+ brcmf_sdbrcm_rxfail(bus, false, true);
brcmf_sdbrcm_pktfree2(bus, pkt);
continue;
}
- if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
- BRCMF_ERROR(("Received %d bytes on %d channel."
- " Running out of " "rx pktbuf's or"
- " not yet malloced.\n",
- len, chan));
- continue;
- }
-
/* Validate data offset */
if ((doff < SDPCM_HDRLEN) || (doff > len)) {
- BRCMF_ERROR(("%s (nextlen): bad data offset %d:"
- " HW len %d min %d\n", __func__,
- doff, len, SDPCM_HDRLEN));
+ brcmf_dbg(ERROR, "(nextlen): bad data offset %d: HW len %d min %d\n",
+ doff, len, SDPCM_HDRLEN);
brcmf_sdbrcm_rxfail(bus, false, false);
brcmf_sdbrcm_pktfree2(bus, pkt);
continue;
@@ -4316,20 +1972,15 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
/* All done with this one -- now deliver the packet */
goto deliver;
}
- /* gSPI frames should not be handled in fractions */
- if (bus->bus == SPI_BUS)
- break;
/* Read frame header (hardware and software) */
- sdret = brcmf_sdcard_recv_buf(card,
- brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2, F2SYNC, bus->rxhdr, firstread,
- NULL, NULL, NULL);
+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad,
+ SDIO_FUNC_2, F2SYNC, bus->rxhdr,
+ BRCMF_FIRSTREAD, NULL);
bus->f2rxhdrs++;
if (sdret < 0) {
- BRCMF_ERROR(("%s: RXHEADER FAILED: %d\n", __func__,
- sdret));
+ brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret);
bus->rx_hdrfail++;
brcmf_sdbrcm_rxfail(bus, true, true);
continue;
@@ -4354,8 +2005,8 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
/* Validate check bytes */
if ((u16) ~(len ^ check)) {
- BRCMF_ERROR(("%s: HW hdr err: len/check "
- "0x%04x/0x%04x\n", __func__, len, check));
+ brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n",
+ len, check);
bus->rx_badhdr++;
brcmf_sdbrcm_rxfail(bus, false, false);
continue;
@@ -4363,8 +2014,7 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
/* Validate frame length */
if (len < SDPCM_HDRLEN) {
- BRCMF_ERROR(("%s: HW hdr length invalid: %d\n",
- __func__, len));
+ brcmf_dbg(ERROR, "HW hdr length invalid: %d\n", len);
continue;
}
@@ -4376,9 +2026,8 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
/* Validate data offset */
if ((doff < SDPCM_HDRLEN) || (doff > len)) {
- BRCMF_ERROR(("%s: Bad data offset %d: HW len %d,"
- " min %d seq %d\n", __func__, doff,
- len, SDPCM_HDRLEN, seq));
+ brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n",
+ doff, len, SDPCM_HDRLEN, seq);
bus->rx_badhdr++;
brcmf_sdbrcm_rxfail(bus, false, false);
continue;
@@ -4388,9 +2037,8 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
bus->nextlen =
bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
- BRCMF_INFO(("%s (nextlen): got frame w/nextlen too"
- " large (%d), seq %d\n",
- __func__, bus->nextlen, seq));
+ brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n",
+ bus->nextlen, seq);
bus->nextlen = 0;
}
@@ -4410,16 +2058,15 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
/* Check and update sequence number */
if (rxseq != seq) {
- BRCMF_INFO(("%s: rx_seq %d, expected %d\n", __func__,
- seq, rxseq));
+ brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq);
bus->rx_badseq++;
rxseq = seq;
}
/* Check window for sanity */
if ((u8) (txmax - bus->tx_seq) > 0x40) {
- BRCMF_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
- __func__, txmax, bus->tx_seq));
+ brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n",
+ txmax, bus->tx_seq);
txmax = bus->tx_seq + 2;
}
bus->tx_max = txmax;
@@ -4435,61 +2082,59 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
SDPCM_GLOM_CHANNEL */
/* Length to read */
- rdlen = (len > firstread) ? (len - firstread) : 0;
+ rdlen = (len > BRCMF_FIRSTREAD) ? (len - BRCMF_FIRSTREAD) : 0;
/* May pad read to blocksize for efficiency */
if (bus->roundup && bus->blocksize &&
(rdlen > bus->blocksize)) {
pad = bus->blocksize - (rdlen % bus->blocksize);
if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
- ((rdlen + pad + firstread) < MAX_RX_DATASZ))
+ ((rdlen + pad + BRCMF_FIRSTREAD) < MAX_RX_DATASZ))
rdlen += pad;
} else if (rdlen % BRCMF_SDALIGN) {
rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
}
/* Satisfy length-alignment requirements */
- if (forcealign && (rdlen & (ALIGNMENT - 1)))
+ if (rdlen & (ALIGNMENT - 1))
rdlen = roundup(rdlen, ALIGNMENT);
- if ((rdlen + firstread) > MAX_RX_DATASZ) {
+ if ((rdlen + BRCMF_FIRSTREAD) > MAX_RX_DATASZ) {
/* Too long -- skip this frame */
- BRCMF_ERROR(("%s: too long: len %d rdlen %d\n",
- __func__, len, rdlen));
+ brcmf_dbg(ERROR, "too long: len %d rdlen %d\n",
+ len, rdlen);
bus->drvr->rx_errors++;
bus->rx_toolong++;
brcmf_sdbrcm_rxfail(bus, false, false);
continue;
}
- pkt = brcmu_pkt_buf_get_skb(rdlen + firstread + BRCMF_SDALIGN);
+ pkt = brcmu_pkt_buf_get_skb(rdlen +
+ BRCMF_FIRSTREAD + BRCMF_SDALIGN);
if (!pkt) {
/* Give up on data, request rtx of events */
- BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed:"
- " rdlen %d chan %d\n", __func__, rdlen,
- chan));
+ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: rdlen %d chan %d\n",
+ rdlen, chan);
bus->drvr->rx_dropped++;
brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan));
continue;
}
/* Leave room for what we already read, and align remainder */
- skb_pull(pkt, firstread);
- PKTALIGN(pkt, rdlen, BRCMF_SDALIGN);
+ skb_pull(pkt, BRCMF_FIRSTREAD);
+ pkt_align(pkt, rdlen, BRCMF_SDALIGN);
/* Read the remaining frame data */
- sdret = brcmf_sdcard_recv_buf(card,
- brcmf_sdcard_cur_sbwad(card),
+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)),
- rdlen, pkt, NULL, NULL);
+ rdlen, pkt);
bus->f2rxdata++;
if (sdret < 0) {
- BRCMF_ERROR(("%s: read %d %s bytes failed: %d\n",
- __func__, rdlen,
- ((chan == SDPCM_EVENT_CHANNEL) ? "event"
- : ((chan == SDPCM_DATA_CHANNEL) ? "data"
- : "test")), sdret));
+ brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen,
+ ((chan == SDPCM_EVENT_CHANNEL) ? "event"
+ : ((chan == SDPCM_DATA_CHANNEL) ? "data"
+ : "test")), sdret);
brcmu_pkt_buf_free_skb(pkt);
bus->drvr->rx_errors++;
brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan));
@@ -4497,8 +2142,8 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
}
/* Copy the already-read portion */
- skb_push(pkt, firstread);
- memcpy(pkt->data, bus->rxhdr, firstread);
+ skb_push(pkt, BRCMF_FIRSTREAD);
+ memcpy(pkt->data, bus->rxhdr, BRCMF_FIRSTREAD);
#ifdef BCMDBG
if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
@@ -4512,8 +2157,8 @@ deliver:
/* Save superframe descriptor and allocate packet frame */
if (chan == SDPCM_GLOM_CHANNEL) {
if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
- BRCMF_GLOM(("%s: glom descriptor, %d bytes:\n",
- __func__, len));
+ brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n",
+ len);
#ifdef BCMDBG
if (BRCMF_GLOM_ON()) {
printk(KERN_DEBUG "Glom Data:\n");
@@ -4526,8 +2171,8 @@ deliver:
skb_pull(pkt, SDPCM_HDRLEN);
bus->glomd = pkt;
} else {
- BRCMF_ERROR(("%s: glom superframe w/o "
- "descriptor!\n", __func__));
+ brcmf_dbg(ERROR, "%s: glom superframe w/o "
+ "descriptor!\n", __func__);
brcmf_sdbrcm_rxfail(bus, false, false);
}
continue;
@@ -4537,38 +2182,30 @@ deliver:
__skb_trim(pkt, len);
skb_pull(pkt, doff);
-#ifdef SDTEST
- /* Test channel packets are processed separately */
- if (chan == SDPCM_TEST_CHANNEL) {
- brcmf_sdbrcm_checkdied(bus, pkt, seq);
- continue;
- }
-#endif /* SDTEST */
-
if (pkt->len == 0) {
brcmu_pkt_buf_free_skb(pkt);
continue;
} else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pkt) != 0) {
- BRCMF_ERROR(("%s: rx protocol error\n", __func__));
+ brcmf_dbg(ERROR, "rx protocol error\n");
brcmu_pkt_buf_free_skb(pkt);
bus->drvr->rx_errors++;
continue;
}
/* Unlock during rx call */
- brcmf_sdbrcm_sdunlock(bus);
+ up(&bus->sdsem);
brcmf_rx_frame(bus->drvr, ifidx, pkt, 1);
- brcmf_sdbrcm_sdlock(bus);
+ down(&bus->sdsem);
}
rxcount = maxframes - rxleft;
#ifdef BCMDBG
/* Message if we hit the limit */
- if (!rxleft && !sdtest)
- BRCMF_DATA(("%s: hit rx limit of %d frames\n", __func__,
- maxframes));
+ if (!rxleft)
+ brcmf_dbg(DATA, "hit rx limit of %d frames\n",
+ maxframes);
else
#endif /* BCMDBG */
- BRCMF_DATA(("%s: processed %d frames\n", __func__, rxcount));
+ brcmf_dbg(DATA, "processed %d frames\n", rxcount);
/* Back off rxseq if awaiting rtx, update rx_seq */
if (bus->rxskip)
rxseq--;
@@ -4577,100 +2214,243 @@ deliver:
return rxcount;
}
-static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus)
+static int
+brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags,
+ u8 *buf, uint nbytes, struct sk_buff *pkt)
{
- u32 intstatus = 0;
- u32 hmb_data;
- u8 fcbits;
- uint retries = 0;
+ return brcmf_sdcard_send_buf
+ (bus->sdiodev, addr, fn, flags, buf, nbytes, pkt);
+}
- BRCMF_TRACE(("%s: Enter\n", __func__));
+static void
+brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar)
+{
+ up(&bus->sdsem);
+ wait_event_interruptible_timeout(bus->ctrl_wait,
+ (*lockvar == false), HZ * 2);
+ down(&bus->sdsem);
+ return;
+}
- /* Read mailbox data and ack that we did so */
- r_sdreg32(bus, &hmb_data,
- offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries);
+static void
+brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus)
+{
+ if (waitqueue_active(&bus->ctrl_wait))
+ wake_up_interruptible(&bus->ctrl_wait);
+ return;
+}
- if (retries <= retry_limit)
- w_sdreg32(bus, SMB_INT_ACK,
- offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
- bus->f1regdata += 2;
+/* Writes a HW/SW header into the packet and sends it. */
+/* Assumes: (a) header space already there, (b) caller holds lock */
+static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt,
+ uint chan, bool free_pkt)
+{
+ int ret;
+ u8 *frame;
+ u16 len, pad = 0;
+ u32 swheader;
+ struct sk_buff *new;
+ int i;
- /* Dongle recomposed rx frames, accept them again */
- if (hmb_data & HMB_DATA_NAKHANDLED) {
- BRCMF_INFO(("Dongle reports NAK handled, expect rtx of %d\n",
- bus->rx_seq));
- if (!bus->rxskip)
- BRCMF_ERROR(("%s: unexpected NAKHANDLED!\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
- bus->rxskip = false;
- intstatus |= I_HMB_FRAME_IND;
+ frame = (u8 *) (pkt->data);
+
+ /* Add alignment padding, allocate new packet if needed */
+ pad = ((unsigned long)frame % BRCMF_SDALIGN);
+ if (pad) {
+ if (skb_headroom(pkt) < pad) {
+ brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n",
+ skb_headroom(pkt), pad);
+ bus->drvr->tx_realloc++;
+ new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN);
+ if (!new) {
+ brcmf_dbg(ERROR, "couldn't allocate new %d-byte packet\n",
+ pkt->len + BRCMF_SDALIGN);
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ pkt_align(new, pkt->len, BRCMF_SDALIGN);
+ memcpy(new->data, pkt->data, pkt->len);
+ if (free_pkt)
+ brcmu_pkt_buf_free_skb(pkt);
+ /* free the pkt if canned one is not used */
+ free_pkt = true;
+ pkt = new;
+ frame = (u8 *) (pkt->data);
+ /* precondition: (frame % BRCMF_SDALIGN) == 0) */
+ pad = 0;
+ } else {
+ skb_push(pkt, pad);
+ frame = (u8 *) (pkt->data);
+ /* precondition: pad + SDPCM_HDRLEN <= pkt->len */
+ memset(frame, 0, pad + SDPCM_HDRLEN);
+ }
}
+ /* precondition: pad < BRCMF_SDALIGN */
- /*
- * DEVREADY does not occur with gSPI.
- */
- if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
- bus->sdpcm_ver =
- (hmb_data & HMB_DATA_VERSION_MASK) >>
- HMB_DATA_VERSION_SHIFT;
- if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
- BRCMF_ERROR(("Version mismatch, dongle reports %d, "
- "expecting %d\n",
- bus->sdpcm_ver, SDPCM_PROT_VERSION));
- else
- BRCMF_INFO(("Dongle ready, protocol version %d\n",
- bus->sdpcm_ver));
+ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
+ len = (u16) (pkt->len);
+ *(__le16 *) frame = cpu_to_le16(len);
+ *(((__le16 *) frame) + 1) = cpu_to_le16(~len);
+
+ /* Software tag: channel, sequence number, data offset */
+ swheader =
+ ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
+ (((pad +
+ SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
+
+ put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
+ put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+
+#ifdef BCMDBG
+ tx_packets[pkt->priority]++;
+ if (BRCMF_BYTES_ON() &&
+ (((BRCMF_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
+ (BRCMF_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
+ printk(KERN_DEBUG "Tx Frame:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len);
+ } else if (BRCMF_HDRS_ON()) {
+ printk(KERN_DEBUG "TxHdr:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ frame, min_t(u16, len, 16));
}
+#endif
- /*
- * Flow Control has been moved into the RX headers and this out of band
- * method isn't used any more.
- * remaining backward compatible with older dongles.
- */
- if (hmb_data & HMB_DATA_FC) {
- fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >>
- HMB_DATA_FCDATA_SHIFT;
+ /* Raise len to next SDIO block to eliminate tail command */
+ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
+ u16 pad = bus->blocksize - (len % bus->blocksize);
+ if ((pad <= bus->roundup) && (pad < bus->blocksize))
+ len += pad;
+ } else if (len % BRCMF_SDALIGN) {
+ len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
+ }
- if (fcbits & ~bus->flowcontrol)
- bus->fc_xoff++;
+ /* Some controllers have trouble with odd bytes -- round to even */
+ if (len & (ALIGNMENT - 1))
+ len = roundup(len, ALIGNMENT);
- if (bus->flowcontrol & ~fcbits)
- bus->fc_xon++;
+ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad,
+ SDIO_FUNC_2, F2SYNC, frame,
+ len, pkt);
+ bus->f2txdata++;
+
+ if (ret < 0) {
+ /* On failure, abort the command and terminate the frame */
+ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
+ ret);
+ bus->tx_sderrs++;
+
+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
+ NULL);
+ bus->f1regdata++;
+
+ for (i = 0; i < 3; i++) {
+ u8 hi, lo;
+ hi = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
+ SBSDIO_FUNC1_WFRAMEBCHI,
+ NULL);
+ lo = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
+ SBSDIO_FUNC1_WFRAMEBCLO,
+ NULL);
+ bus->f1regdata += 2;
+ if ((hi == 0) && (lo == 0))
+ break;
+ }
- bus->fc_rcvd++;
- bus->flowcontrol = fcbits;
}
+ if (ret == 0)
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
- /* Shouldn't be any others */
- if (hmb_data & ~(HMB_DATA_DEVREADY |
- HMB_DATA_NAKHANDLED |
- HMB_DATA_FC |
- HMB_DATA_FWREADY |
- HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) {
- BRCMF_ERROR(("Unknown mailbox data content: 0x%02x\n",
- hmb_data));
+done:
+ /* restore pkt buffer pointer before calling tx complete routine */
+ skb_pull(pkt, SDPCM_HDRLEN + pad);
+ up(&bus->sdsem);
+ brcmf_txcomplete(bus->drvr, pkt, ret != 0);
+ down(&bus->sdsem);
+
+ if (free_pkt)
+ brcmu_pkt_buf_free_skb(pkt);
+
+ return ret;
+}
+
+static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes)
+{
+ struct sk_buff *pkt;
+ u32 intstatus = 0;
+ uint retries = 0;
+ int ret = 0, prec_out;
+ uint cnt = 0;
+ uint datalen;
+ u8 tx_prec_map;
+
+ struct brcmf_pub *drvr = bus->drvr;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ tx_prec_map = ~bus->flowcontrol;
+
+ /* Send frames until the limit or some other event */
+ for (cnt = 0; (cnt < maxframes) && data_ok(bus); cnt++) {
+ spin_lock_bh(&bus->txqlock);
+ pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
+ if (pkt == NULL) {
+ spin_unlock_bh(&bus->txqlock);
+ break;
+ }
+ spin_unlock_bh(&bus->txqlock);
+ datalen = pkt->len - SDPCM_HDRLEN;
+
+ ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
+ if (ret)
+ bus->drvr->tx_errors++;
+ else
+ bus->drvr->dstats.tx_bytes += datalen;
+
+ /* In poll mode, need to check for other events */
+ if (!bus->intr && cnt) {
+ /* Check device status, signal pending interrupt */
+ r_sdreg32(bus, &intstatus,
+ offsetof(struct sdpcmd_regs, intstatus),
+ &retries);
+ bus->f2txdata++;
+ if (brcmf_sdcard_regfail(bus->sdiodev))
+ break;
+ if (intstatus & bus->hostintmask)
+ bus->ipend = true;
+ }
}
- return intstatus;
+ /* Deflow-control stack if needed */
+ if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) &&
+ drvr->txoff && (pktq_len(&bus->txq) < TXLOW))
+ brcmf_txflowcontrol(drvr, 0, OFF);
+
+ return cnt;
}
static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
{
- struct brcmf_sdio_card *card = bus->card;
u32 intstatus, newstatus = 0;
uint retries = 0;
- uint rxlimit = brcmf_rxbound; /* Rx frames to read before resched */
- uint txlimit = brcmf_txbound; /* Tx frames to send before resched */
+ uint rxlimit = bus->rxbound; /* Rx frames to read before resched */
+ uint txlimit = bus->txbound; /* Tx frames to send before resched */
uint framecnt = 0; /* Temporary counter of tx/rx frames */
bool rxdone = true; /* Flag for no more read data */
bool resched = false; /* Flag indicating resched wanted */
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
/* Start with leftover status bits */
intstatus = bus->intstatus;
- brcmf_sdbrcm_sdlock(bus);
+ down(&bus->sdsem);
/* If waiting for HTAVAIL, check status */
if (bus->clkstate == CLK_PENDING) {
@@ -4679,41 +2459,41 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
#ifdef BCMDBG
/* Check for inconsistent device control */
- devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_DEVICE_CTL, &err);
if (err) {
- BRCMF_ERROR(("%s: error reading DEVCTL: %d\n",
- __func__, err));
+ brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err);
bus->drvr->busstate = BRCMF_BUS_DOWN;
}
#endif /* BCMDBG */
/* Read CSR, if clock on switch to AVAIL, else ignore */
- clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (err) {
- BRCMF_ERROR(("%s: error reading CSR: %d\n", __func__,
- err));
+ brcmf_dbg(ERROR, "error reading CSR: %d\n",
+ err);
bus->drvr->busstate = BRCMF_BUS_DOWN;
}
- BRCMF_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
- devctl, clkctl));
+ brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
+ devctl, clkctl);
if (SBSDIO_HTAV(clkctl)) {
- devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
SBSDIO_DEVICE_CTL, &err);
if (err) {
- BRCMF_ERROR(("%s: error reading DEVCTL: %d\n",
- __func__, err));
+ brcmf_dbg(ERROR, "error reading DEVCTL: %d\n",
+ err);
bus->drvr->busstate = BRCMF_BUS_DOWN;
}
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_DEVICE_CTL, devctl, &err);
if (err) {
- BRCMF_ERROR(("%s: error writing DEVCTL: %d\n",
- __func__, err));
+ brcmf_dbg(ERROR, "error writing DEVCTL: %d\n",
+ err);
bus->drvr->busstate = BRCMF_BUS_DOWN;
}
bus->clkstate = CLK_AVAIL;
@@ -4722,7 +2502,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
}
}
- BUS_WAKE(bus);
+ bus_wake(bus);
/* Make sure backplane clock is on */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
@@ -4735,7 +2515,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
r_sdreg32(bus, &newstatus,
offsetof(struct sdpcmd_regs, intstatus), &retries);
bus->f1regdata++;
- if (brcmf_sdcard_regfail(bus->card))
+ if (brcmf_sdcard_regfail(bus->sdiodev))
newstatus = 0;
newstatus &= bus->hostintmask;
bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
@@ -4776,23 +2556,23 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
/* Generally don't ask for these, can get CRC errors... */
if (intstatus & I_WR_OOSYNC) {
- BRCMF_ERROR(("Dongle reports WR_OOSYNC\n"));
+ brcmf_dbg(ERROR, "Dongle reports WR_OOSYNC\n");
intstatus &= ~I_WR_OOSYNC;
}
if (intstatus & I_RD_OOSYNC) {
- BRCMF_ERROR(("Dongle reports RD_OOSYNC\n"));
+ brcmf_dbg(ERROR, "Dongle reports RD_OOSYNC\n");
intstatus &= ~I_RD_OOSYNC;
}
if (intstatus & I_SBINT) {
- BRCMF_ERROR(("Dongle reports SBINT\n"));
+ brcmf_dbg(ERROR, "Dongle reports SBINT\n");
intstatus &= ~I_SBINT;
}
/* Would be active due to wake-wlan in gSPI */
if (intstatus & I_CHIPACTIVE) {
- BRCMF_INFO(("Dongle reports CHIPACTIVE\n"));
+ brcmf_dbg(INFO, "Dongle reports CHIPACTIVE\n");
intstatus &= ~I_CHIPACTIVE;
}
@@ -4812,45 +2592,36 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
bus->intstatus = intstatus;
clkwait:
- /* Re-enable interrupts to detect new device events (mailbox, rx frame)
- * or clock availability. (Allows tx loop to check ipend if desired.)
- * (Unless register access seems hosed, as we may not be able to ACK...)
- */
- if (bus->intr && bus->intdis && !brcmf_sdcard_regfail(card)) {
- BRCMF_INTR(("%s: enable SDIO interrupts, rxdone %d"
- " framecnt %d\n", __func__, rxdone, framecnt));
- bus->intdis = false;
- brcmf_sdcard_intr_enable(card);
- }
-
- if (DATAOK(bus) && bus->ctrl_frame_stat &&
+ if (data_ok(bus) && bus->ctrl_frame_stat &&
(bus->clkstate == CLK_AVAIL)) {
int ret, i;
- ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card),
+ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf,
- (u32) bus->ctrl_frame_len, NULL, NULL, NULL);
+ (u32) bus->ctrl_frame_len, NULL);
if (ret < 0) {
/* On failure, abort the command and
terminate the frame */
- BRCMF_INFO(("%s: sdio error %d, abort command and "
- "terminate frame.\n", __func__, ret));
+ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
+ ret);
bus->tx_sderrs++;
- brcmf_sdcard_abort(card, SDIO_FUNC_2);
+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
NULL);
bus->f1regdata++;
for (i = 0; i < 3; i++) {
u8 hi, lo;
- hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ hi = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
SBSDIO_FUNC1_WFRAMEBCHI,
NULL);
- lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+ lo = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
SBSDIO_FUNC1_WFRAMEBCLO,
NULL);
bus->f1regdata += 2;
@@ -4862,15 +2633,15 @@ clkwait:
if (ret == 0)
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
- BRCMF_INFO(("Return_dpc value is : %d\n", ret));
+ brcmf_dbg(INFO, "Return_dpc value is : %d\n", ret);
bus->ctrl_frame_stat = false;
brcmf_sdbrcm_wait_event_wakeup(bus);
}
/* Send queued frames (limit 1 if rx may still be pending) */
else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
- && DATAOK(bus)) {
- framecnt = rxdone ? txlimit : min(txlimit, brcmf_txminmax);
+ && data_ok(bus)) {
+ framecnt = rxdone ? txlimit : min(txlimit, bus->txminmax);
framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt);
txlimit -= framecnt;
}
@@ -4880,19 +2651,17 @@ clkwait:
/* On failed register access, all bets are off:
no resched or interrupts */
if ((bus->drvr->busstate == BRCMF_BUS_DOWN) ||
- brcmf_sdcard_regfail(card)) {
- BRCMF_ERROR(("%s: failed backplane access over SDIO, halting "
- "operation %d\n", __func__,
- brcmf_sdcard_regfail(card)));
+ brcmf_sdcard_regfail(bus->sdiodev)) {
+ brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation %d\n",
+ brcmf_sdcard_regfail(bus->sdiodev));
bus->drvr->busstate = BRCMF_BUS_DOWN;
bus->intstatus = 0;
} else if (bus->clkstate == CLK_PENDING) {
- BRCMF_INFO(("%s: rescheduled due to CLK_PENDING awaiting "
- "I_CHIPACTIVE interrupt\n", __func__));
+ brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n");
resched = true;
} else if (bus->intstatus || bus->ipend ||
(!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)
- && DATAOK(bus)) || PKT_AVAILABLE()) {
+ && data_ok(bus)) || PKT_AVAILABLE()) {
resched = true;
}
@@ -4905,1010 +2674,733 @@ clkwait:
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
}
- brcmf_sdbrcm_sdunlock(bus);
+ up(&bus->sdsem);
return resched;
}
-void brcmf_sdbrcm_isr(void *arg)
+static int brcmf_sdbrcm_dpc_thread(void *data)
{
- struct brcmf_bus *bus = (struct brcmf_bus *) arg;
- struct brcmf_sdio_card *card;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (!bus) {
- BRCMF_ERROR(("%s : bus is null pointer , exit\n", __func__));
- return;
- }
- card = bus->card;
-
- if (bus->drvr->busstate == BRCMF_BUS_DOWN) {
- BRCMF_ERROR(("%s : bus is down. we have nothing to do\n",
- __func__));
- return;
- }
- /* Count the interrupt call */
- bus->intrcount++;
- bus->ipend = true;
+ struct brcmf_bus *bus = (struct brcmf_bus *) data;
- /* Shouldn't get this interrupt if we're sleeping? */
- if (bus->sleeping) {
- BRCMF_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
- return;
+ allow_signal(SIGTERM);
+ /* Run until signal received */
+ while (1) {
+ if (kthread_should_stop())
+ break;
+ if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
+ /* Call bus dpc unless it indicated down
+ (then clean stop) */
+ if (bus->drvr->busstate != BRCMF_BUS_DOWN) {
+ if (brcmf_sdbrcm_dpc(bus))
+ complete(&bus->dpc_wait);
+ } else {
+ /* after stopping the bus, exit thread */
+ brcmf_sdbrcm_bus_stop(bus);
+ bus->dpc_tsk = NULL;
+ break;
+ }
+ } else
+ break;
}
-
- /* Disable additional interrupts (is this needed now)? */
- if (bus->intr)
- BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
- else
- BRCMF_ERROR(("brcmf_sdbrcm_isr() w/o interrupt configured!\n"));
-
- brcmf_sdcard_intr_disable(card);
- bus->intdis = true;
-
-#if defined(SDIO_ISR_THREAD)
- BRCMF_TRACE(("Calling brcmf_sdbrcm_dpc() from %s\n", __func__));
- while (brcmf_sdbrcm_dpc(bus))
- ;
-#else
- bus->dpc_sched = true;
- brcmf_sdbrcm_sched_dpc(bus);
-#endif
-
+ return 0;
}
-#ifdef SDTEST
-static void brcmf_sdbrcm_pktgen_init(struct brcmf_bus *bus)
+int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt)
{
- /* Default to specified length, or full range */
- if (brcmf_pktgen_len) {
- bus->pktgen_maxlen = min(brcmf_pktgen_len,
- BRCMF_MAX_PKTGEN_LEN);
- bus->pktgen_minlen = bus->pktgen_maxlen;
- } else {
- bus->pktgen_maxlen = BRCMF_MAX_PKTGEN_LEN;
- bus->pktgen_minlen = 0;
- }
- bus->pktgen_len = (u16) bus->pktgen_minlen;
+ int ret = -EBADE;
+ uint datalen, prec;
- /* Default to per-watchdog burst with 10s print time */
- bus->pktgen_freq = 1;
- bus->pktgen_print = 10000 / brcmf_watchdog_ms;
- bus->pktgen_count = (brcmf_pktgen * brcmf_watchdog_ms + 999) / 1000;
+ brcmf_dbg(TRACE, "Enter\n");
- /* Default to echo mode */
- bus->pktgen_mode = BRCMF_PKTGEN_ECHO;
- bus->pktgen_stop = 1;
-}
+ datalen = pkt->len;
-static void brcmf_sdbrcm_pktgen(struct brcmf_bus *bus)
-{
- struct sk_buff *pkt;
- u8 *data;
- uint pktcount;
- uint fillbyte;
- u16 len;
+ /* Add space for the header */
+ skb_push(pkt, SDPCM_HDRLEN);
+ /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */
- /* Display current count if appropriate */
- if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
- bus->pktgen_ptick = 0;
- printk(KERN_DEBUG "%s: send attempts %d rcvd %d\n",
- __func__, bus->pktgen_sent, bus->pktgen_rcvd);
- }
+ prec = prio2prec((pkt->priority & PRIOMASK));
- /* For recv mode, just make sure dongle has started sending */
- if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) {
- if (!bus->pktgen_rcvd)
- brcmf_sdbrcm_sdtest_set(bus, true);
- return;
+ /* Check for existing queue, current flow-control,
+ pending event, or pending clock */
+ brcmf_dbg(TRACE, "deferring pktq len %d\n", pktq_len(&bus->txq));
+ bus->fcqueued++;
+
+ /* Priority based enq */
+ spin_lock_bh(&bus->txqlock);
+ if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) {
+ skb_pull(pkt, SDPCM_HDRLEN);
+ brcmf_txcomplete(bus->drvr, pkt, false);
+ brcmu_pkt_buf_free_skb(pkt);
+ brcmf_dbg(ERROR, "out of bus->txq !!!\n");
+ ret = -ENOSR;
+ } else {
+ ret = 0;
}
+ spin_unlock_bh(&bus->txqlock);
- /* Otherwise, generate or request the specified number of packets */
- for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
- /* Stop if total has been reached */
- if (bus->pktgen_total
- && (bus->pktgen_sent >= bus->pktgen_total)) {
- bus->pktgen_count = 0;
- break;
- }
-
- /* Allocate an appropriate-sized packet */
- len = bus->pktgen_len;
- pkt = brcmu_pkt_buf_get_skb(
- len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN,
- true);
- if (!pkt) {
- BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n",
- __func__));
- break;
- }
- PKTALIGN(pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN),
- BRCMF_SDALIGN);
- data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
-
- /* Write test header cmd and extra based on mode */
- switch (bus->pktgen_mode) {
- case BRCMF_PKTGEN_ECHO:
- *data++ = SDPCM_TEST_ECHOREQ;
- *data++ = (u8) bus->pktgen_sent;
- break;
-
- case BRCMF_PKTGEN_SEND:
- *data++ = SDPCM_TEST_DISCARD;
- *data++ = (u8) bus->pktgen_sent;
- break;
-
- case BRCMF_PKTGEN_RXBURST:
- *data++ = SDPCM_TEST_BURST;
- *data++ = (u8) bus->pktgen_count;
- break;
-
- default:
- BRCMF_ERROR(("Unrecognized pktgen mode %d\n",
- bus->pktgen_mode));
- brcmu_pkt_buf_free_skb(pkt, true);
- bus->pktgen_count = 0;
- return;
- }
-
- /* Write test header length field */
- *data++ = (len >> 0);
- *data++ = (len >> 8);
-
- /* Then fill in the remainder -- N/A for burst,
- but who cares... */
- for (fillbyte = 0; fillbyte < len; fillbyte++)
- *data++ =
- SDPCM_TEST_FILL(fillbyte, (u8) bus->pktgen_sent);
+ if (pktq_len(&bus->txq) >= TXHI)
+ brcmf_txflowcontrol(bus->drvr, 0, ON);
#ifdef BCMDBG
- if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
- data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
- printk(KERN_DEBUG "brcmf_sdbrcm_pktgen: Tx Data:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data,
- pkt->len - SDPCM_HDRLEN);
- }
+ if (pktq_plen(&bus->txq, prec) > qcount[prec])
+ qcount[prec] = pktq_plen(&bus->txq, prec);
#endif
-
- /* Send it */
- if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true)) {
- bus->pktgen_fail++;
- if (bus->pktgen_stop
- && bus->pktgen_stop == bus->pktgen_fail)
- bus->pktgen_count = 0;
- }
- bus->pktgen_sent++;
-
- /* Bump length if not fixed, wrap at max */
- if (++bus->pktgen_len > bus->pktgen_maxlen)
- bus->pktgen_len = (u16) bus->pktgen_minlen;
-
- /* Special case for burst mode: just send one request! */
- if (bus->pktgen_mode == BRCMF_PKTGEN_RXBURST)
- break;
+ /* Schedule DPC if needed to send queued packet(s) */
+ if (!bus->dpc_sched) {
+ bus->dpc_sched = true;
+ if (bus->dpc_tsk)
+ complete(&bus->dpc_wait);
}
-}
-
-static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start)
-{
- struct sk_buff *pkt;
- u8 *data;
- /* Allocate the packet */
- pkt = brcmu_pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
- BRCMF_SDALIGN, true);
- if (!pkt) {
- BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n", __func__));
- return;
- }
- PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), BRCMF_SDALIGN);
- data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
-
- /* Fill in the test header */
- *data++ = SDPCM_TEST_SEND;
- *data++ = start;
- *data++ = (bus->pktgen_maxlen >> 0);
- *data++ = (bus->pktgen_maxlen >> 8);
-
- /* Send it */
- if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true))
- bus->pktgen_fail++;
+ return ret;
}
-static void
-brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, struct sk_buff *pkt, uint seq)
+static int
+brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data,
+ uint size)
{
- u8 *data;
- uint pktlen;
+ int bcmerror = 0;
+ u32 sdaddr;
+ uint dsize;
- u8 cmd;
- u8 extra;
- u16 len;
- u16 offset;
-
- /* Check for min length */
- pktlen = pkt->len;
- if (pktlen < SDPCM_TEST_HDRLEN) {
- BRCMF_ERROR(("brcmf_sdbrcm_checkdied: toss runt frame, pktlen "
- "%d\n", pktlen));
- brcmu_pkt_buf_free_skb(pkt, false);
- return;
- }
+ /* Determine initial transfer parameters */
+ sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
+ if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
+ dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
+ else
+ dsize = size;
- /* Extract header fields */
- data = pkt->data;
- cmd = *data++;
- extra = *data++;
- len = *data++;
- len += *data++ << 8;
-
- /* Check length for relevant commands */
- if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ
- || cmd == SDPCM_TEST_ECHORSP) {
- if (pktlen != len + SDPCM_TEST_HDRLEN) {
- BRCMF_ERROR(("brcmf_sdbrcm_checkdied: frame length "
- "mismatch, pktlen %d seq %d"
- " cmd %d extra %d len %d\n",
- pktlen, seq, cmd, extra, len));
- brcmu_pkt_buf_free_skb(pkt, false);
- return;
- }
+ /* Set the backplane window to include the start address */
+ bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address);
+ if (bcmerror) {
+ brcmf_dbg(ERROR, "window change failed\n");
+ goto xfer_done;
}
- /* Process as per command */
- switch (cmd) {
- case SDPCM_TEST_ECHOREQ:
- /* Rx->Tx turnaround ok (even on NDIS w/current
- implementation) */
- *(u8 *) (pkt->data) = SDPCM_TEST_ECHORSP;
- if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true) == 0)
- bus->pktgen_sent++;
- else {
- bus->pktgen_fail++;
- brcmu_pkt_buf_free_skb(pkt, false);
- }
- bus->pktgen_rcvd++;
- break;
-
- case SDPCM_TEST_ECHORSP:
- if (bus->ext_loop) {
- brcmu_pkt_buf_free_skb(pkt, false);
- bus->pktgen_rcvd++;
+ /* Do the transfer(s) */
+ while (size) {
+ brcmf_dbg(INFO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
+ write ? "write" : "read", dsize,
+ sdaddr, address & SBSDIO_SBWINDOW_MASK);
+ bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write,
+ sdaddr, data, dsize);
+ if (bcmerror) {
+ brcmf_dbg(ERROR, "membytes transfer failed\n");
break;
}
- for (offset = 0; offset < len; offset++, data++) {
- if (*data != SDPCM_TEST_FILL(offset, extra)) {
- BRCMF_ERROR(("brcmf_sdbrcm_checkdied: echo"
- " data mismatch: "
- "offset %d (len %d) "
- "expect 0x%02x rcvd 0x%02x\n",
- offset, len,
- SDPCM_TEST_FILL(offset, extra),
- *data));
+ /* Adjust for next transfer (if any) */
+ size -= dsize;
+ if (size) {
+ data += dsize;
+ address += dsize;
+ bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev,
+ address);
+ if (bcmerror) {
+ brcmf_dbg(ERROR, "window change failed\n");
break;
}
- }
- brcmu_pkt_buf_free_skb(pkt, false);
- bus->pktgen_rcvd++;
- break;
-
- case SDPCM_TEST_DISCARD:
- brcmu_pkt_buf_free_skb(pkt, false);
- bus->pktgen_rcvd++;
- break;
-
- case SDPCM_TEST_BURST:
- case SDPCM_TEST_SEND:
- default:
- BRCMF_INFO(("brcmf_sdbrcm_checkdied: unsupported or unknown "
- "command, pktlen %d seq %d" " cmd %d extra %d"
- " len %d\n", pktlen, seq, cmd, extra, len));
- brcmu_pkt_buf_free_skb(pkt, false);
- break;
- }
-
- /* For recv mode, stop at limie (and tell dongle to stop sending) */
- if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) {
- if (bus->pktgen_total
- && (bus->pktgen_rcvd >= bus->pktgen_total)) {
- bus->pktgen_count = 0;
- brcmf_sdbrcm_sdtest_set(bus, false);
- }
- }
-}
-#endif /* SDTEST */
-
-extern bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr)
-{
- struct brcmf_bus *bus;
-
- BRCMF_TIMER(("%s: Enter\n", __func__));
-
- bus = drvr->bus;
-
- if (bus->drvr->dongle_reset)
- return false;
-
- /* Ignore the timer if simulating bus down */
- if (bus->sleeping)
- return false;
-
- brcmf_sdbrcm_sdlock(bus);
-
- /* Poll period: check device if appropriate. */
- if (bus->poll && (++bus->polltick >= bus->pollrate)) {
- u32 intstatus = 0;
-
- /* Reset poll tick */
- bus->polltick = 0;
-
- /* Check device if no interrupts */
- if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
-
- if (!bus->dpc_sched) {
- u8 devpend;
- devpend = brcmf_sdcard_cfg_read(bus->card,
- SDIO_FUNC_0, SDIO_CCCR_INTx,
- NULL);
- intstatus =
- devpend & (INTR_STATUS_FUNC1 |
- INTR_STATUS_FUNC2);
- }
-
- /* If there is something, make like the ISR and
- schedule the DPC */
- if (intstatus) {
- bus->pollcnt++;
- bus->ipend = true;
- if (bus->intr)
- brcmf_sdcard_intr_disable(bus->card);
-
- bus->dpc_sched = true;
- brcmf_sdbrcm_sched_dpc(bus);
-
- }
- }
-
- /* Update interrupt tracking */
- bus->lastintrs = bus->intrcount;
- }
-#ifdef BCMDBG
- /* Poll for console output periodically */
- if (drvr->busstate == BRCMF_BUS_DATA && brcmf_console_ms != 0) {
- bus->console.count += brcmf_watchdog_ms;
- if (bus->console.count >= brcmf_console_ms) {
- bus->console.count -= brcmf_console_ms;
- /* Make sure backplane clock is on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- if (brcmf_sdbrcm_readconsole(bus) < 0)
- brcmf_console_ms = 0; /* On error,
- stop trying */
- }
- }
-#endif /* BCMDBG */
-
-#ifdef SDTEST
- /* Generate packets if configured */
- if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
- /* Make sure backplane clock is on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- bus->pktgen_tick = 0;
- brcmf_sdbrcm_pktgen(bus);
- }
-#endif
-
- /* On idle timeout clear activity flag and/or turn off clock */
- if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
- if (++bus->idlecount >= bus->idletime) {
- bus->idlecount = 0;
- if (bus->activity) {
- bus->activity = false;
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
- } else {
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
- }
+ sdaddr = 0;
+ dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
}
}
- brcmf_sdbrcm_sdunlock(bus);
+xfer_done:
+ /* Return the window to backplane enumeration space for core access */
+ if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, bus->sdiodev->sbwad))
+ brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n",
+ bus->sdiodev->sbwad);
- return bus->ipend;
+ return bcmerror;
}
#ifdef BCMDBG
-static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr,
- unsigned char *msg, uint msglen)
+#define CONSOLE_LINE_MAX 192
+
+static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus)
{
- struct brcmf_bus *bus = drvr->bus;
- u32 addr, val;
+ struct brcmf_console *c = &bus->console;
+ u8 line[CONSOLE_LINE_MAX], ch;
+ u32 n, idx, addr;
int rv;
- struct sk_buff *pkt;
- /* Address could be zero if CONSOLE := 0 in dongle Makefile */
+ /* Don't do anything until FWREADY updates console address */
if (bus->console_addr == 0)
- return -ENOTSUPP;
+ return 0;
- /* Exclusive bus access */
- brcmf_sdbrcm_sdlock(bus);
+ /* Read console log struct */
+ addr = bus->console_addr + offsetof(struct rte_console, log_le);
+ rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log_le,
+ sizeof(c->log_le));
+ if (rv < 0)
+ return rv;
- /* Don't allow input if dongle is in reset */
- if (bus->drvr->dongle_reset) {
- brcmf_sdbrcm_sdunlock(bus);
- return -EPERM;
+ /* Allocate console buffer (one time only) */
+ if (c->buf == NULL) {
+ c->bufsize = le32_to_cpu(c->log_le.buf_size);
+ c->buf = kmalloc(c->bufsize, GFP_ATOMIC);
+ if (c->buf == NULL)
+ return -ENOMEM;
}
- /* Request clock to allow SDIO accesses */
- BUS_WAKE(bus);
- /* No pend allowed since txpkt is called later, ht clk has to be on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ idx = le32_to_cpu(c->log_le.idx);
- /* Zero cbuf_index */
- addr = bus->console_addr + offsetof(struct rte_console, cbuf_idx);
- val = cpu_to_le32(0);
- rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
- if (rv < 0)
- goto done;
+ /* Protect against corrupt value */
+ if (idx > c->bufsize)
+ return -EBADE;
- /* Write message into cbuf */
- addr = bus->console_addr + offsetof(struct rte_console, cbuf);
- rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)msg, msglen);
- if (rv < 0)
- goto done;
+ /* Skip reading the console buffer if the index pointer
+ has not moved */
+ if (idx == c->last)
+ return 0;
- /* Write length into vcons_in */
- addr = bus->console_addr + offsetof(struct rte_console, vcons_in);
- val = cpu_to_le32(msglen);
- rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
+ /* Read the console buffer */
+ addr = le32_to_cpu(c->log_le.buf);
+ rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize);
if (rv < 0)
- goto done;
+ return rv;
- /* Bump dongle by sending an empty event pkt.
- * sdpcm_sendup (RX) checks for virtual console input.
- */
- pkt = brcmu_pkt_buf_get_skb(4 + SDPCM_RESERVE);
- if ((pkt != NULL) && bus->clkstate == CLK_AVAIL)
- brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, true);
+ while (c->last != idx) {
+ for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
+ if (c->last == idx) {
+ /* This would output a partial line.
+ * Instead, back up
+ * the buffer pointer and output this
+ * line next time around.
+ */
+ if (c->last >= n)
+ c->last -= n;
+ else
+ c->last = c->bufsize - n;
+ goto break2;
+ }
+ ch = c->buf[c->last];
+ c->last = (c->last + 1) % c->bufsize;
+ if (ch == '\n')
+ break;
+ line[n] = ch;
+ }
-done:
- if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
- bus->activity = false;
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
+ if (n > 0) {
+ if (line[n - 1] == '\r')
+ n--;
+ line[n] = 0;
+ printk(KERN_DEBUG "CONSOLE: %s\n", line);
+ }
}
+break2:
- brcmf_sdbrcm_sdunlock(bus);
-
- return rv;
+ return 0;
}
#endif /* BCMDBG */
-static bool brcmf_sdbrcm_chipmatch(u16 chipid)
-{
- if (chipid == BCM4325_CHIP_ID)
- return true;
- if (chipid == BCM4329_CHIP_ID)
- return true;
- if (chipid == BCM4319_CHIP_ID)
- return true;
- return false;
-}
-
-static void *brcmf_sdbrcm_probe(u16 venid, u16 devid, u16 bus_no,
- u16 slot, u16 func, uint bustype, u32 regsva,
- void *card)
+static int brcmf_tx_frame(struct brcmf_bus *bus, u8 *frame, u16 len)
{
+ int i;
int ret;
- struct brcmf_bus *bus;
-
- /* Init global variables at run-time, not as part of the declaration.
- * This is required to support init/de-init of the driver.
- * Initialization
- * of globals as part of the declaration results in non-deterministic
- * behavior since the value of the globals may be different on the
- * first time that the driver is initialized vs subsequent
- * initializations.
- */
- brcmf_txbound = BRCMF_TXBOUND;
- brcmf_rxbound = BRCMF_RXBOUND;
- brcmf_alignctl = true;
- sd1idle = true;
- brcmf_readahead = true;
- retrydata = false;
- brcmf_dongle_memsize = 0;
- brcmf_txminmax = BRCMF_TXMINMAX;
- forcealign = true;
+ bus->ctrl_frame_stat = false;
+ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad,
+ SDIO_FUNC_2, F2SYNC, frame, len, NULL);
- brcmf_c_init();
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
- BRCMF_INFO(("%s: venid 0x%04x devid 0x%04x\n", __func__, venid, devid));
+ if (ret < 0) {
+ /* On failure, abort the command and terminate the frame */
+ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
+ ret);
+ bus->tx_sderrs++;
- /* We make an assumption about address window mappings:
- * regsva == SI_ENUM_BASE*/
+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
- /* SDIO car passes venid and devid based on CIS parsing -- but
- * low-power start
- * means early parse could fail, so here we should get either an ID
- * we recognize OR (-1) indicating we must request power first.
- */
- /* Check the Vendor ID */
- switch (venid) {
- case 0x0000:
- case PCI_VENDOR_ID_BROADCOM:
- break;
- default:
- BRCMF_ERROR(("%s: unknown vendor: 0x%04x\n", __func__, venid));
- return NULL;
- }
-
- /* Check the Device ID and make sure it's one that we support */
- switch (devid) {
- case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */
- case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */
- case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */
- BRCMF_INFO(("%s: found 4325 Dongle\n", __func__));
- break;
- case BCM4329_D11NDUAL_ID: /* 4329 802.11n dualband device */
- case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */
- case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */
- case 0x4329:
- BRCMF_INFO(("%s: found 4329 Dongle\n", __func__));
- break;
- case BCM4319_D11N_ID: /* 4319 802.11n id */
- case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */
- case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */
- BRCMF_INFO(("%s: found 4319 Dongle\n", __func__));
- break;
- case 0:
- BRCMF_INFO(("%s: allow device id 0, will check chip"
- " internals\n", __func__));
- break;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_FRAMECTRL,
+ SFC_WF_TERM, NULL);
+ bus->f1regdata++;
- default:
- BRCMF_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
- __func__, venid, devid));
- return NULL;
+ for (i = 0; i < 3; i++) {
+ u8 hi, lo;
+ hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_WFRAMEBCHI,
+ NULL);
+ lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_WFRAMEBCLO,
+ NULL);
+ bus->f1regdata += 2;
+ if (hi == 0 && lo == 0)
+ break;
+ }
+ return ret;
}
- /* Allocate private bus interface state */
- bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
- if (!bus) {
- BRCMF_ERROR(("%s: kmalloc of struct dhd_bus failed\n",
- __func__));
- goto fail;
- }
- bus->card = card;
- bus->cl_devid = (u16) devid;
- bus->bus = BRCMF_BUS;
- bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
- bus->usebufpool = false; /* Use bufpool if allocated,
- else use locally malloced rxbuf */
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
- /* attempt to attach to the dongle */
- if (!(brcmf_sdbrcm_probe_attach(bus, card, regsva, devid))) {
- BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_attach failed\n",
- __func__));
- goto fail;
- }
-
- spin_lock_init(&bus->txqlock);
- init_waitqueue_head(&bus->ctrl_wait);
+ return ret;
+}
- /* Set up the watchdog timer */
- init_timer(&bus->timer);
- bus->timer.data = (unsigned long)bus;
- bus->timer.function = brcmf_sdbrcm_watchdog;
+int
+brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
+{
+ u8 *frame;
+ u16 len;
+ u32 swheader;
+ uint retries = 0;
+ u8 doff = 0;
+ int ret = -1;
- /* Initialize thread based operation and lock */
- if ((brcmf_watchdog_prio >= 0) && (brcmf_dpc_prio >= 0)) {
- bus->threads_only = true;
- sema_init(&bus->sdsem, 1);
- } else {
- bus->threads_only = false;
- spin_lock_init(&bus->sdlock);
- }
+ brcmf_dbg(TRACE, "Enter\n");
- if (brcmf_dpc_prio >= 0) {
- /* Initialize watchdog thread */
- init_completion(&bus->watchdog_wait);
- bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread,
- bus, "brcmf_watchdog");
- if (IS_ERR(bus->watchdog_tsk)) {
- printk(KERN_WARNING
- "brcmf_watchdog thread failed to start\n");
- bus->watchdog_tsk = NULL;
- }
- } else
- bus->watchdog_tsk = NULL;
+ /* Back the pointer to make a room for bus header */
+ frame = msg - SDPCM_HDRLEN;
+ len = (msglen += SDPCM_HDRLEN);
- /* Set up the bottom half handler */
- if (brcmf_dpc_prio >= 0) {
- /* Initialize DPC thread */
- init_completion(&bus->dpc_wait);
- bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
- bus, "brcmf_dpc");
- if (IS_ERR(bus->dpc_tsk)) {
- printk(KERN_WARNING
- "brcmf_dpc thread failed to start\n");
- bus->dpc_tsk = NULL;
- }
- } else {
- tasklet_init(&bus->tasklet, brcmf_sdbrcm_dpc_tasklet,
- (unsigned long)bus);
- bus->dpc_tsk = NULL;
- }
+ /* Add alignment padding (optional for ctl frames) */
+ doff = ((unsigned long)frame % BRCMF_SDALIGN);
+ if (doff) {
+ frame -= doff;
+ len += doff;
+ msglen += doff;
+ memset(frame, 0, doff + SDPCM_HDRLEN);
+ }
+ /* precondition: doff < BRCMF_SDALIGN */
+ doff += SDPCM_HDRLEN;
- /* Attach to the brcmf/OS/network interface */
- bus->drvr = brcmf_attach(bus, SDPCM_RESERVE);
- if (!bus->drvr) {
- BRCMF_ERROR(("%s: brcmf_attach failed\n", __func__));
- goto fail;
+ /* Round send length to next SDIO block */
+ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
+ u16 pad = bus->blocksize - (len % bus->blocksize);
+ if ((pad <= bus->roundup) && (pad < bus->blocksize))
+ len += pad;
+ } else if (len % BRCMF_SDALIGN) {
+ len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
}
- /* Allocate buffers */
- if (!(brcmf_sdbrcm_probe_malloc(bus, card))) {
- BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_malloc failed\n",
- __func__));
- goto fail;
- }
+ /* Satisfy length-alignment requirements */
+ if (len & (ALIGNMENT - 1))
+ len = roundup(len, ALIGNMENT);
- if (!(brcmf_sdbrcm_probe_init(bus, card))) {
- BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_init failed\n", __func__));
- goto fail;
- }
+ /* precondition: IS_ALIGNED((unsigned long)frame, 2) */
- /* Register interrupt callback, but mask it (not operational yet). */
- BRCMF_INTR(("%s: disable SDIO interrupts (not interested yet)\n",
- __func__));
- brcmf_sdcard_intr_disable(card);
- ret = brcmf_sdcard_intr_reg(card, brcmf_sdbrcm_isr, bus);
- if (ret != 0) {
- BRCMF_ERROR(("%s: FAILED: sdcard_intr_reg returned %d\n",
- __func__, ret));
- goto fail;
- }
- BRCMF_INTR(("%s: registered SDIO interrupt function ok\n", __func__));
+ /* Need to lock here to protect txseq and SDIO tx calls */
+ down(&bus->sdsem);
- BRCMF_INFO(("%s: completed!!\n", __func__));
+ bus_wake(bus);
- /* if firmware path present try to download and bring up bus */
- ret = brcmf_bus_start(bus->drvr);
- if (ret != 0) {
- if (ret == -ENOLINK) {
- BRCMF_ERROR(("%s: dongle is not responding\n",
- __func__));
- goto fail;
- }
- }
- /* Ok, have the per-port tell the stack we're open for business */
- if (brcmf_net_attach(bus->drvr, 0) != 0) {
- BRCMF_ERROR(("%s: Net attach failed!!\n", __func__));
- goto fail;
- }
+ /* Make sure backplane clock is on */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- return bus;
+ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
+ *(__le16 *) frame = cpu_to_le16((u16) msglen);
+ *(((__le16 *) frame) + 1) = cpu_to_le16(~msglen);
-fail:
- brcmf_sdbrcm_release(bus);
- return NULL;
-}
+ /* Software tag: channel, sequence number, data offset */
+ swheader =
+ ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) &
+ SDPCM_CHANNEL_MASK)
+ | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) &
+ SDPCM_DOFFSET_MASK);
+ put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
+ put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
-static bool
-brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card, u32 regsva,
- u16 devid)
-{
- u8 clkctl = 0;
- int err = 0;
+ if (!data_ok(bus)) {
+ brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n",
+ bus->tx_max, bus->tx_seq);
+ bus->ctrl_frame_stat = true;
+ /* Send from dpc */
+ bus->ctrl_frame_buf = frame;
+ bus->ctrl_frame_len = len;
- bus->alp_only = true;
+ brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat);
- /* Return the window to backplane enumeration space for core access */
- if (brcmf_sdbrcm_set_siaddr_window(bus, SI_ENUM_BASE))
- BRCMF_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n",
- __func__));
+ if (bus->ctrl_frame_stat == false) {
+ brcmf_dbg(INFO, "ctrl_frame_stat == false\n");
+ ret = 0;
+ } else {
+ brcmf_dbg(INFO, "ctrl_frame_stat == true\n");
+ ret = -1;
+ }
+ }
+ if (ret == -1) {
#ifdef BCMDBG
- printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n",
- brcmf_sdcard_reg_read(bus->card, SI_ENUM_BASE, 4));
-
-#endif /* BCMDBG */
-
- /*
- * Force PLL off until brcmf_sdbrcm_chip_attach()
- * programs PLL control regs
- */
-
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- BRCMF_INIT_CLKCTL1, &err);
- if (!err)
- clkctl =
- brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
+ printk(KERN_DEBUG "Tx Frame:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ frame, len);
+ } else if (BRCMF_HDRS_ON()) {
+ printk(KERN_DEBUG "TxHdr:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ frame, min_t(u16, len, 16));
+ }
+#endif
- if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
- BRCMF_ERROR(("brcmf_sdbrcm_probe: ChipClkCSR access: err %d"
- " wrote 0x%02x read 0x%02x\n",
- err, BRCMF_INIT_CLKCTL1, clkctl));
- goto fail;
+ do {
+ ret = brcmf_tx_frame(bus, frame, len);
+ } while (ret < 0 && retries++ < TXRETRIES);
}
- if (brcmf_sdbrcm_chip_attach(bus, regsva)) {
- BRCMF_ERROR(("%s: brcmf_sdbrcm_chip_attach failed!\n",
- __func__));
- goto fail;
+ if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ bus->activity = false;
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
}
- if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) {
- BRCMF_ERROR(("%s: unsupported chip: 0x%04x\n",
- __func__, bus->ci->chip));
- goto fail;
- }
+ up(&bus->sdsem);
- brcmf_sdbrcm_sdiod_drive_strength_init(bus, brcmf_sdiod_drive_strength);
+ if (ret)
+ bus->drvr->tx_ctlerrs++;
+ else
+ bus->drvr->tx_ctlpkts++;
- /* Get info on the ARM and SOCRAM cores... */
- if (!BRCMF_NOPMU(bus)) {
- brcmf_sdcard_reg_read(bus->card,
- CORE_SB(bus->ci->armcorebase, sbidhigh), 4);
- bus->orig_ramsize = bus->ci->ramsize;
- if (!(bus->orig_ramsize)) {
- BRCMF_ERROR(("%s: failed to find SOCRAM memory!\n",
- __func__));
- goto fail;
- }
- bus->ramsize = bus->orig_ramsize;
- if (brcmf_dongle_memsize)
- brcmf_sdbrcm_setmemsize(bus, brcmf_dongle_memsize);
+ return ret ? -EIO : 0;
+}
- BRCMF_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n",
- bus->ramsize, bus->orig_ramsize));
- }
+int
+brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
+{
+ int timeleft;
+ uint rxlen = 0;
+ bool pending;
- /* Set core control so an SDIO reset does a backplane reset */
- OR_REG(bus->ci->buscorebase + offsetof(struct sdpcmd_regs,
- corecontrol),
- CC_BPRESEN, u32);
+ brcmf_dbg(TRACE, "Enter\n");
- brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
+ /* Wait until control frame is available */
+ timeleft = brcmf_sdbrcm_dcmd_resp_wait(bus, &bus->rxlen, &pending);
- /* Locate an appropriately-aligned portion of hdrbuf */
- bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0],
- BRCMF_SDALIGN);
+ down(&bus->sdsem);
+ rxlen = bus->rxlen;
+ memcpy(msg, bus->rxctl, min(msglen, rxlen));
+ bus->rxlen = 0;
+ up(&bus->sdsem);
- /* Set the poll and/or interrupt flags */
- bus->intr = (bool) brcmf_intr;
- bus->poll = (bool) brcmf_poll;
- if (bus->poll)
- bus->pollrate = 1;
+ if (rxlen) {
+ brcmf_dbg(CTL, "resumed on rxctl frame, got %d expected %d\n",
+ rxlen, msglen);
+ } else if (timeleft == 0) {
+ brcmf_dbg(ERROR, "resumed on timeout\n");
+ } else if (pending == true) {
+ brcmf_dbg(CTL, "cancelled\n");
+ return -ERESTARTSYS;
+ } else {
+ brcmf_dbg(CTL, "resumed for unknown reason?\n");
+ }
- return true;
+ if (rxlen)
+ bus->drvr->rx_ctlpkts++;
+ else
+ bus->drvr->rx_ctlerrs++;
-fail:
- return false;
+ return rxlen ? (int)rxlen : -ETIMEDOUT;
}
-static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card)
+static int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len)
{
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ int bcmerror = 0;
- if (bus->drvr->maxctl) {
- bus->rxblen =
- roundup((bus->drvr->maxctl + SDPCM_HDRLEN),
- ALIGNMENT) + BRCMF_SDALIGN;
- bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
- if (!(bus->rxbuf)) {
- BRCMF_ERROR(("%s: kmalloc of %d-byte rxbuf failed\n",
- __func__, bus->rxblen));
- goto fail;
- }
- }
+ brcmf_dbg(TRACE, "Enter\n");
- /* Allocate buffer to receive glomed packet */
- bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC);
- if (!(bus->databuf)) {
- BRCMF_ERROR(("%s: kmalloc of %d-byte databuf failed\n",
- __func__, MAX_DATA_BUF));
- /* release rxbuf which was already located as above */
- if (!bus->rxblen)
- kfree(bus->rxbuf);
- goto fail;
+ /* Basic sanity checks */
+ if (bus->drvr->up) {
+ bcmerror = -EISCONN;
+ goto err;
+ }
+ if (!len) {
+ bcmerror = -EOVERFLOW;
+ goto err;
}
- /* Align the buffer */
- if ((unsigned long)bus->databuf % BRCMF_SDALIGN)
- bus->dataptr = bus->databuf + (BRCMF_SDALIGN -
- ((unsigned long)bus->databuf % BRCMF_SDALIGN));
- else
- bus->dataptr = bus->databuf;
+ /* Free the old ones and replace with passed variables */
+ kfree(bus->vars);
- return true;
+ bus->vars = kmalloc(len, GFP_ATOMIC);
+ bus->varsz = bus->vars ? len : 0;
+ if (bus->vars == NULL) {
+ bcmerror = -ENOMEM;
+ goto err;
+ }
-fail:
- return false;
+ /* Copy the passed variables, which should include the
+ terminating double-null */
+ memcpy(bus->vars, arg, bus->varsz);
+err:
+ return bcmerror;
}
-static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card)
+static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus)
{
- s32 fnum;
+ int bcmerror = 0;
+ u32 varsize;
+ u32 varaddr;
+ u8 *vbuffer;
+ u32 varsizew;
+ __le32 varsizew_le;
+#ifdef BCMDBG
+ char *nvram_ularray;
+#endif /* BCMDBG */
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ /* Even if there are no vars are to be written, we still
+ need to set the ramsize. */
+ varsize = bus->varsz ? roundup(bus->varsz, 4) : 0;
+ varaddr = (bus->ramsize - 4) - varsize;
-#ifdef SDTEST
- brcmf_sdbrcm_pktgen_init(bus);
-#endif /* SDTEST */
+ if (bus->vars) {
+ vbuffer = kzalloc(varsize, GFP_ATOMIC);
+ if (!vbuffer)
+ return -ENOMEM;
- /* Disable F2 to clear any intermediate frame state on the dongle */
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
- SDIO_FUNC_ENABLE_1, NULL);
+ memcpy(vbuffer, bus->vars, bus->varsz);
- bus->drvr->busstate = BRCMF_BUS_DOWN;
- bus->sleeping = false;
- bus->rxflow = false;
+ /* Write the vars list */
+ bcmerror =
+ brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize);
+#ifdef BCMDBG
+ /* Verify NVRAM bytes */
+ brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize);
+ nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
+ if (!nvram_ularray)
+ return -ENOMEM;
- /* Done with backplane-dependent accesses, can drop clock... */
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0,
- NULL);
+ /* Upload image to verify downloaded contents. */
+ memset(nvram_ularray, 0xaa, varsize);
- /* ...and initialize clock/power states */
- bus->clkstate = CLK_SDONLY;
- bus->idletime = (s32) brcmf_idletime;
- bus->idleclock = BRCMF_IDLE_ACTIVE;
+ /* Read the vars list to temp buffer for comparison */
+ bcmerror =
+ brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray,
+ varsize);
+ if (bcmerror) {
+ brcmf_dbg(ERROR, "error %d on reading %d nvram bytes at 0x%08x\n",
+ bcmerror, varsize, varaddr);
+ }
+ /* Compare the org NVRAM with the one read from RAM */
+ if (memcmp(vbuffer, nvram_ularray, varsize))
+ brcmf_dbg(ERROR, "Downloaded NVRAM image is corrupted\n");
+ else
+ brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n");
- /* Query the F2 block size, set roundup accordingly */
- fnum = 2;
- if (brcmf_sdcard_iovar_op(card, "sd_blocksize", &fnum, sizeof(s32),
- &bus->blocksize, sizeof(s32), false) != 0) {
- bus->blocksize = 0;
- BRCMF_ERROR(("%s: fail on %s get\n", __func__, "sd_blocksize"));
- } else {
- BRCMF_INFO(("%s: Initial value for %s is %d\n",
- __func__, "sd_blocksize", bus->blocksize));
+ kfree(nvram_ularray);
+#endif /* BCMDBG */
+
+ kfree(vbuffer);
}
- bus->roundup = min(max_roundup, bus->blocksize);
- /* Query if bus module supports packet chaining,
- default to use if supported */
- if (brcmf_sdcard_iovar_op(card, "sd_rxchain", NULL, 0,
- &bus->sd_rxchain, sizeof(s32),
- false) != 0) {
- bus->sd_rxchain = false;
+ /* adjust to the user specified RAM */
+ brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize);
+ brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n",
+ varaddr, varsize);
+ varsize = ((bus->ramsize - 4) - varaddr);
+
+ /*
+ * Determine the length token:
+ * Varsize, converted to words, in lower 16-bits, checksum
+ * in upper 16-bits.
+ */
+ if (bcmerror) {
+ varsizew = 0;
+ varsizew_le = cpu_to_le32(0);
} else {
- BRCMF_INFO(("%s: bus module (through sdiocard API) %s"
- " chaining\n", __func__, bus->sd_rxchain
- ? "supports" : "does not support"));
+ varsizew = varsize / 4;
+ varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
+ varsizew_le = cpu_to_le32(varsizew);
}
- bus->use_rxchain = (bool) bus->sd_rxchain;
- return true;
-}
+ brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n",
+ varsize, varsizew);
-static bool
-brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card)
-{
- bool ret;
+ /* Write the length token to the last word */
+ bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4),
+ (u8 *)&varsizew_le, 4);
- /* Download the firmware */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ return bcmerror;
+}
- ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
+static void
+brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_dev *sdiodev, u32 corebase)
+{
+ u32 regdata;
- brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4);
+ if (regdata & SBTML_RESET)
+ return;
- return ret;
-}
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4);
+ if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
+ /*
+ * set target reject and spin until busy is clear
+ * (preserve core-specific bits)
+ */
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4);
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow),
+ 4, regdata | SBTML_REJ);
-/* Detach and free everything */
-static void brcmf_sdbrcm_release(struct brcmf_bus *bus)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4);
+ udelay(1);
+ SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatehigh), 4) &
+ SBTMH_BUSY), 100000);
- if (bus) {
- /* De-register interrupt handler */
- brcmf_sdcard_intr_disable(bus->card);
- brcmf_sdcard_intr_dereg(bus->card);
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatehigh), 4);
+ if (regdata & SBTMH_BUSY)
+ brcmf_dbg(ERROR, "ARM core still busy\n");
- if (bus->drvr) {
- brcmf_detach(bus->drvr);
- brcmf_sdbrcm_release_dongle(bus);
- bus->drvr = NULL;
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbidlow), 4);
+ if (regdata & SBIDL_INIT) {
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbimstate), 4) |
+ SBIM_RJ;
+ brcmf_sdcard_reg_write(sdiodev,
+ CORE_SB(corebase, sbimstate), 4,
+ regdata);
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbimstate), 4);
+ udelay(1);
+ SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbimstate), 4) &
+ SBIM_BY), 100000);
}
- brcmf_sdbrcm_release_malloc(bus);
+ /* set reset and reject while enabling the clocks */
+ brcmf_sdcard_reg_write(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4,
+ (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
+ SBTML_REJ | SBTML_RESET));
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4);
+ udelay(10);
- kfree(bus);
+ /* clear the initiator reject bit */
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbidlow), 4);
+ if (regdata & SBIDL_INIT) {
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbimstate), 4) &
+ ~SBIM_RJ;
+ brcmf_sdcard_reg_write(sdiodev,
+ CORE_SB(corebase, sbimstate), 4,
+ regdata);
+ }
}
- BRCMF_TRACE(("%s: Disconnected\n", __func__));
+ /* leave reset and reject asserted */
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
+ (SBTML_REJ | SBTML_RESET));
+ udelay(1);
}
-static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus)
+static void
+brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase)
{
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (bus->drvr && bus->drvr->dongle_reset)
- return;
+ u32 regdata;
- kfree(bus->rxbuf);
- bus->rxctl = bus->rxbuf = NULL;
- bus->rxlen = 0;
+ /*
+ * Must do the disable sequence first to work for
+ * arbitrary current core state.
+ */
+ brcmf_sdbrcm_chip_disablecore(sdiodev, corebase);
- kfree(bus->databuf);
- bus->databuf = NULL;
-}
+ /*
+ * Now do the initialization sequence.
+ * set reset while enabling the clock and
+ * forcing them on throughout the core
+ */
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
+ ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
+ SBTML_RESET);
+ udelay(1);
-static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatehigh), 4);
+ if (regdata & SBTMH_SERR)
+ brcmf_sdcard_reg_write(sdiodev,
+ CORE_SB(corebase, sbtmstatehigh), 4, 0);
- if (bus->drvr && bus->drvr->dongle_reset)
- return;
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbimstate), 4);
+ if (regdata & (SBIM_IBE | SBIM_TO))
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4,
+ regdata & ~(SBIM_IBE | SBIM_TO));
- if (bus->ci) {
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
- brcmf_sdbrcm_chip_detach(bus);
- if (bus->vars && bus->varsz)
- kfree(bus->vars);
- bus->vars = NULL;
- }
+ /* clear reset and allow it to propagate throughout the core */
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
+ (SICF_FGC << SBTML_SICF_SHIFT) |
+ (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
+ udelay(1);
- BRCMF_TRACE(("%s: Disconnected\n", __func__));
+ /* leave clock enabled */
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
+ (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
+ udelay(1);
}
-static void brcmf_sdbrcm_disconnect(void *ptr)
+static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
{
- struct brcmf_bus *bus = (struct brcmf_bus *)ptr;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ uint retries;
+ u32 regdata;
+ int bcmerror = 0;
- if (bus) {
- brcmf_sdbrcm_release(bus);
- }
+ /* To enter download state, disable ARM and reset SOCRAM.
+ * To exit download state, simply reset ARM (default is RAM boot).
+ */
+ if (enter) {
+ bus->alp_only = true;
- BRCMF_TRACE(("%s: Disconnected\n", __func__));
-}
+ brcmf_sdbrcm_chip_disablecore(bus->sdiodev,
+ bus->ci->armcorebase);
-/* Register/Unregister functions are called by the main DHD entry
- * point (e.g. module insertion) to link with the bus driver, in
- * order to look for or await the device.
- */
+ brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->ramcorebase);
-static struct brcmf_sdioh_driver brcmf_sdio = {
- brcmf_sdbrcm_probe,
- brcmf_sdbrcm_disconnect
-};
+ /* Clear the top bit of memory */
+ if (bus->ramsize) {
+ u32 zeros = 0;
+ brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4,
+ (u8 *)&zeros, 4);
+ }
+ } else {
+ regdata = brcmf_sdcard_reg_read(bus->sdiodev,
+ CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4);
+ regdata &= (SBTML_RESET | SBTML_REJ_MASK |
+ (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
+ if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) {
+ brcmf_dbg(ERROR, "SOCRAM core is down after reset?\n");
+ bcmerror = -EBADE;
+ goto fail;
+ }
-int brcmf_bus_register(void)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ bcmerror = brcmf_sdbrcm_write_vars(bus);
+ if (bcmerror) {
+ brcmf_dbg(ERROR, "no vars written to RAM\n");
+ bcmerror = 0;
+ }
- /* Sanity check on the module parameters */
- do {
- /* Both watchdog and DPC as tasklets are ok */
- if ((brcmf_watchdog_prio < 0) && (brcmf_dpc_prio < 0))
- break;
+ w_sdreg32(bus, 0xFFFFFFFF,
+ offsetof(struct sdpcmd_regs, intstatus), &retries);
- /* If both watchdog and DPC are threads, TX must be deferred */
- if ((brcmf_watchdog_prio >= 0) && (brcmf_dpc_prio >= 0)
- && brcmf_deferred_tx)
- break;
+ brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->armcorebase);
- BRCMF_ERROR(("Invalid module parameters.\n"));
- return -EINVAL;
- } while (0);
+ /* Allow HT Clock now that the ARM is running. */
+ bus->alp_only = false;
- return brcmf_sdio_register(&brcmf_sdio);
+ bus->drvr->busstate = BRCMF_BUS_LOAD;
+ }
+fail:
+ return bcmerror;
}
-void brcmf_bus_unregister(void)
+static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus)
{
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ if (bus->firmware->size < bus->fw_ptr + len)
+ len = bus->firmware->size - bus->fw_ptr;
- brcmf_sdio_unregister();
+ memcpy(buf, &bus->firmware->data[bus->fw_ptr], len);
+ bus->fw_ptr += len;
+ return len;
}
+MODULE_FIRMWARE(BCM4329_FW_NAME);
+MODULE_FIRMWARE(BCM4329_NV_NAME);
+
static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus)
{
int offset = 0;
@@ -5916,22 +3408,19 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus)
u8 *memblock = NULL, *memptr;
int ret;
- BRCMF_INFO(("%s: Enter\n", __func__));
+ brcmf_dbg(INFO, "Enter\n");
bus->fw_name = BCM4329_FW_NAME;
ret = request_firmware(&bus->firmware, bus->fw_name,
- &gInstance->func[2]->dev);
+ &bus->sdiodev->func[2]->dev);
if (ret) {
- BRCMF_ERROR(("%s: Fail to request firmware %d\n",
- __func__, ret));
+ brcmf_dbg(ERROR, "Fail to request firmware %d\n", ret);
return ret;
}
bus->fw_ptr = 0;
memptr = memblock = kmalloc(MEMBLOCK + BRCMF_SDALIGN, GFP_ATOMIC);
if (memblock == NULL) {
- BRCMF_ERROR(("%s: Failed to allocate memory %d bytes\n",
- __func__, MEMBLOCK));
ret = -ENOMEM;
goto err;
}
@@ -5944,9 +3433,8 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus)
brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) {
ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len);
if (ret) {
- BRCMF_ERROR(("%s: error %d on writing %d membytes at "
- "0x%08x\n", __func__, ret, MEMBLOCK,
- offset));
+ brcmf_dbg(ERROR, "error %d on writing %d membytes at 0x%08x\n",
+ ret, MEMBLOCK, offset);
goto err;
}
@@ -6022,17 +3510,15 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus)
bus->nv_name = BCM4329_NV_NAME;
ret = request_firmware(&bus->firmware, bus->nv_name,
- &gInstance->func[2]->dev);
+ &bus->sdiodev->func[2]->dev);
if (ret) {
- BRCMF_ERROR(("%s: Fail to request nvram %d\n", __func__, ret));
+ brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret);
return ret;
}
bus->fw_ptr = 0;
memblock = kmalloc(MEMBLOCK, GFP_ATOMIC);
if (memblock == NULL) {
- BRCMF_ERROR(("%s: Failed to allocate memory %d bytes\n",
- __func__, MEMBLOCK));
ret = -ENOMEM;
goto err;
}
@@ -6048,11 +3534,9 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus)
if (len)
ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1);
if (ret)
- BRCMF_ERROR(("%s: error downloading vars: %d\n",
- __func__, ret));
+ brcmf_dbg(ERROR, "error downloading vars: %d\n", ret);
} else {
- BRCMF_ERROR(("%s: error reading nvram file: %d\n",
- __func__, len));
+ brcmf_dbg(ERROR, "error reading nvram file: %d\n", len);
ret = -EIO;
}
@@ -6071,28 +3555,23 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus)
/* Keep arm in reset */
if (brcmf_sdbrcm_download_state(bus, true)) {
- BRCMF_ERROR(("%s: error placing ARM core in reset\n",
- __func__));
+ brcmf_dbg(ERROR, "error placing ARM core in reset\n");
goto err;
}
/* External image takes precedence if specified */
if (brcmf_sdbrcm_download_code_file(bus)) {
- BRCMF_ERROR(("%s: dongle image file download failed\n",
- __func__));
+ brcmf_dbg(ERROR, "dongle image file download failed\n");
goto err;
}
/* External nvram takes precedence if specified */
- if (brcmf_sdbrcm_download_nvram(bus)) {
- BRCMF_ERROR(("%s: dongle nvram file download failed\n",
- __func__));
- }
+ if (brcmf_sdbrcm_download_nvram(bus))
+ brcmf_dbg(ERROR, "dongle nvram file download failed\n");
/* Take arm out of reset */
if (brcmf_sdbrcm_download_state(bus, false)) {
- BRCMF_ERROR(("%s: error getting out of ARM core reset\n",
- __func__));
+ brcmf_dbg(ERROR, "error getting out of ARM core reset\n");
goto err;
}
@@ -6102,359 +3581,379 @@ err:
return bcmerror;
}
-
-static int
-brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags,
- u8 *buf, uint nbytes, struct sk_buff *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle)
+static bool
+brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus)
{
- return brcmf_sdcard_send_buf
- (bus->card, addr, fn, flags, buf, nbytes, pkt, complete,
- handle);
+ bool ret;
+
+ /* Download the firmware */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+
+ ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
+
+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+
+ return ret;
}
-int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag)
+void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus)
{
- int bcmerror = 0;
- struct brcmf_bus *bus;
-
- bus = drvr->bus;
+ u32 local_hostintmask;
+ u8 saveclk;
+ uint retries;
+ int err;
- if (flag == true) {
- brcmf_sdbrcm_wd_timer(bus, 0);
- if (!bus->drvr->dongle_reset) {
- /* Expect app to have torn down any
- connection before calling */
- /* Stop the bus, disable F2 */
- brcmf_sdbrcm_bus_stop(bus, false);
-
- /* Clean tx/rx buffer pointers,
- detach from the dongle */
- brcmf_sdbrcm_release_dongle(bus);
+ brcmf_dbg(TRACE, "Enter\n");
- bus->drvr->dongle_reset = true;
- bus->drvr->up = false;
+ if (bus->watchdog_tsk) {
+ send_sig(SIGTERM, bus->watchdog_tsk, 1);
+ kthread_stop(bus->watchdog_tsk);
+ bus->watchdog_tsk = NULL;
+ }
- BRCMF_TRACE(("%s: WLAN OFF DONE\n", __func__));
- /* App can now remove power from device */
- } else
- bcmerror = -EIO;
- } else {
- /* App must have restored power to device before calling */
-
- BRCMF_TRACE(("\n\n%s: == WLAN ON ==\n", __func__));
-
- if (bus->drvr->dongle_reset) {
- /* Turn on WLAN */
-
- /* Attempt to re-attach & download */
- if (brcmf_sdbrcm_probe_attach(bus, bus->card,
- SI_ENUM_BASE,
- bus->cl_devid)) {
- /* Attempt to download binary to the dongle */
- if (brcmf_sdbrcm_probe_init(bus, bus->card)) {
- /* Re-init bus, enable F2 transfer */
- brcmf_sdbrcm_bus_init(bus->drvr, false);
-
- bus->drvr->dongle_reset = false;
- bus->drvr->up = true;
-
- BRCMF_TRACE(("%s: WLAN ON DONE\n",
- __func__));
- } else
- bcmerror = -EIO;
- } else
- bcmerror = -EIO;
- } else {
- bcmerror = -EISCONN;
- BRCMF_ERROR(("%s: Set DEVRESET=false invoked when"
- " device is on\n", __func__));
- bcmerror = -EIO;
- }
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
+ if (bus->dpc_tsk && bus->dpc_tsk != current) {
+ send_sig(SIGTERM, bus->dpc_tsk, 1);
+ kthread_stop(bus->dpc_tsk);
+ bus->dpc_tsk = NULL;
}
- return bcmerror;
-}
-static int
-brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_card *card,
- struct chip_info *ci, u32 regs)
-{
- u32 regdata;
+ down(&bus->sdsem);
- /*
- * Get CC core rev
- * Chipid is assume to be at offset 0 from regs arg
- * For different chiptypes or old sdio hosts w/o chipcommon,
- * other ways of recognition should be added here.
- */
- ci->cccorebase = regs;
- regdata = brcmf_sdcard_reg_read(card,
- CORE_CC_REG(ci->cccorebase, chipid), 4);
- ci->chip = regdata & CID_ID_MASK;
- ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
+ bus_wake(bus);
- BRCMF_INFO(("%s: chipid=0x%x chiprev=%d\n",
- __func__, ci->chip, ci->chiprev));
+ /* Enable clock for device interrupts */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- /* Address of cores for new chips should be added here */
- switch (ci->chip) {
- case BCM4329_CHIP_ID:
- ci->buscorebase = BCM4329_CORE_BUS_BASE;
- ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
- ci->armcorebase = BCM4329_CORE_ARM_BASE;
- ci->ramsize = BCM4329_RAMSIZE;
- break;
- default:
- BRCMF_ERROR(("%s: chipid 0x%x is not supported\n",
- __func__, ci->chip));
- return -ENODEV;
+ /* Disable and clear interrupts at the chip level also */
+ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries);
+ local_hostintmask = bus->hostintmask;
+ bus->hostintmask = 0;
+
+ /* Change our idea of bus state */
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
+
+ /* Force clocks on backplane to be sure F2 interrupt propagates */
+ saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (!err) {
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
}
+ if (err)
+ brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err);
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(ci->cccorebase, sbidhigh), 4);
- ci->ccrev = SBCOREREV(regdata);
+ /* Turn off the bus (F2), free any pending packets */
+ brcmf_dbg(INTR, "disable SDIO interrupts\n");
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+ SDIO_FUNC_ENABLE_1, NULL);
- regdata = brcmf_sdcard_reg_read(card,
- CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
- ci->pmurev = regdata & PCAP_REV_MASK;
+ /* Clear any pending interrupts now that F2 is disabled */
+ w_sdreg32(bus, local_hostintmask,
+ offsetof(struct sdpcmd_regs, intstatus), &retries);
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(ci->buscorebase, sbidhigh), 4);
- ci->buscorerev = SBCOREREV(regdata);
- ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
+ /* Turn off the backplane clock (only) */
+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
- BRCMF_INFO(("%s: ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
- __func__, ci->ccrev, ci->pmurev,
- ci->buscorerev, ci->buscoretype));
+ /* Clear the data packet queues */
+ brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
- /* get chipcommon capabilites */
- ci->cccaps = brcmf_sdcard_reg_read(card,
- CORE_CC_REG(ci->cccorebase, capabilities), 4);
+ /* Clear any held glomming stuff */
+ if (bus->glomd)
+ brcmu_pkt_buf_free_skb(bus->glomd);
- return 0;
+ if (bus->glom)
+ brcmu_pkt_buf_free_skb(bus->glom);
+
+ bus->glom = bus->glomd = NULL;
+
+ /* Clear rx control and wake any waiters */
+ bus->rxlen = 0;
+ brcmf_sdbrcm_dcmd_resp_wake(bus);
+
+ /* Reset some F2 state stuff */
+ bus->rxskip = false;
+ bus->tx_seq = bus->rx_seq = 0;
+
+ up(&bus->sdsem);
}
-static void
-brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase)
+int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr)
{
- u32 regdata;
+ struct brcmf_bus *bus = drvr->bus;
+ unsigned long timeout;
+ uint retries = 0;
+ u8 ready, enable;
+ int err, ret = 0;
+ u8 saveclk;
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatelow), 4);
- if (regdata & SBTML_RESET)
- return;
+ brcmf_dbg(TRACE, "Enter\n");
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatelow), 4);
- if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
- /*
- * set target reject and spin until busy is clear
- * (preserve core-specific bits)
- */
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatelow), 4);
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
- regdata | SBTML_REJ);
+ /* try to download image and nvram to the dongle */
+ if (drvr->busstate == BRCMF_BUS_DOWN) {
+ if (!(brcmf_sdbrcm_download_firmware(bus)))
+ return -1;
+ }
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatelow), 4);
- udelay(1);
- SPINWAIT((brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatehigh), 4) &
- SBTMH_BUSY), 100000);
+ if (!bus->drvr)
+ return 0;
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatehigh), 4);
- if (regdata & SBTMH_BUSY)
- BRCMF_ERROR(("%s: ARM core still busy\n", __func__));
+ /* Start the watchdog timer */
+ bus->drvr->tickcnt = 0;
+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbidlow), 4);
- if (regdata & SBIDL_INIT) {
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbimstate), 4) |
- SBIM_RJ;
- brcmf_sdcard_reg_write(card,
- CORE_SB(corebase, sbimstate), 4,
- regdata);
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbimstate), 4);
- udelay(1);
- SPINWAIT((brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbimstate), 4) &
- SBIM_BY), 100000);
- }
+ down(&bus->sdsem);
- /* set reset and reject while enabling the clocks */
- brcmf_sdcard_reg_write(card,
- CORE_SB(corebase, sbtmstatelow), 4,
- (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
- SBTML_REJ | SBTML_RESET));
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatelow), 4);
- udelay(10);
+ /* Make sure backplane clock is on, needed to generate F2 interrupt */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ if (bus->clkstate != CLK_AVAIL)
+ goto exit;
- /* clear the initiator reject bit */
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbidlow), 4);
- if (regdata & SBIDL_INIT) {
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbimstate), 4) &
- ~SBIM_RJ;
- brcmf_sdcard_reg_write(card,
- CORE_SB(corebase, sbimstate), 4,
- regdata);
- }
+ /* Force clocks on backplane to be sure F2 interrupt propagates */
+ saveclk =
+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (!err) {
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
+ }
+ if (err) {
+ brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err);
+ goto exit;
}
- /* leave reset and reject asserted */
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
- (SBTML_REJ | SBTML_RESET));
- udelay(1);
+ /* Enable function 2 (frame transfers) */
+ w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
+ offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries);
+ enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+ enable, NULL);
+
+ timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY);
+ ready = 0;
+ while (enable != ready) {
+ ready = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_0,
+ SDIO_CCCR_IORx, NULL);
+ if (time_after(jiffies, timeout))
+ break;
+ else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50))
+ /* prevent busy waiting if it takes too long */
+ msleep_interruptible(20);
+ }
+
+ brcmf_dbg(INFO, "enable 0x%02x, ready 0x%02x\n", enable, ready);
+
+ /* If F2 successfully enabled, set core and enable interrupts */
+ if (ready == enable) {
+ /* Set up the interrupt mask and enable interrupts */
+ bus->hostintmask = HOSTINTMASK;
+ w_sdreg32(bus, bus->hostintmask,
+ offsetof(struct sdpcmd_regs, hostintmask), &retries);
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_WATERMARK, 8, &err);
+
+ /* Set bus state according to enable result */
+ drvr->busstate = BRCMF_BUS_DATA;
+ }
+
+ else {
+ /* Disable F2 again */
+ enable = SDIO_FUNC_ENABLE_1;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0,
+ SDIO_CCCR_IOEx, enable, NULL);
+ }
+
+ /* Restore previous clock setting */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
+
+ /* If we didn't come up, turn off backplane clock */
+ if (drvr->busstate != BRCMF_BUS_DATA)
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+
+exit:
+ up(&bus->sdsem);
+
+ return ret;
}
-static int
-brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs)
+void brcmf_sdbrcm_isr(void *arg)
{
- struct chip_info *ci;
- int err;
- u8 clkval, clkset;
+ struct brcmf_bus *bus = (struct brcmf_bus *) arg;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
- /* alloc chip_info_t */
- ci = kmalloc(sizeof(struct chip_info), GFP_ATOMIC);
- if (NULL == ci) {
- BRCMF_ERROR(("%s: malloc failed!\n", __func__));
- return -ENOMEM;
+ if (!bus) {
+ brcmf_dbg(ERROR, "bus is null pointer, exiting\n");
+ return;
}
- memset((unsigned char *)ci, 0, sizeof(struct chip_info));
-
- /* bus/core/clk setup for register access */
- /* Try forcing SDIO core to do ALPAvail request only */
- clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- clkset, &err);
- if (err) {
- BRCMF_ERROR(("%s: error writing for HT off\n", __func__));
- goto fail;
+ if (bus->drvr->busstate == BRCMF_BUS_DOWN) {
+ brcmf_dbg(ERROR, "bus is down. we have nothing to do\n");
+ return;
}
+ /* Count the interrupt call */
+ bus->intrcount++;
+ bus->ipend = true;
- /* If register supported, wait for ALPAvail and then force ALP */
- /* This may take up to 15 milliseconds */
- clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, NULL);
- if ((clkval & ~SBSDIO_AVBITS) == clkset) {
- SPINWAIT(((clkval =
- brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- NULL)),
- !SBSDIO_ALPAV(clkval)),
- PMU_MAX_TRANSITION_DLY);
- if (!SBSDIO_ALPAV(clkval)) {
- BRCMF_ERROR(("%s: timeout on ALPAV wait,"
- " clkval 0x%02x\n", __func__, clkval));
- err = -EBUSY;
- goto fail;
- }
- clkset = SBSDIO_FORCE_HW_CLKREQ_OFF |
- SBSDIO_FORCE_ALP;
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- clkset, &err);
- udelay(65);
- } else {
- BRCMF_ERROR(("%s: ChipClkCSR access: wrote 0x%02x"
- " read 0x%02x\n", __func__, clkset, clkval));
- err = -EACCES;
- goto fail;
+ /* Shouldn't get this interrupt if we're sleeping? */
+ if (bus->sleeping) {
+ brcmf_dbg(ERROR, "INTERRUPT WHILE SLEEPING??\n");
+ return;
}
- /* Also, disable the extra SDIO pull-ups */
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP,
- 0, NULL);
+ /* Disable additional interrupts (is this needed now)? */
+ if (!bus->intr)
+ brcmf_dbg(ERROR, "isr w/o interrupt configured!\n");
- err = brcmf_sdbrcm_chip_recognition(bus->card, ci, regs);
- if (err)
- goto fail;
+#if defined(ISR_THREAD)
+ while (brcmf_sdbrcm_dpc(bus))
+ ;
+#else
+ bus->dpc_sched = true;
+ if (bus->dpc_tsk)
+ complete(&bus->dpc_wait);
+#endif
- /*
- * Make sure any on-chip ARM is off (in case strapping is wrong),
- * or downloaded code was already running.
- */
- brcmf_sdbrcm_chip_disablecore(bus->card, ci->armcorebase);
+}
- brcmf_sdcard_reg_write(bus->card,
- CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
- brcmf_sdcard_reg_write(bus->card,
- CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
+static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr)
+{
+ struct brcmf_bus *bus;
- /* Disable F2 to clear any intermediate frame state on the dongle */
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
- SDIO_FUNC_ENABLE_1, NULL);
+ brcmf_dbg(TIMER, "Enter\n");
- /* WAR: cmd52 backplane read so core HW will drop ALPReq */
- clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
- 0, NULL);
+ bus = drvr->bus;
- /* Done with backplane-dependent accesses, can drop clock... */
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- 0, NULL);
+ /* Ignore the timer if simulating bus down */
+ if (bus->sleeping)
+ return false;
- bus->ci = ci;
- return 0;
-fail:
- bus->ci = NULL;
- kfree(ci);
- return err;
+ down(&bus->sdsem);
+
+ /* Poll period: check device if appropriate. */
+ if (bus->poll && (++bus->polltick >= bus->pollrate)) {
+ u32 intstatus = 0;
+
+ /* Reset poll tick */
+ bus->polltick = 0;
+
+ /* Check device if no interrupts */
+ if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
+
+ if (!bus->dpc_sched) {
+ u8 devpend;
+ devpend = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_0, SDIO_CCCR_INTx,
+ NULL);
+ intstatus =
+ devpend & (INTR_STATUS_FUNC1 |
+ INTR_STATUS_FUNC2);
+ }
+
+ /* If there is something, make like the ISR and
+ schedule the DPC */
+ if (intstatus) {
+ bus->pollcnt++;
+ bus->ipend = true;
+
+ bus->dpc_sched = true;
+ if (bus->dpc_tsk)
+ complete(&bus->dpc_wait);
+ }
+ }
+
+ /* Update interrupt tracking */
+ bus->lastintrs = bus->intrcount;
+ }
+#ifdef BCMDBG
+ /* Poll for console output periodically */
+ if (drvr->busstate == BRCMF_BUS_DATA && bus->console_interval != 0) {
+ bus->console.count += BRCMF_WD_POLL_MS;
+ if (bus->console.count >= bus->console_interval) {
+ bus->console.count -= bus->console_interval;
+ /* Make sure backplane clock is on */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ if (brcmf_sdbrcm_readconsole(bus) < 0)
+ /* stop on error */
+ bus->console_interval = 0;
+ }
+ }
+#endif /* BCMDBG */
+
+ /* On idle timeout clear activity flag and/or turn off clock */
+ if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
+ if (++bus->idlecount >= bus->idletime) {
+ bus->idlecount = 0;
+ if (bus->activity) {
+ bus->activity = false;
+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
+ } else {
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ }
+ }
+ }
+
+ up(&bus->sdsem);
+
+ return bus->ipend;
}
-static void
-brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase)
+static bool brcmf_sdbrcm_chipmatch(u16 chipid)
{
- u32 regdata;
+ if (chipid == BCM4329_CHIP_ID)
+ return true;
+ return false;
+}
- /*
- * Must do the disable sequence first to work for
- * arbitrary current core state.
- */
- brcmf_sdbrcm_chip_disablecore(card, corebase);
+static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus)
+{
+ brcmf_dbg(TRACE, "Enter\n");
- /*
- * Now do the initialization sequence.
- * set reset while enabling the clock and
- * forcing them on throughout the core
- */
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
- ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
- SBTML_RESET);
- udelay(1);
+ kfree(bus->rxbuf);
+ bus->rxctl = bus->rxbuf = NULL;
+ bus->rxlen = 0;
- regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatehigh),
- 4);
- if (regdata & SBTMH_SERR)
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatehigh),
- 4, 0);
+ kfree(bus->databuf);
+ bus->databuf = NULL;
+}
- regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbimstate), 4);
- if (regdata & (SBIM_IBE | SBIM_TO))
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbimstate), 4,
- regdata & ~(SBIM_IBE | SBIM_TO));
+static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus)
+{
+ brcmf_dbg(TRACE, "Enter\n");
- /* clear reset and allow it to propagate throughout the core */
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
- (SICF_FGC << SBTML_SICF_SHIFT) |
- (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
- udelay(1);
+ if (bus->drvr->maxctl) {
+ bus->rxblen =
+ roundup((bus->drvr->maxctl + SDPCM_HDRLEN),
+ ALIGNMENT) + BRCMF_SDALIGN;
+ bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
+ if (!(bus->rxbuf))
+ goto fail;
+ }
- /* leave clock enabled */
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
- (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
- udelay(1);
+ /* Allocate buffer to receive glomed packet */
+ bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC);
+ if (!(bus->databuf)) {
+ /* release rxbuf which was already located as above */
+ if (!bus->rxblen)
+ kfree(bus->rxbuf);
+ goto fail;
+ }
+
+ /* Align the buffer */
+ if ((unsigned long)bus->databuf % BRCMF_SDALIGN)
+ bus->dataptr = bus->databuf + (BRCMF_SDALIGN -
+ ((unsigned long)bus->databuf % BRCMF_SDALIGN));
+ else
+ bus->dataptr = bus->databuf;
+
+ return true;
+
+fail:
+ return false;
}
/* SDIO Pad drive strength to select value mappings */
@@ -6499,8 +3998,17 @@ static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
-static void
-brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, u32 drivestrength) {
+static char *brcmf_chipname(uint chipid, char *buf, uint len)
+{
+ const char *fmt;
+
+ fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
+ snprintf(buf, len, fmt, chipid);
+ return buf;
+}
+
+static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus,
+ u32 drivestrength) {
struct sdiod_drive_str *str_tab = NULL;
u32 str_mask = 0;
u32 str_shift = 0;
@@ -6527,10 +4035,9 @@ brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, u32 drivestrength)
str_shift = 11;
break;
default:
- BRCMF_ERROR(("No SDIO Drive strength init"
- "done for chip %s rev %d pmurev %d\n",
- brcmu_chipname(bus->ci->chip, chn, 8),
- bus->ci->chiprev, bus->ci->pmurev));
+ brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
+ brcmf_chipname(bus->ci->chip, chn, 8),
+ bus->ci->chiprev, bus->ci->pmurev);
break;
}
@@ -6546,48 +4053,287 @@ brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, u32 drivestrength)
}
}
- brcmf_sdcard_reg_write(bus->card,
+ brcmf_sdcard_reg_write(bus->sdiodev,
CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
4, 1);
- cc_data_temp = brcmf_sdcard_reg_read(bus->card,
+ cc_data_temp = brcmf_sdcard_reg_read(bus->sdiodev,
CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4);
cc_data_temp &= ~str_mask;
drivestrength_sel <<= str_shift;
cc_data_temp |= drivestrength_sel;
- brcmf_sdcard_reg_write(bus->card,
+ brcmf_sdcard_reg_write(bus->sdiodev,
CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
4, cc_data_temp);
- BRCMF_INFO(("SDIO: %dmA drive strength selected, "
- "set to 0x%08x\n", drivestrength, cc_data_temp));
+ brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
+ drivestrength, cc_data_temp);
}
}
-static void
-brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus)
+static int
+brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci, u32 regs)
{
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ u32 regdata;
- kfree(bus->ci);
+ /*
+ * Get CC core rev
+ * Chipid is assume to be at offset 0 from regs arg
+ * For different chiptypes or old sdio hosts w/o chipcommon,
+ * other ways of recognition should be added here.
+ */
+ ci->cccorebase = regs;
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_CC_REG(ci->cccorebase, chipid), 4);
+ ci->chip = regdata & CID_ID_MASK;
+ ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
+
+ brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
+
+ /* Address of cores for new chips should be added here */
+ switch (ci->chip) {
+ case BCM4329_CHIP_ID:
+ ci->buscorebase = BCM4329_CORE_BUS_BASE;
+ ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
+ ci->armcorebase = BCM4329_CORE_ARM_BASE;
+ ci->ramsize = BCM4329_RAMSIZE;
+ break;
+ default:
+ brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
+ return -ENODEV;
+ }
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(ci->cccorebase, sbidhigh), 4);
+ ci->ccrev = SBCOREREV(regdata);
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
+ ci->pmurev = regdata & PCAP_REV_MASK;
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(ci->buscorebase, sbidhigh), 4);
+ ci->buscorerev = SBCOREREV(regdata);
+ ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
+
+ brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
+ ci->ccrev, ci->pmurev, ci->buscorerev, ci->buscoretype);
+
+ /* get chipcommon capabilites */
+ ci->cccaps = brcmf_sdcard_reg_read(sdiodev,
+ CORE_CC_REG(ci->cccorebase, capabilities), 4);
+
+ return 0;
+}
+
+static int
+brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs)
+{
+ struct chip_info *ci;
+ int err;
+ u8 clkval, clkset;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* alloc chip_info_t */
+ ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
+ if (NULL == ci)
+ return -ENOMEM;
+
+ /* bus/core/clk setup for register access */
+ /* Try forcing SDIO core to do ALPAvail request only */
+ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
+ if (err) {
+ brcmf_dbg(ERROR, "error writing for HT off\n");
+ goto fail;
+ }
+
+ /* If register supported, wait for ALPAvail and then force ALP */
+ /* This may take up to 15 milliseconds */
+ clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, NULL);
+ if ((clkval & ~SBSDIO_AVBITS) == clkset) {
+ SPINWAIT(((clkval =
+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ NULL)),
+ !SBSDIO_ALPAV(clkval)),
+ PMU_MAX_TRANSITION_DLY);
+ if (!SBSDIO_ALPAV(clkval)) {
+ brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
+ clkval);
+ err = -EBUSY;
+ goto fail;
+ }
+ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF |
+ SBSDIO_FORCE_ALP;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ clkset, &err);
+ udelay(65);
+ } else {
+ brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
+ clkset, clkval);
+ err = -EACCES;
+ goto fail;
+ }
+
+ /* Also, disable the extra SDIO pull-ups */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
+
+ err = brcmf_sdbrcm_chip_recognition(bus->sdiodev, ci, regs);
+ if (err)
+ goto fail;
+
+ /*
+ * Make sure any on-chip ARM is off (in case strapping is wrong),
+ * or downloaded code was already running.
+ */
+ brcmf_sdbrcm_chip_disablecore(bus->sdiodev, ci->armcorebase);
+
+ brcmf_sdcard_reg_write(bus->sdiodev,
+ CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
+ brcmf_sdcard_reg_write(bus->sdiodev,
+ CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
+
+ /* Disable F2 to clear any intermediate frame state on the dongle */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+ SDIO_FUNC_ENABLE_1, NULL);
+
+ /* WAR: cmd52 backplane read so core HW will drop ALPReq */
+ clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ 0, NULL);
+
+ /* Done with backplane-dependent accesses, can drop clock... */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+
+ bus->ci = ci;
+ return 0;
+fail:
bus->ci = NULL;
+ kfree(ci);
+ return err;
}
-static void
-brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar)
+static bool
+brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
{
- brcmf_sdbrcm_sdunlock(bus);
- wait_event_interruptible_timeout(bus->ctrl_wait,
- (*lockvar == false), HZ * 2);
- brcmf_sdbrcm_sdlock(bus);
- return;
+ u8 clkctl = 0;
+ int err = 0;
+ int reg_addr;
+ u32 reg_val;
+
+ bus->alp_only = true;
+
+ /* Return the window to backplane enumeration space for core access */
+ if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, SI_ENUM_BASE))
+ brcmf_dbg(ERROR, "FAILED to return to SI_ENUM_BASE\n");
+
+#ifdef BCMDBG
+ printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n",
+ brcmf_sdcard_reg_read(bus->sdiodev, SI_ENUM_BASE, 4));
+
+#endif /* BCMDBG */
+
+ /*
+ * Force PLL off until brcmf_sdbrcm_chip_attach()
+ * programs PLL control regs
+ */
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ BRCMF_INIT_CLKCTL1, &err);
+ if (!err)
+ clkctl =
+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
+
+ if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
+ brcmf_dbg(ERROR, "ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
+ err, BRCMF_INIT_CLKCTL1, clkctl);
+ goto fail;
+ }
+
+ if (brcmf_sdbrcm_chip_attach(bus, regsva)) {
+ brcmf_dbg(ERROR, "brcmf_sdbrcm_chip_attach failed!\n");
+ goto fail;
+ }
+
+ if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) {
+ brcmf_dbg(ERROR, "unsupported chip: 0x%04x\n", bus->ci->chip);
+ goto fail;
+ }
+
+ brcmf_sdbrcm_sdiod_drive_strength_init(bus, SDIO_DRIVE_STRENGTH);
+
+ /* Get info on the ARM and SOCRAM cores... */
+ brcmf_sdcard_reg_read(bus->sdiodev,
+ CORE_SB(bus->ci->armcorebase, sbidhigh), 4);
+ bus->ramsize = bus->ci->ramsize;
+ if (!(bus->ramsize)) {
+ brcmf_dbg(ERROR, "failed to find SOCRAM memory!\n");
+ goto fail;
+ }
+
+ /* Set core control so an SDIO reset does a backplane reset */
+ reg_addr = bus->ci->buscorebase +
+ offsetof(struct sdpcmd_regs, corecontrol);
+ reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32));
+ brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32),
+ reg_val | CC_BPRESEN);
+
+ brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
+
+ /* Locate an appropriately-aligned portion of hdrbuf */
+ bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0],
+ BRCMF_SDALIGN);
+
+ /* Set the poll and/or interrupt flags */
+ bus->intr = true;
+ bus->poll = false;
+ if (bus->poll)
+ bus->pollrate = 1;
+
+ return true;
+
+fail:
+ return false;
}
-static void
-brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus)
+static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus)
{
- if (waitqueue_active(&bus->ctrl_wait))
- wake_up_interruptible(&bus->ctrl_wait);
- return;
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Disable F2 to clear any intermediate frame state on the dongle */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+ SDIO_FUNC_ENABLE_1, NULL);
+
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
+ bus->sleeping = false;
+ bus->rxflow = false;
+
+ /* Done with backplane-dependent accesses, can drop clock... */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+
+ /* ...and initialize clock/power states */
+ bus->clkstate = CLK_SDONLY;
+ bus->idletime = BRCMF_IDLE_INTERVAL;
+ bus->idleclock = BRCMF_IDLE_ACTIVE;
+
+ /* Query the F2 block size, set roundup accordingly */
+ bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
+ bus->roundup = min(max_roundup, bus->blocksize);
+
+ /* bus module does not support packet chaining */
+ bus->use_rxchain = false;
+ bus->sd_rxchain = false;
+
+ return true;
}
static int
@@ -6595,24 +4341,13 @@ brcmf_sdbrcm_watchdog_thread(void *data)
{
struct brcmf_bus *bus = (struct brcmf_bus *)data;
- /* This thread doesn't need any user-level access,
- * so get rid of all our resources
- */
- if (brcmf_watchdog_prio > 0) {
- struct sched_param param;
- param.sched_priority = (brcmf_watchdog_prio < MAX_RT_PRIO) ?
- brcmf_watchdog_prio : (MAX_RT_PRIO - 1);
- sched_setscheduler(current, SCHED_FIFO, &param);
- }
-
allow_signal(SIGTERM);
/* Run until signal received */
while (1) {
if (kthread_should_stop())
break;
if (!wait_for_completion_interruptible(&bus->watchdog_wait)) {
- if (bus->drvr->dongle_reset == false)
- brcmf_sdbrcm_bus_watchdog(bus->drvr);
+ brcmf_sdbrcm_bus_watchdog(bus->drvr);
/* Count the tick for reference */
bus->drvr->tickcnt++;
} else
@@ -6626,147 +4361,237 @@ brcmf_sdbrcm_watchdog(unsigned long data)
{
struct brcmf_bus *bus = (struct brcmf_bus *)data;
- if (brcmf_watchdog_prio >= 0) {
- if (bus->watchdog_tsk)
- complete(&bus->watchdog_wait);
- else
- return;
- } else {
- brcmf_sdbrcm_bus_watchdog(bus->drvr);
-
- /* Count the tick for reference */
- bus->drvr->tickcnt++;
+ if (bus->watchdog_tsk) {
+ complete(&bus->watchdog_wait);
+ /* Reschedule the watchdog */
+ if (bus->wd_timer_valid)
+ mod_timer(&bus->timer,
+ jiffies + BRCMF_WD_POLL_MS * HZ / 1000);
}
-
- /* Reschedule the watchdog */
- if (bus->wd_timer_valid)
- mod_timer(&bus->timer, jiffies + brcmf_watchdog_ms * HZ / 1000);
}
-void
-brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
+static void
+brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus)
{
- static uint save_ms;
+ brcmf_dbg(TRACE, "Enter\n");
- /* don't start the wd until fw is loaded */
- if (bus->drvr->busstate == BRCMF_BUS_DOWN)
- return;
+ kfree(bus->ci);
+ bus->ci = NULL;
+}
- /* Totally stop the timer */
- if (!wdtick && bus->wd_timer_valid == true) {
- del_timer_sync(&bus->timer);
- bus->wd_timer_valid = false;
- save_ms = wdtick;
- return;
+static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ if (bus->ci) {
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ brcmf_sdbrcm_chip_detach(bus);
+ if (bus->vars && bus->varsz)
+ kfree(bus->vars);
+ bus->vars = NULL;
}
- if (wdtick) {
- brcmf_watchdog_ms = (uint) wdtick;
+ brcmf_dbg(TRACE, "Disconnected\n");
+}
- if (save_ms != brcmf_watchdog_ms) {
- if (bus->wd_timer_valid == true)
- /* Stop timer and restart at new value */
- del_timer_sync(&bus->timer);
+/* Detach and free everything */
+static void brcmf_sdbrcm_release(struct brcmf_bus *bus)
+{
+ brcmf_dbg(TRACE, "Enter\n");
- /* Create timer again when watchdog period is
- dynamically changed or in the first instance
- */
- bus->timer.expires =
- jiffies + brcmf_watchdog_ms * HZ / 1000;
- add_timer(&bus->timer);
+ if (bus) {
+ /* De-register interrupt handler */
+ brcmf_sdcard_intr_dereg(bus->sdiodev);
- } else {
- /* Re arm the timer, at last watchdog period */
- mod_timer(&bus->timer,
- jiffies + brcmf_watchdog_ms * HZ / 1000);
+ if (bus->drvr) {
+ brcmf_detach(bus->drvr);
+ brcmf_sdbrcm_release_dongle(bus);
+ bus->drvr = NULL;
}
- bus->wd_timer_valid = true;
- save_ms = wdtick;
+ brcmf_sdbrcm_release_malloc(bus);
+
+ kfree(bus);
}
+
+ brcmf_dbg(TRACE, "Disconnected\n");
}
-static int brcmf_sdbrcm_dpc_thread(void *data)
+void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
+ u32 regsva, struct brcmf_sdio_dev *sdiodev)
{
- struct brcmf_bus *bus = (struct brcmf_bus *) data;
+ int ret;
+ struct brcmf_bus *bus;
- /* This thread doesn't need any user-level access,
- * so get rid of all our resources
+ /* Init global variables at run-time, not as part of the declaration.
+ * This is required to support init/de-init of the driver.
+ * Initialization
+ * of globals as part of the declaration results in non-deterministic
+ * behavior since the value of the globals may be different on the
+ * first time that the driver is initialized vs subsequent
+ * initializations.
*/
- if (brcmf_dpc_prio > 0) {
- struct sched_param param;
- param.sched_priority = (brcmf_dpc_prio < MAX_RT_PRIO) ?
- brcmf_dpc_prio : (MAX_RT_PRIO - 1);
- sched_setscheduler(current, SCHED_FIFO, &param);
+ brcmf_c_init();
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* We make an assumption about address window mappings:
+ * regsva == SI_ENUM_BASE*/
+
+ /* Allocate private bus interface state */
+ bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
+ if (!bus)
+ goto fail;
+
+ bus->sdiodev = sdiodev;
+ sdiodev->bus = bus;
+ bus->txbound = BRCMF_TXBOUND;
+ bus->rxbound = BRCMF_RXBOUND;
+ bus->txminmax = BRCMF_TXMINMAX;
+ bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
+ bus->usebufpool = false; /* Use bufpool if allocated,
+ else use locally malloced rxbuf */
+
+ /* attempt to attach to the dongle */
+ if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) {
+ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_attach failed\n");
+ goto fail;
}
- allow_signal(SIGTERM);
- /* Run until signal received */
- while (1) {
- if (kthread_should_stop())
- break;
- if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
- /* Call bus dpc unless it indicated down
- (then clean stop) */
- if (bus->drvr->busstate != BRCMF_BUS_DOWN) {
- if (brcmf_sdbrcm_dpc(bus))
- complete(&bus->dpc_wait);
- } else {
- brcmf_sdbrcm_bus_stop(bus, true);
- }
- } else
- break;
+ spin_lock_init(&bus->txqlock);
+ init_waitqueue_head(&bus->ctrl_wait);
+ init_waitqueue_head(&bus->dcmd_resp_wait);
+
+ /* Set up the watchdog timer */
+ init_timer(&bus->timer);
+ bus->timer.data = (unsigned long)bus;
+ bus->timer.function = brcmf_sdbrcm_watchdog;
+
+ /* Initialize thread based operation and lock */
+ sema_init(&bus->sdsem, 1);
+
+ /* Initialize watchdog thread */
+ init_completion(&bus->watchdog_wait);
+ bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread,
+ bus, "brcmf_watchdog");
+ if (IS_ERR(bus->watchdog_tsk)) {
+ printk(KERN_WARNING
+ "brcmf_watchdog thread failed to start\n");
+ bus->watchdog_tsk = NULL;
+ }
+ /* Initialize DPC thread */
+ init_completion(&bus->dpc_wait);
+ bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
+ bus, "brcmf_dpc");
+ if (IS_ERR(bus->dpc_tsk)) {
+ printk(KERN_WARNING
+ "brcmf_dpc thread failed to start\n");
+ bus->dpc_tsk = NULL;
}
- return 0;
-}
-static void brcmf_sdbrcm_dpc_tasklet(unsigned long data)
-{
- struct brcmf_bus *bus = (struct brcmf_bus *) data;
+ /* Attach to the brcmf/OS/network interface */
+ bus->drvr = brcmf_attach(bus, SDPCM_RESERVE);
+ if (!bus->drvr) {
+ brcmf_dbg(ERROR, "brcmf_attach failed\n");
+ goto fail;
+ }
- /* Call bus dpc unless it indicated down (then clean stop) */
- if (bus->drvr->busstate != BRCMF_BUS_DOWN) {
- if (brcmf_sdbrcm_dpc(bus))
- tasklet_schedule(&bus->tasklet);
- } else
- brcmf_sdbrcm_bus_stop(bus, true);
-}
+ /* Allocate buffers */
+ if (!(brcmf_sdbrcm_probe_malloc(bus))) {
+ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_malloc failed\n");
+ goto fail;
+ }
-static void brcmf_sdbrcm_sched_dpc(struct brcmf_bus *bus)
-{
- if (bus->dpc_tsk) {
- complete(&bus->dpc_wait);
- return;
+ if (!(brcmf_sdbrcm_probe_init(bus))) {
+ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_init failed\n");
+ goto fail;
}
- tasklet_schedule(&bus->tasklet);
+ /* Register interrupt callback, but mask it (not operational yet). */
+ brcmf_dbg(INTR, "disable SDIO interrupts (not interested yet)\n");
+ ret = brcmf_sdcard_intr_reg(bus->sdiodev);
+ if (ret != 0) {
+ brcmf_dbg(ERROR, "FAILED: sdcard_intr_reg returned %d\n", ret);
+ goto fail;
+ }
+ brcmf_dbg(INTR, "registered SDIO interrupt function ok\n");
+
+ brcmf_dbg(INFO, "completed!!\n");
+
+ /* if firmware path present try to download and bring up bus */
+ ret = brcmf_bus_start(bus->drvr);
+ if (ret != 0) {
+ if (ret == -ENOLINK) {
+ brcmf_dbg(ERROR, "dongle is not responding\n");
+ goto fail;
+ }
+ }
+ /* Ok, have the per-port tell the stack we're open for business */
+ if (brcmf_net_attach(bus->drvr, 0) != 0) {
+ brcmf_dbg(ERROR, "Net attach failed!!\n");
+ goto fail;
+ }
+
+ return bus;
+
+fail:
+ brcmf_sdbrcm_release(bus);
+ return NULL;
}
-static void brcmf_sdbrcm_sdlock(struct brcmf_bus *bus)
+void brcmf_sdbrcm_disconnect(void *ptr)
{
- if (bus->threads_only)
- down(&bus->sdsem);
- else
- spin_lock_bh(&bus->sdlock);
+ struct brcmf_bus *bus = (struct brcmf_bus *)ptr;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ if (bus)
+ brcmf_sdbrcm_release(bus);
+
+ brcmf_dbg(TRACE, "Disconnected\n");
}
-static void brcmf_sdbrcm_sdunlock(struct brcmf_bus *bus)
+struct device *brcmf_bus_get_device(struct brcmf_bus *bus)
{
- if (bus->threads_only)
- up(&bus->sdsem);
- else
- spin_unlock_bh(&bus->sdlock);
+ return &bus->sdiodev->func[2]->dev;
}
-static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus)
+void
+brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
{
- if (bus->firmware->size < bus->fw_ptr + len)
- len = bus->firmware->size - bus->fw_ptr;
+ /* don't start the wd until fw is loaded */
+ if (bus->drvr->busstate == BRCMF_BUS_DOWN)
+ return;
- memcpy(buf, &bus->firmware->data[bus->fw_ptr], len);
- bus->fw_ptr += len;
- return len;
-}
+ /* Totally stop the timer */
+ if (!wdtick && bus->wd_timer_valid == true) {
+ del_timer_sync(&bus->timer);
+ bus->wd_timer_valid = false;
+ bus->save_ms = wdtick;
+ return;
+ }
-MODULE_FIRMWARE(BCM4329_FW_NAME);
-MODULE_FIRMWARE(BCM4329_NV_NAME);
+ if (wdtick) {
+ if (bus->save_ms != BRCMF_WD_POLL_MS) {
+ if (bus->wd_timer_valid == true)
+ /* Stop timer and restart at new value */
+ del_timer_sync(&bus->timer);
+
+ /* Create timer again when watchdog period is
+ dynamically changed or in the first instance
+ */
+ bus->timer.expires =
+ jiffies + BRCMF_WD_POLL_MS * HZ / 1000;
+ add_timer(&bus->timer);
+
+ } else {
+ /* Re arm the timer, at last watchdog period */
+ mod_timer(&bus->timer,
+ jiffies + BRCMF_WD_POLL_MS * HZ / 1000);
+ }
+
+ bus->wd_timer_valid = true;
+ bus->save_ms = wdtick;
+ }
+}
diff --git a/drivers/staging/brcm80211/brcmfmac/sdio_host.h b/drivers/staging/brcm80211/brcmfmac/sdio_host.h
index d34547215060..726fa8981113 100644
--- a/drivers/staging/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/staging/brcm80211/brcmfmac/sdio_host.h
@@ -18,7 +18,6 @@
#define _BRCM_SDH_H_
#include <linux/skbuff.h>
-extern const uint brcmf_sdio_msglevel;
#define SDIO_FUNC_0 0
#define SDIO_FUNC_1 1
@@ -41,46 +40,71 @@ extern const uint brcmf_sdio_msglevel;
/* Maximum number of I/O funcs */
#define SDIOD_MAX_IOFUNCS 7
-#define SBSDIO_NUM_FUNCTION 3 /* as of sdiod rev 0, supports 3 functions */
+/* as of sdiod rev 0, supports 3 functions */
+#define SBSDIO_NUM_FUNCTION 3
/* function 1 miscellaneous registers */
-#define SBSDIO_SPROM_CS 0x10000 /* sprom command and status */
-#define SBSDIO_SPROM_INFO 0x10001 /* sprom info register */
-#define SBSDIO_SPROM_DATA_LOW 0x10002 /* sprom indirect access data byte 0 */
-#define SBSDIO_SPROM_DATA_HIGH 0x10003 /* sprom indirect access data byte 1 */
-#define SBSDIO_SPROM_ADDR_LOW 0x10004 /* sprom indirect access addr byte 0 */
-#define SBSDIO_SPROM_ADDR_HIGH 0x10005 /* sprom indirect access addr byte 0 */
-#define SBSDIO_CHIP_CTRL_DATA 0x10006 /* xtal_pu (gpio) output */
-#define SBSDIO_CHIP_CTRL_EN 0x10007 /* xtal_pu (gpio) enable */
-#define SBSDIO_WATERMARK 0x10008 /* rev < 7, watermark for sdio device */
-#define SBSDIO_DEVICE_CTL 0x10009 /* control busy signal generation */
-
-/* registers introduced in rev 8, some content (mask/bits) defs in sbsdpcmdev.h */
-#define SBSDIO_FUNC1_SBADDRLOW 0x1000A /* SB Address Window Low (b15) */
-#define SBSDIO_FUNC1_SBADDRMID 0x1000B /* SB Address Window Mid (b23:b16) */
-#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C /* SB Address Window High (b31:b24) */
-#define SBSDIO_FUNC1_FRAMECTRL 0x1000D /* Frame Control (frame term/abort) */
-#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E /* ChipClockCSR (ALP/HT ctl/status) */
-#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F /* SdioPullUp (on cmd, d0-d2) */
-#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 /* Write Frame Byte Count Low */
-#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A /* Write Frame Byte Count High */
-#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B /* Read Frame Byte Count Low */
-#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C /* Read Frame Byte Count High */
+
+/* sprom command and status */
+#define SBSDIO_SPROM_CS 0x10000
+/* sprom info register */
+#define SBSDIO_SPROM_INFO 0x10001
+/* sprom indirect access data byte 0 */
+#define SBSDIO_SPROM_DATA_LOW 0x10002
+/* sprom indirect access data byte 1 */
+#define SBSDIO_SPROM_DATA_HIGH 0x10003
+/* sprom indirect access addr byte 0 */
+#define SBSDIO_SPROM_ADDR_LOW 0x10004
+/* sprom indirect access addr byte 0 */
+#define SBSDIO_SPROM_ADDR_HIGH 0x10005
+/* xtal_pu (gpio) output */
+#define SBSDIO_CHIP_CTRL_DATA 0x10006
+/* xtal_pu (gpio) enable */
+#define SBSDIO_CHIP_CTRL_EN 0x10007
+/* rev < 7, watermark for sdio device */
+#define SBSDIO_WATERMARK 0x10008
+/* control busy signal generation */
+#define SBSDIO_DEVICE_CTL 0x10009
+
+/* SB Address Window Low (b15) */
+#define SBSDIO_FUNC1_SBADDRLOW 0x1000A
+/* SB Address Window Mid (b23:b16) */
+#define SBSDIO_FUNC1_SBADDRMID 0x1000B
+/* SB Address Window High (b31:b24) */
+#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C
+/* Frame Control (frame term/abort) */
+#define SBSDIO_FUNC1_FRAMECTRL 0x1000D
+/* ChipClockCSR (ALP/HT ctl/status) */
+#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E
+/* SdioPullUp (on cmd, d0-d2) */
+#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F
+/* Write Frame Byte Count Low */
+#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019
+/* Write Frame Byte Count High */
+#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A
+/* Read Frame Byte Count Low */
+#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B
+/* Read Frame Byte Count High */
+#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C
#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */
/* function 1 OCP space */
-#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF /* sb offset addr is <= 15 bits, 32k */
+
+/* sb offset addr is <= 15 bits, 32k */
+#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF
#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000
-#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 /* with b15, maps to 32-bit SB access */
+/* with b15, maps to 32-bit SB access */
+#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000
-/* some duplication with sbsdpcmdev.h here */
/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
+
#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */
#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */
#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */
-#define SBSDIO_SBWINDOW_MASK 0xffff8000 /* Address bits from SBADDR regs */
+/* Address bits from SBADDR regs */
+#define SBSDIO_SBWINDOW_MASK 0xffff8000
#define SDIOH_READ 0 /* Read request */
#define SDIOH_WRITE 1 /* Write request */
@@ -92,68 +116,32 @@ extern const uint brcmf_sdio_msglevel;
#define SUCCESS 0
#define ERROR 1
-/* forward declarations */
-struct brcmf_sdio_card;
-
struct brcmf_sdreg {
int func;
int offset;
int value;
};
-struct sdioh_info {
- struct osl_info *osh; /* osh handler */
- bool client_intr_enabled; /* interrupt connnected flag */
- bool intr_handler_valid; /* client driver interrupt handler valid */
- void (*intr_handler)(void *); /* registered interrupt handler */
- void *intr_handler_arg; /* argument to call interrupt handler */
- u16 intmask; /* Current active interrupts */
- void *sdos_info; /* Pointer to per-OS private data */
-
- uint irq; /* Client irq */
- int intrcount; /* Client interrupts */
- bool sd_blockmode; /* sd_blockmode == false => 64 Byte Cmd 53s. */
- /* Must be on for sd_multiblock to be effective */
- bool use_client_ints; /* If this is false, make sure to restore */
- int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
- u8 num_funcs; /* Supported funcs on client */
- u32 com_cis_ptr;
+struct brcmf_sdio_dev {
+ struct sdio_func *func[SDIO_MAX_FUNCS];
+ u8 num_funcs; /* Supported funcs on client */
u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
- uint max_dma_len;
- uint max_dma_descriptors; /* DMA Descriptors supported by this controller. */
- /* SDDMA_DESCRIPTOR SGList[32]; *//* Scatter/Gather DMA List */
-};
+ u32 sbwad; /* Save backplane window address */
+ bool regfail; /* status of last reg_r/w call */
+ void *bus;
+ atomic_t suspend; /* suspend flag */
+ wait_queue_head_t request_byte_wait;
+ wait_queue_head_t request_word_wait;
+ wait_queue_head_t request_packet_wait;
+ wait_queue_head_t request_buffer_wait;
-struct brcmf_sdmmc_instance {
- struct sdioh_info *sd;
- struct sdio_func *func[SDIOD_MAX_IOFUNCS];
- u32 host_claimed;
};
-/* Attach and build an interface to the underlying SD host driver.
- * - Allocates resources (structs, arrays, mem, OS handles, etc) needed by
- * brcmf_sdcard.
- * - Returns the sdio card handle and virtual address base for register access.
- * The returned handle should be used in all subsequent calls, but the bcmsh
- * implementation may maintain a single "default" handle (e.g. the first or
- * most recent one) to enable single-instance implementations to pass NULL.
- */
-extern struct brcmf_sdio_card*
-brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq);
-
-/* Detach - freeup resources allocated in attach */
-extern int brcmf_sdcard_detach(struct brcmf_sdio_card *card);
-
-/* Enable/disable SD interrupt */
-extern int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card);
-extern int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card);
-
/* Register/deregister device interrupt handler. */
extern int
-brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
- void (*fn)(void *), void *argh);
+brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev);
-extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card);
+extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev);
/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
* fn: function number
@@ -161,44 +149,25 @@ extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card);
* data: data byte to write
* err: pointer to error code (or NULL)
*/
-extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint func,
+extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint func,
u32 addr, int *err);
-extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint func,
+extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint func,
u32 addr, u8 data, int *err);
-/* Read/Write 4bytes from/to cfg space */
-extern u32
-brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
- u32 addr, int *err);
-
-extern void brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card,
- uint fnc_num, u32 addr,
- u32 data, int *err);
-
-/* Read CIS content for specified function.
- * fn: function whose CIS is being requested (0 is common CIS)
- * cis: pointer to memory location to place results
- * length: number of bytes to read
- * Internally, this routine uses the values from the cis base regs (0x9-0xB)
- * to form an SDIO-space address to read the data from.
- */
-extern int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func,
- u8 *cis, uint length);
-
/* Synchronous access to device (client) core registers via CMD53 to F1.
* addr: backplane address (i.e. >= regsva from attach)
* size: register width in bytes (2 or 4)
* data: data for register write
*/
extern u32
-brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size);
+brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size);
extern u32
-brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
+brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
u32 data);
/* Indicate if last reg read/write failed */
-extern bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card);
+extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev);
/* Buffer transfer to/from device (client) core via cmd53.
* fn: function number
@@ -213,25 +182,20 @@ extern bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card);
* NOTE: Async operation is not currently supported.
*/
extern int
-brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
- uint flags, u8 *buf, uint nbytes, void *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle);
+brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt);
extern int
-brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
- uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle);
+brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt);
/* Flags bits */
-#define SDIO_REQ_4BYTE 0x1 /* Four-byte target (backplane) width (vs. two-byte) */
-#define SDIO_REQ_FIXED 0x2 /* Fixed address (FIFO) (vs. incrementing address) */
-#define SDIO_REQ_ASYNC 0x4 /* Async request (vs. sync request) */
-/* Pending (non-error) return code */
-#define BCME_PENDING 1
+/* Four-byte target (backplane) width (vs. two-byte) */
+#define SDIO_REQ_4BYTE 0x1
+/* Fixed address (FIFO) (vs. incrementing address) */
+#define SDIO_REQ_FIXED 0x2
+/* Async request (vs. sync request) */
+#define SDIO_REQ_ASYNC 0x4
/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
* rw: read or write (0/1)
@@ -240,108 +204,49 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
* nbytes: number of bytes to transfer to/from buf
* Returns 0 or error code.
*/
-extern int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
- u8 *buf, uint nbytes);
+extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw,
+ u32 addr, u8 *buf, uint nbytes);
/* Issue an abort to the specified function */
-extern int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn);
-
-/* Returns the "Device ID" of target device on the SDIO bus. */
-extern int brcmf_sdcard_query_device(struct brcmf_sdio_card *card);
-
-/* Miscellaneous knob tweaker. */
-extern int brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
- void *params, int plen, void *arg, int len,
- bool set);
-
-/* helper functions */
-
-/* callback functions */
-struct brcmf_sdioh_driver {
- /* attach to device */
- void *(*attach) (u16 vend_id, u16 dev_id, u16 bus, u16 slot,
- u16 func, uint bustype, u32 regsva, void *param);
- /* detach from device */
- void (*detach) (void *ch);
-};
-
-struct sdioh_info;
+extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
/* platform specific/high level functions */
-extern int brcmf_sdio_function_init(void);
-extern int brcmf_sdio_register(struct brcmf_sdioh_driver *driver);
-extern void brcmf_sdio_unregister(void);
-extern void brcmf_sdio_function_cleanup(void);
-extern int brcmf_sdio_probe(struct device *dev);
-extern int brcmf_sdio_remove(struct device *dev);
+extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
+extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev);
-/* Function to return current window addr */
-extern u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card);
-
-/* Allocate/init/free per-OS private data */
-extern int brcmf_sdioh_osinit(struct sdioh_info *sd);
-extern void brcmf_sdioh_osfree(struct sdioh_info *sd);
-
-/* Core interrupt enable/disable of device interrupts */
-extern void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd);
-extern void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd);
+extern int brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev,
+ u32 address);
/* attach, return handler on success, NULL if failed.
* The handler shall be provided by all subsequent calls. No local cache
* cfghdl points to the starting address of pci device mapped memory
*/
-extern struct sdioh_info *brcmf_sdioh_attach(void *cfghdl, uint irq);
-extern int brcmf_sdioh_detach(struct sdioh_info *si);
-
-extern int
-brcmf_sdioh_interrupt_register(struct sdioh_info *si,
- void (*sdioh_cb_fn)(void *), void *argh);
-
-extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *si);
-
-/* enable or disable SD interrupt */
-extern int
-brcmf_sdioh_interrupt_set(struct sdioh_info *si, bool enable_disable);
+extern int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev);
+extern void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev);
/* read or write one byte using cmd52 */
-extern int
-brcmf_sdioh_request_byte(struct sdioh_info *si, uint rw, uint fnc, uint addr,
- u8 *byte);
+extern int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw,
+ uint fnc, uint addr, u8 *byte);
/* read or write 2/4 bytes using cmd53 */
extern int
-brcmf_sdioh_request_word(struct sdioh_info *si, uint cmd_type,
+brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
uint rw, uint fnc, uint addr,
u32 *word, uint nbyte);
/* read or write any buffer using cmd53 */
extern int
-brcmf_sdioh_request_buffer(struct sdioh_info *si, uint pio_dma,
+brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
uint fix_inc, uint rw, uint fnc_num,
u32 addr, uint regwidth,
u32 buflen, u8 *buffer, struct sk_buff *pkt);
-/* get cis data */
-extern int
-brcmf_sdioh_cis_read(struct sdioh_info *si, uint fuc, u8 *cis, u32 length);
-
-extern int
-brcmf_sdioh_cfg_read(struct sdioh_info *si, uint fuc, u32 addr, u8 *data);
-extern int
-brcmf_sdioh_cfg_write(struct sdioh_info *si, uint fuc, u32 addr, u8 *data);
-
-/* handle iovars */
-extern int brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
- void *params, int plen, void *arg, int len, bool set);
-
-/* Issue abort to the specified function and clear controller as needed */
-extern int brcmf_sdioh_abort(struct sdioh_info *si, uint fnc);
-
/* Watchdog timer interface for pm ops */
-extern void brcmf_sdio_wdtmr_enable(bool enable);
-
-extern uint sd_msglevel; /* Debug message level */
-
-extern struct brcmf_sdmmc_instance *gInstance;
+extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev,
+ bool enable);
+extern void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
+ u32 regsva, struct brcmf_sdio_dev *sdiodev);
+extern void brcmf_sdbrcm_disconnect(void *ptr);
+extern void brcmf_sdbrcm_isr(void *arg);
#endif /* _BRCM_SDH_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
index 821206d3e536..d626ebd05aea 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
@@ -14,19 +14,18 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
+
#include <linux/kernel.h>
#include <linux/if_arp.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/netdevice.h>
-#include <linux/sched.h>
+#include <linux/bitops.h>
#include <linux/etherdevice.h>
-#include <linux/wireless.h>
#include <linux/ieee80211.h>
-#include <linux/mmc/sdio_func.h>
#include <linux/uaccess.h>
#include <net/cfg80211.h>
-#include <net/rtnetlink.h>
#include <brcmu_utils.h>
#include <defs.h>
@@ -34,306 +33,50 @@
#include "dhd.h"
#include "wl_cfg80211.h"
-static struct sdio_func *cfg80211_sdio_func;
-static struct brcmf_cfg80211_dev *cfg80211_dev;
-static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
-
-u32 brcmf_dbg_level = WL_DBG_ERR;
+#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
+ (sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
-/*
-** cfg80211_ops api/callback list
-*/
-static s32 brcmf_cfg80211_change_iface(struct wiphy *wiphy,
- struct net_device *ndev,
- enum nl80211_iftype type, u32 *flags,
- struct vif_params *params);
-static s32 __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
- struct cfg80211_scan_request *request,
- struct cfg80211_ssid *this_ssid);
-static s32 brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
- struct cfg80211_scan_request *request);
-static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
-static s32 brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_ibss_params *params);
-static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy,
- struct net_device *dev);
-static s32 brcmf_cfg80211_get_station(struct wiphy *wiphy,
- struct net_device *dev, u8 *mac,
- struct station_info *sinfo);
-static s32 brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy,
- struct net_device *dev, bool enabled,
- s32 timeout);
-static s32 brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
- struct net_device *dev,
- const u8 *addr,
- const struct cfg80211_bitrate_mask
- *mask);
-static int brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_cfg80211_disconnect(struct wiphy *wiphy,
- struct net_device *dev,
- u16 reason_code);
-static s32 brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
- enum nl80211_tx_power_setting type,
- s32 dbm);
-static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
-static s32 brcmf_cfg80211_config_default_key(struct wiphy *wiphy,
- struct net_device *dev, u8 key_idx,
- bool unicast, bool multicast);
-static s32 brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, bool pairwise, const u8 *mac_addr,
- struct key_params *params);
-static s32 brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, bool pairwise, const u8 *mac_addr);
-static s32 brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, bool pairwise, const u8 *mac_addr,
- void *cookie, void (*callback) (void *cookie,
- struct
- key_params *
- params));
-static s32 brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
- struct net_device *dev,
- u8 key_idx);
-static s32 brcmf_cfg80211_resume(struct wiphy *wiphy);
-static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
- struct cfg80211_wowlan *wow);
-static s32 brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_pmksa *pmksa);
-static s32 brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_pmksa *pmksa);
-static s32 brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy,
- struct net_device *dev);
-/*
-** event & event Q handlers for cfg80211 interfaces
-*/
-static s32 brcmf_create_event_handler(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_destroy_event_handler(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_event_handler(void *data);
-static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_lock_eq(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_unlock_eq(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_init_eq_lock(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el);
-static struct brcmf_cfg80211_event_q *
-brcmf_deq_event(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 type,
- const struct brcmf_event_msg *msg, void *data);
-static void brcmf_put_event(struct brcmf_cfg80211_event_q *e);
-static void brcmf_wakeup_event(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e,
- void *data);
-static s32 brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e,
- void *data);
-static s32 brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e,
- void *data);
-static s32 brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data,
- bool completed);
-static s32 brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data);
-static s32 brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data);
-
-/*
-** register/deregister sdio function
-*/
-static void brcmf_clear_sdio_func(void);
-
-/*
-** ioctl utilites
-*/
-static s32 brcmf_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
- s32 buf_len);
-static __used s32 brcmf_dev_bufvar_set(struct net_device *dev, s8 *name,
- s8 *buf, s32 len);
-static s32 brcmf_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
-static s32 brcmf_dev_intvar_get(struct net_device *dev, s8 *name,
- s32 *retval);
-static s32 brcmf_dev_ioctl(struct net_device *dev, u32 cmd, void *arg,
- u32 len);
-
-/*
-** cfg80211 set_wiphy_params utilities
-*/
-static s32 brcmf_set_frag(struct net_device *dev, u32 frag_threshold);
-static s32 brcmf_set_rts(struct net_device *dev, u32 frag_threshold);
-static s32 brcmf_set_retry(struct net_device *dev, u32 retry, bool l);
-
-/*
-** wl profile utilities
-*/
-static s32 brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
- const struct brcmf_event_msg *e,
- void *data, s32 item);
-static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item);
-static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof);
-
-/*
-** cfg80211 connect utilites
-*/
-static s32 brcmf_set_wpa_version(struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_set_auth_type(struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_set_set_cipher(struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_set_key_mgmt(struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_set_set_sharedkey(struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_ch_to_chanspec(int ch,
- struct brcmf_join_params *join_params, size_t *join_params_size);
-
-/*
-** information element utilities
-*/
-static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
- u8 t, u8 l, u8 *v);
-static s32 brcmf_mode_to_nl80211_iftype(s32 mode);
-static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
- struct device *dev);
-static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
- struct brcmf_bss_info *bi);
-static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, const u8 *mac_addr,
- struct key_params *params);
-
-/*
-** key indianess swap utilities
-*/
-static void swap_key_from_BE(struct brcmf_wsec_key *key);
-static void swap_key_to_BE(struct brcmf_wsec_key *key);
-
-/*
-** brcmf_cfg80211_priv memory init/deinit utilities
-*/
-static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv);
-
-static void brcmf_delay(u32 ms);
+static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
-/*
-** store/restore cfg80211 instance data
-*/
-static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data);
-static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev);
+static u32 brcmf_dbg_level = WL_DBG_ERR;
-/*
-** ibss mode utilities
-*/
static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv);
+static s32
+brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
+ struct net_device *ndev, const struct brcmf_event_msg *e,
+ bool completed);
-/*
-** dongle up/down , default configuration utilities
-*/
-static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
- const struct brcmf_event_msg *e);
-static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
- const struct brcmf_event_msg *e);
-static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
- const struct brcmf_event_msg *e);
-static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype);
-static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf);
-
-/*
-** dongle configuration utilities
-*/
-static s32 brcmf_dongle_eventmsg(struct net_device *ndev);
-static s32 brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
- s32 scan_unassoc_time, s32 scan_passive_time);
-static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv,
- bool need_lock);
-static s32 brcmf_dongle_roam(struct net_device *ndev, u32 roamvar,
- u32 bcn_timeout);
-
-/*
-** iscan handler
-*/
-static void brcmf_iscan_timer(unsigned long data);
-static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_iscan_thread(void *data);
-static s32 brcmf_dev_iovar_setbuf(struct net_device *dev, s8 *iovar,
- void *param, s32 paramlen, void *bufptr,
- s32 buflen);
-static s32 brcmf_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
- void *param, s32 paramlen, void *bufptr,
- s32 buflen);
-static s32 brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
- struct brcmf_ssid *ssid, u16 action);
-static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan);
-static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan,
- u32 *status,
- struct brcmf_scan_results **bss_list);
-static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
- bool aborted);
-static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el);
-static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data)
+{
+ dev->driver_data = data;
+}
-/*
-* find most significant bit set
-*/
-static __used u32 brcmf_find_msb(u16 bit16);
+static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev)
+{
+ void *data = NULL;
-/*
-* update pmklist to dongle
-*/
-static __used s32 brcmf_update_pmklist(struct net_device *dev,
- struct brcmf_cfg80211_pmk_list *pmk_list,
- s32 err);
+ if (dev)
+ data = dev->driver_data;
+ return data;
+}
-static void brcmf_set_mpc(struct net_device *ndev, int mpc);
+static
+struct brcmf_cfg80211_priv *brcmf_priv_get(struct brcmf_cfg80211_dev *cfg_dev)
+{
+ struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg_dev);
+ return ci->cfg_priv;
+}
-/*
-* debufs support
-*/
-static int
-brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv);
-
-#define WL_PRIV_GET() \
- ({ \
- struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg80211_dev); \
- if (unlikely(!ci)) { \
- WL_ERR("wl_cfg80211_dev is unavailable\n"); \
- BUG(); \
- } \
- ci->cfg_priv; \
-})
-
-#define CHECK_SYS_UP() \
-do { \
- struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); \
- if (unlikely(!test_bit(WL_STATUS_READY, &cfg_priv->status))) { \
- WL_INFO("device is not ready : status (%d)\n", \
- (int)cfg_priv->status); \
- return -EIO; \
- } \
-} while (0)
+static bool check_sys_up(struct wiphy *wiphy)
+{
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+ if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
+ WL_INFO("device is not ready : status (%d)\n",
+ (int)cfg_priv->status);
+ return false;
+ }
+ return true;
+}
#define CHAN2G(_channel, _freq, _flags) { \
.band = IEEE80211_BAND_2GHZ, \
@@ -510,48 +253,134 @@ static const u32 __wl_cipher_suites[] = {
WLAN_CIPHER_SUITE_AES_CMAC,
};
-static void swap_key_from_BE(struct brcmf_wsec_key *key)
+/* tag_ID/length/value_buffer tuple */
+struct brcmf_tlv {
+ u8 id;
+ u8 len;
+ u8 data[1];
+};
+
+/* Quarter dBm units to mW
+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
+ * Table is offset so the last entry is largest mW value that fits in
+ * a u16.
+ */
+
+#define QDBM_OFFSET 153 /* Offset for first entry */
+#define QDBM_TABLE_LEN 40 /* Table size */
+
+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
+ */
+#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
+
+/* Largest mW value that will round down to the last table entry,
+ * QDBM_OFFSET + QDBM_TABLE_LEN-1.
+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
+ * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
+ */
+#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
+
+static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
+/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
+/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
+/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
+/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
+/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
+/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
+};
+
+static u16 brcmf_qdbm_to_mw(u8 qdbm)
{
- key->index = cpu_to_le32(key->index);
- key->len = cpu_to_le32(key->len);
- key->algo = cpu_to_le32(key->algo);
- key->flags = cpu_to_le32(key->flags);
- key->rxiv.hi = cpu_to_le32(key->rxiv.hi);
- key->rxiv.lo = cpu_to_le16(key->rxiv.lo);
- key->iv_initialized = cpu_to_le32(key->iv_initialized);
+ uint factor = 1;
+ int idx = qdbm - QDBM_OFFSET;
+
+ if (idx >= QDBM_TABLE_LEN)
+ /* clamp to max u16 mW value */
+ return 0xFFFF;
+
+ /* scale the qdBm index up to the range of the table 0-40
+ * where an offset of 40 qdBm equals a factor of 10 mW.
+ */
+ while (idx < 0) {
+ idx += 40;
+ factor *= 10;
+ }
+
+ /* return the mW value scaled down to the correct factor of 10,
+ * adding in factor/2 to get proper rounding.
+ */
+ return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
}
-static void swap_key_to_BE(struct brcmf_wsec_key *key)
+static u8 brcmf_mw_to_qdbm(u16 mw)
{
- key->index = le32_to_cpu(key->index);
- key->len = le32_to_cpu(key->len);
- key->algo = le32_to_cpu(key->algo);
- key->flags = le32_to_cpu(key->flags);
- key->rxiv.hi = le32_to_cpu(key->rxiv.hi);
- key->rxiv.lo = le16_to_cpu(key->rxiv.lo);
- key->iv_initialized = le32_to_cpu(key->iv_initialized);
+ u8 qdbm;
+ int offset;
+ uint mw_uint = mw;
+ uint boundary;
+
+ /* handle boundary case */
+ if (mw_uint <= 1)
+ return 0;
+
+ offset = QDBM_OFFSET;
+
+ /* move mw into the range of the table */
+ while (mw_uint < QDBM_TABLE_LOW_BOUND) {
+ mw_uint *= 10;
+ offset -= 40;
+ }
+
+ for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
+ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
+ nqdBm_to_mW_map[qdbm]) / 2;
+ if (mw_uint < boundary)
+ break;
+ }
+
+ qdbm += (u8) offset;
+
+ return qdbm;
}
-static s32
-brcmf_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
+/* function for reading/writing a single u32 from/to the dongle */
+static int
+brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par)
{
- struct ifreq ifr;
- struct brcmf_ioctl ioc;
- mm_segment_t fs;
- s32 err = 0;
+ int err;
+ __le32 par_le = cpu_to_le32(*par);
+
+ err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32));
+ *par = le32_to_cpu(par_le);
+
+ return err;
+}
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = cmd;
- ioc.buf = arg;
- ioc.len = len;
- strcpy(ifr.ifr_name, dev->name);
- ifr.ifr_data = (caddr_t)&ioc;
+static void convert_key_from_CPU(struct brcmf_wsec_key *key,
+ struct brcmf_wsec_key_le *key_le)
+{
+ key_le->index = cpu_to_le32(key->index);
+ key_le->len = cpu_to_le32(key->len);
+ key_le->algo = cpu_to_le32(key->algo);
+ key_le->flags = cpu_to_le32(key->flags);
+ key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);
+ key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);
+ key_le->iv_initialized = cpu_to_le32(key->iv_initialized);
+ memcpy(key_le->data, key->data, sizeof(key->data));
+ memcpy(key_le->ea, key->ea, sizeof(key->ea));
+}
- fs = get_fs();
- set_fs(get_ds());
- err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
- set_fs(fs);
+static int send_key_to_dongle(struct net_device *ndev,
+ struct brcmf_wsec_key *key)
+{
+ int err;
+ struct brcmf_wsec_key_le key_le;
+ convert_key_from_CPU(key, &key_le);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, sizeof(key_le));
+ if (err)
+ WL_ERR("WLC_SET_KEY error (%d)\n", err);
return err;
}
@@ -566,7 +395,8 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
switch (type) {
case NL80211_IFTYPE_MONITOR:
@@ -587,9 +417,8 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
goto done;
}
- infra = cpu_to_le32(infra);
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_INFRA, &infra, sizeof(infra));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
+ if (err) {
WL_ERR("WLC_SET_INFRA error (%d)\n", err);
err = -EAGAIN;
} else {
@@ -606,83 +435,134 @@ done:
return err;
}
-static void wl_iscan_prep(struct brcmf_scan_params *params,
+static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val)
+{
+ s8 buf[BRCMF_DCMD_SMLEN];
+ u32 len;
+ s32 err = 0;
+ __le32 val_le;
+
+ val_le = cpu_to_le32(val);
+ len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf,
+ sizeof(buf));
+ BUG_ON(!len);
+
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
+ if (err)
+ WL_ERR("error (%d)\n", err);
+
+ return err;
+}
+
+static s32
+brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval)
+{
+ union {
+ s8 buf[BRCMF_DCMD_SMLEN];
+ __le32 val;
+ } var;
+ u32 len;
+ u32 data_null;
+ s32 err = 0;
+
+ len =
+ brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
+ sizeof(var.buf));
+ BUG_ON(!len);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len);
+ if (err)
+ WL_ERR("error (%d)\n", err);
+
+ *retval = le32_to_cpu(var.val);
+
+ return err;
+}
+
+static void brcmf_set_mpc(struct net_device *ndev, int mpc)
+{
+ s32 err = 0;
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
+
+ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
+ err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
+ if (err) {
+ WL_ERR("fail to set mpc\n");
+ return;
+ }
+ WL_INFO("MPC : %d\n", mpc);
+ }
+}
+
+static void wl_iscan_prep(struct brcmf_scan_params_le *params_le,
struct brcmf_ssid *ssid)
{
- memcpy(params->bssid, ether_bcast, ETH_ALEN);
- params->bss_type = DOT11_BSSTYPE_ANY;
- params->scan_type = 0;
- params->nprobes = -1;
- params->active_time = -1;
- params->passive_time = -1;
- params->home_time = -1;
- params->channel_num = 0;
-
- params->nprobes = cpu_to_le32(params->nprobes);
- params->active_time = cpu_to_le32(params->active_time);
- params->passive_time = cpu_to_le32(params->passive_time);
- params->home_time = cpu_to_le32(params->home_time);
+ memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
+ params_le->bss_type = DOT11_BSSTYPE_ANY;
+ params_le->scan_type = 0;
+ params_le->channel_num = 0;
+ params_le->nprobes = cpu_to_le32(-1);
+ params_le->active_time = cpu_to_le32(-1);
+ params_le->passive_time = cpu_to_le32(-1);
+ params_le->home_time = cpu_to_le32(-1);
if (ssid && ssid->SSID_len)
- memcpy(&params->ssid, ssid, sizeof(struct brcmf_ssid));
-
+ memcpy(&params_le->ssid_le, ssid, sizeof(struct brcmf_ssid));
}
static s32
-brcmf_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
+brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param,
s32 paramlen, void *bufptr, s32 buflen)
{
s32 iolen;
- iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
+ iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
BUG_ON(!iolen);
- return brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, bufptr, iolen);
+ return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen);
}
static s32
-brcmf_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
+brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param,
s32 paramlen, void *bufptr, s32 buflen)
{
s32 iolen;
- iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
+ iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
BUG_ON(!iolen);
- return brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, bufptr, buflen);
+ return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen);
}
static s32
brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
struct brcmf_ssid *ssid, u16 action)
{
- s32 params_size = (BRCMF_SCAN_PARAMS_FIXED_SIZE +
- offsetof(struct brcmf_iscan_params, params));
- struct brcmf_iscan_params *params;
+ s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
+ offsetof(struct brcmf_iscan_params_le, params_le);
+ struct brcmf_iscan_params_le *params;
s32 err = 0;
if (ssid && ssid->SSID_len)
params_size += sizeof(struct brcmf_ssid);
params = kzalloc(params_size, GFP_KERNEL);
- if (unlikely(!params))
+ if (!params)
return -ENOMEM;
- BUG_ON(params_size >= BRCMF_C_IOCTL_SMLEN);
+ BUG_ON(params_size >= BRCMF_DCMD_SMLEN);
- wl_iscan_prep(&params->params, ssid);
+ wl_iscan_prep(&params->params_le, ssid);
params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
params->action = cpu_to_le16(action);
params->scan_duration = cpu_to_le16(0);
- /* params_size += offsetof(struct brcmf_iscan_params, params); */
- err = brcmf_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
- iscan->ioctl_buf, BRCMF_C_IOCTL_SMLEN);
- if (unlikely(err)) {
- if (err == -EBUSY) {
+ err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size,
+ iscan->dcmd_buf, BRCMF_DCMD_SMLEN);
+ if (err) {
+ if (err == -EBUSY)
WL_INFO("system busy : iscan canceled\n");
- } else {
+ else
WL_ERR("error (%d)\n", err);
- }
}
+
kfree(params);
return err;
}
@@ -692,7 +572,7 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
struct net_device *ndev = cfg_to_ndev(cfg_priv);
struct brcmf_ssid ssid;
- s32 passive_scan;
+ __le32 passive_scan;
s32 err = 0;
/* Broadcast scan by default */
@@ -700,19 +580,23 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
iscan->state = WL_ISCAN_STATE_SCANING;
- passive_scan = cfg_priv->active_scan ? 0 : 1;
- err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
+ passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
+ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
&passive_scan, sizeof(passive_scan));
- if (unlikely(err)) {
+ if (err) {
WL_ERR("error (%d)\n", err);
return err;
}
brcmf_set_mpc(ndev, 0);
cfg_priv->iscan_kickstart = true;
- brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
+ err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
+ if (err) {
+ brcmf_set_mpc(ndev, 1);
+ cfg_priv->iscan_kickstart = false;
+ return err;
+ }
mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
iscan->timer_on = 1;
-
return err;
}
@@ -724,16 +608,17 @@ __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct cfg80211_ssid *ssids;
struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
- s32 passive_scan;
+ __le32 passive_scan;
bool iscan_req;
bool spec_scan;
s32 err = 0;
+ u32 SSID_len;
- if (unlikely(test_bit(WL_STATUS_SCANNING, &cfg_priv->status))) {
+ if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
return -EAGAIN;
}
- if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status))) {
+ if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) {
WL_ERR("Scanning being aborted : status (%lu)\n",
cfg_priv->status);
return -EAGAIN;
@@ -761,41 +646,41 @@ __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
if (iscan_req) {
err = brcmf_do_iscan(cfg_priv);
- if (likely(!err))
+ if (!err)
return err;
else
goto scan_out;
} else {
WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
ssids->ssid, ssids->ssid_len);
- memset(&sr->ssid, 0, sizeof(sr->ssid));
- sr->ssid.SSID_len =
- min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
- if (sr->ssid.SSID_len) {
- memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
- sr->ssid.SSID_len = cpu_to_le32(sr->ssid.SSID_len);
+ memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
+ SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
+ sr->ssid_le.SSID_len = cpu_to_le32(0);
+ if (SSID_len) {
+ memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
+ sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
spec_scan = true;
} else {
WL_SCAN("Broadcast scan\n");
}
- passive_scan = cfg_priv->active_scan ? 0 : 1;
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_PASSIVE_SCAN,
+ passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
&passive_scan, sizeof(passive_scan));
- if (unlikely(err)) {
+ if (err) {
WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
goto scan_out;
}
brcmf_set_mpc(ndev, 0);
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SCAN, &sr->ssid,
- sizeof(sr->ssid));
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
+ sizeof(sr->ssid_le));
if (err) {
- if (err == -EBUSY) {
- WL_INFO("system busy : scan for \"%s\" canceled\n",
- sr->ssid.SSID);
- } else {
+ if (err == -EBUSY)
+ WL_INFO("system busy : scan for \"%s\" "
+ "canceled\n", sr->ssid_le.SSID);
+ else
WL_ERR("WLC_SCAN error (%d)\n", err);
- }
+
brcmf_set_mpc(ndev, 1);
goto scan_out;
}
@@ -817,88 +702,46 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL);
- if (unlikely(err))
+ if (err)
WL_ERR("scan error (%d)\n", err);
WL_TRACE("Exit\n");
return err;
}
-static s32 brcmf_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
+static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
{
- s8 buf[BRCMF_C_IOCTL_SMLEN];
- u32 len;
s32 err = 0;
- val = cpu_to_le32(val);
- len = brcmu_mkiovar(name, (char *)(&val), sizeof(val), buf,
- sizeof(buf));
- BUG_ON(!len);
-
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, buf, len);
- if (unlikely(err))
- WL_ERR("error (%d)\n", err);
-
- return err;
-}
-
-static s32
-brcmf_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
-{
- union {
- s8 buf[BRCMF_C_IOCTL_SMLEN];
- s32 val;
- } var;
- u32 len;
- u32 data_null;
- s32 err = 0;
-
- len =
- brcmu_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
- sizeof(var.buf));
- BUG_ON(!len);
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, &var, len);
- if (unlikely(err))
- WL_ERR("error (%d)\n", err);
-
- *retval = le32_to_cpu(var.val);
-
- return err;
-}
-
-static s32 brcmf_set_rts(struct net_device *dev, u32 rts_threshold)
-{
- s32 err = 0;
-
- err = brcmf_dev_intvar_set(dev, "rtsthresh", rts_threshold);
- if (unlikely(err))
+ err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold);
+ if (err)
WL_ERR("Error (%d)\n", err);
return err;
}
-static s32 brcmf_set_frag(struct net_device *dev, u32 frag_threshold)
+static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
{
s32 err = 0;
- err = brcmf_dev_intvar_set(dev, "fragthresh", frag_threshold);
- if (unlikely(err))
+ err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold);
+ if (err)
WL_ERR("Error (%d)\n", err);
return err;
}
-static s32 brcmf_set_retry(struct net_device *dev, u32 retry, bool l)
+static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
{
s32 err = 0;
u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
- retry = cpu_to_le32(retry);
- err = brcmf_dev_ioctl(dev, cmd, &retry, sizeof(retry));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, cmd, &retry);
+ if (err) {
WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
return err;
}
@@ -912,7 +755,8 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
(cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) {
@@ -948,8 +792,125 @@ done:
return err;
}
+static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item)
+{
+ switch (item) {
+ case WL_PROF_SEC:
+ return &cfg_priv->profile->sec;
+ case WL_PROF_BSSID:
+ return &cfg_priv->profile->bssid;
+ case WL_PROF_SSID:
+ return &cfg_priv->profile->ssid;
+ }
+ WL_ERR("invalid item (%d)\n", item);
+ return NULL;
+}
+
+static s32
+brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
+ const struct brcmf_event_msg *e, void *data, s32 item)
+{
+ s32 err = 0;
+ struct brcmf_ssid *ssid;
+
+ switch (item) {
+ case WL_PROF_SSID:
+ ssid = (struct brcmf_ssid *) data;
+ memset(cfg_priv->profile->ssid.SSID, 0,
+ sizeof(cfg_priv->profile->ssid.SSID));
+ memcpy(cfg_priv->profile->ssid.SSID,
+ ssid->SSID, ssid->SSID_len);
+ cfg_priv->profile->ssid.SSID_len = ssid->SSID_len;
+ break;
+ case WL_PROF_BSSID:
+ if (data)
+ memcpy(cfg_priv->profile->bssid, data, ETH_ALEN);
+ else
+ memset(cfg_priv->profile->bssid, 0, ETH_ALEN);
+ break;
+ case WL_PROF_SEC:
+ memcpy(&cfg_priv->profile->sec, data,
+ sizeof(cfg_priv->profile->sec));
+ break;
+ case WL_PROF_BEACONINT:
+ cfg_priv->profile->beacon_interval = *(u16 *)data;
+ break;
+ case WL_PROF_DTIMPERIOD:
+ cfg_priv->profile->dtim_period = *(u8 *)data;
+ break;
+ default:
+ WL_ERR("unsupported item (%d)\n", item);
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
+static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
+{
+ memset(prof, 0, sizeof(*prof));
+}
+
+static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
+ size_t *join_params_size)
+{
+ u16 chanspec = 0;
+
+ if (ch != 0) {
+ if (ch <= CH_MAX_2G_CHANNEL)
+ chanspec |= WL_CHANSPEC_BAND_2G;
+ else
+ chanspec |= WL_CHANSPEC_BAND_5G;
+
+ chanspec |= WL_CHANSPEC_BW_20;
+ chanspec |= WL_CHANSPEC_CTL_SB_NONE;
+
+ *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
+ sizeof(u16);
+
+ chanspec |= (ch & WL_CHANSPEC_CHAN_MASK);
+ join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec);
+ join_params->params_le.chanspec_num = cpu_to_le32(1);
+
+ WL_CONN("join_params->params.chanspec_list[0]= %#X,"
+ "channel %d, chanspec %#X\n",
+ chanspec, ch, chanspec);
+ }
+}
+
+static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct net_device *ndev = cfg_to_ndev(cfg_priv);
+ s32 err = 0;
+
+ WL_TRACE("Enter\n");
+
+ if (test_and_clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
+ if (!brcmf_is_ibssmode(cfg_priv)) {
+ WL_CONN("Calling cfg80211_disconnected\n ");
+ cfg80211_disconnected(ndev, 0, NULL, 0,
+ GFP_KERNEL);
+ }
+ if (cfg_priv->link_up) {
+ WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0);
+ if (unlikely(err))
+ WL_ERR("WLC_DISASSOC failed (%d)\n", err);
+ cfg_priv->link_up = false;
+ }
+ }
+
+ if (brcmf_is_ibssmode(cfg_priv))
+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
+ else
+ brcmf_bss_connect_done(cfg_priv, ndev, NULL, false);
+
+ WL_TRACE("Exit\n");
+}
+
static s32
-brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_ibss_params *params)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
@@ -958,9 +919,11 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
s32 err = 0;
s32 wsec = 0;
s32 bcnprd;
+ struct brcmf_ssid ssid;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
if (params->ssid)
WL_CONN("SSID: %s\n", params->ssid);
@@ -1012,20 +975,20 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
if (params->privacy)
wsec |= WEP_ENABLED;
- err = brcmf_dev_intvar_set(dev, "wsec", wsec);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
+ if (err) {
WL_ERR("wsec failed (%d)\n", err);
goto done;
}
/* Configure Beacon Interval for starter */
if (params->beacon_interval)
- bcnprd = cpu_to_le32(params->beacon_interval);
+ bcnprd = params->beacon_interval;
else
- bcnprd = cpu_to_le32(100);
+ bcnprd = 100;
- err = brcmf_dev_ioctl(dev, BRCM_SET_BCNPRD, &bcnprd, sizeof(bcnprd));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd);
+ if (err) {
WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
goto done;
}
@@ -1034,23 +997,24 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
memset(&join_params, 0, sizeof(struct brcmf_join_params));
/* SSID */
- join_params.ssid.SSID_len =
- (params->ssid_len > 32) ? 32 : params->ssid_len;
- memcpy(join_params.ssid.SSID, params->ssid, join_params.ssid.SSID_len);
- join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
- join_params_size = sizeof(join_params.ssid);
- brcmf_update_prof(cfg_priv, NULL, &join_params.ssid, WL_PROF_SSID);
+ ssid.SSID_len = min_t(u32, params->ssid_len, 32);
+ memcpy(ssid.SSID, params->ssid, ssid.SSID_len);
+ memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len);
+ join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
+ join_params_size = sizeof(join_params.ssid_le);
+ brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
/* BSSID */
if (params->bssid) {
- memcpy(join_params.params.bssid, params->bssid, ETH_ALEN);
- join_params_size = sizeof(join_params.ssid) +
- BRCMF_ASSOC_PARAMS_FIXED_SIZE;
+ memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
+ join_params_size = sizeof(join_params.ssid_le) +
+ BRCMF_ASSOC_PARAMS_FIXED_SIZE;
} else {
- memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
+ memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
}
+
brcmf_update_prof(cfg_priv, NULL,
- &join_params.params.bssid, WL_PROF_BSSID);
+ &join_params.params_le.bssid, WL_PROF_BSSID);
/* Channel */
if (params->channel) {
@@ -1066,10 +1030,10 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
}
/* set channel for starter */
- target_channel = cpu_to_le32(cfg_priv->channel);
- err = brcmf_dev_ioctl(dev, BRCM_SET_CHANNEL,
- &target_channel, sizeof(target_channel));
- if (unlikely(err)) {
+ target_channel = cfg_priv->channel;
+ err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL,
+ &target_channel);
+ if (err) {
WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
goto done;
}
@@ -1079,9 +1043,9 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
cfg_priv->ibss_starter = false;
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_SSID,
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
&join_params, join_params_size);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("WLC_SET_SSID failed (%d)\n", err);
goto done;
}
@@ -1093,13 +1057,15 @@ done:
return err;
}
-static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+static s32
+brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
brcmf_link_down(cfg_priv);
@@ -1108,10 +1074,10 @@ static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev
return err;
}
-static s32
-brcmf_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
+static s32 brcmf_set_wpa_version(struct net_device *ndev,
+ struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
@@ -1123,8 +1089,8 @@ brcmf_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sm
else
val = WPA_AUTH_DISABLED;
WL_CONN("setting wpa_auth to 0x%0x\n", val);
- err = brcmf_dev_intvar_set(dev, "wpa_auth", val);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
+ if (err) {
WL_ERR("set wpa_auth failed (%d)\n", err);
return err;
}
@@ -1133,10 +1099,10 @@ brcmf_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sm
return err;
}
-static s32
-brcmf_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
+static s32 brcmf_set_auth_type(struct net_device *ndev,
+ struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
@@ -1162,8 +1128,8 @@ brcmf_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
break;
}
- err = brcmf_dev_intvar_set(dev, "auth", val);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "auth", val);
+ if (err) {
WL_ERR("set auth failed (%d)\n", err);
return err;
}
@@ -1173,9 +1139,10 @@ brcmf_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
}
static s32
-brcmf_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_set_cipher(struct net_device *ndev,
+ struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct brcmf_cfg80211_security *sec;
s32 pval = 0;
s32 gval = 0;
@@ -1225,8 +1192,8 @@ brcmf_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme
}
WL_CONN("pval (%d) gval (%d)\n", pval, gval);
- err = brcmf_dev_intvar_set(dev, "wsec", pval | gval);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval);
+ if (err) {
WL_ERR("error (%d)\n", err);
return err;
}
@@ -1239,16 +1206,16 @@ brcmf_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme
}
static s32
-brcmf_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
if (sme->crypto.n_akm_suites) {
- err = brcmf_dev_intvar_get(dev, "wpa_auth", &val);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val);
+ if (err) {
WL_ERR("could not get wpa_auth (%d)\n", err);
return err;
}
@@ -1281,8 +1248,8 @@ brcmf_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
}
WL_CONN("setting wpa_auth to %d\n", val);
- err = brcmf_dev_intvar_set(dev, "wpa_auth", val);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
+ if (err) {
WL_ERR("could not set wpa_auth (%d)\n", err);
return err;
}
@@ -1294,86 +1261,88 @@ brcmf_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
}
static s32
-brcmf_set_set_sharedkey(struct net_device *dev,
+brcmf_set_wep_sharedkey(struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct brcmf_cfg80211_security *sec;
struct brcmf_wsec_key key;
s32 val;
s32 err = 0;
WL_CONN("key len (%d)\n", sme->key_len);
- if (sme->key_len) {
- sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
- WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n",
- sec->wpa_versions, sec->cipher_pairwise);
- if (!
- (sec->wpa_versions & (NL80211_WPA_VERSION_1 |
- NL80211_WPA_VERSION_2))
-&& (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
- WLAN_CIPHER_SUITE_WEP104))) {
- memset(&key, 0, sizeof(key));
- key.len = (u32) sme->key_len;
- key.index = (u32) sme->key_idx;
- if (unlikely(key.len > sizeof(key.data))) {
- WL_ERR("Too long key length (%u)\n", key.len);
- return -EINVAL;
- }
- memcpy(key.data, sme->key, key.len);
- key.flags = BRCMF_PRIMARY_KEY;
- switch (sec->cipher_pairwise) {
- case WLAN_CIPHER_SUITE_WEP40:
- key.algo = CRYPTO_ALGO_WEP1;
- break;
- case WLAN_CIPHER_SUITE_WEP104:
- key.algo = CRYPTO_ALGO_WEP128;
- break;
- default:
- WL_ERR("Invalid algorithm (%d)\n",
- sme->crypto.ciphers_pairwise[0]);
- return -EINVAL;
- }
- /* Set the new key/index */
- WL_CONN("key length (%d) key index (%d) algo (%d)\n",
- key.len, key.index, key.algo);
- WL_CONN("key \"%s\"\n", key.data);
- swap_key_from_BE(&key);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key,
- sizeof(key));
- if (unlikely(err)) {
- WL_ERR("WLC_SET_KEY error (%d)\n", err);
+
+ if (sme->key_len == 0)
+ return 0;
+
+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
+ WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n",
+ sec->wpa_versions, sec->cipher_pairwise);
+
+ if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
+ return 0;
+
+ if (sec->cipher_pairwise &
+ (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)) {
+ memset(&key, 0, sizeof(key));
+ key.len = (u32) sme->key_len;
+ key.index = (u32) sme->key_idx;
+ if (key.len > sizeof(key.data)) {
+ WL_ERR("Too long key length (%u)\n", key.len);
+ return -EINVAL;
+ }
+ memcpy(key.data, sme->key, key.len);
+ key.flags = BRCMF_PRIMARY_KEY;
+ switch (sec->cipher_pairwise) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ key.algo = CRYPTO_ALGO_WEP1;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ key.algo = CRYPTO_ALGO_WEP128;
+ break;
+ default:
+ WL_ERR("Invalid algorithm (%d)\n",
+ sme->crypto.ciphers_pairwise[0]);
+ return -EINVAL;
+ }
+ /* Set the new key/index */
+ WL_CONN("key length (%d) key index (%d) algo (%d)\n",
+ key.len, key.index, key.algo);
+ WL_CONN("key \"%s\"\n", key.data);
+ err = send_key_to_dongle(ndev, &key);
+ if (err)
+ return err;
+
+ if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
+ WL_CONN("set auth_type to shared key\n");
+ val = 1; /* shared key */
+ err = brcmf_dev_intvar_set(ndev, "auth", val);
+ if (err) {
+ WL_ERR("set auth failed (%d)\n", err);
return err;
}
- if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
- WL_CONN("set auth_type to shared key\n");
- val = 1; /* shared key */
- err = brcmf_dev_intvar_set(dev, "auth", val);
- if (unlikely(err)) {
- WL_ERR("set auth failed (%d)\n", err);
- return err;
- }
- }
}
}
return err;
}
static s32
-brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
struct ieee80211_channel *chan = sme->channel;
struct brcmf_join_params join_params;
size_t join_params_size;
+ struct brcmf_ssid ssid;
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
- if (unlikely(!sme->ssid)) {
+ if (!sme->ssid) {
WL_ERR("Invalid ssid\n");
return -EOPNOTSUPP;
}
@@ -1390,62 +1359,54 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
- err = brcmf_set_wpa_version(dev, sme);
+ err = brcmf_set_wpa_version(ndev, sme);
if (err) {
WL_ERR("wl_set_wpa_version failed (%d)\n", err);
goto done;
}
- err = brcmf_set_auth_type(dev, sme);
+ err = brcmf_set_auth_type(ndev, sme);
if (err) {
WL_ERR("wl_set_auth_type failed (%d)\n", err);
goto done;
}
- err = brcmf_set_set_cipher(dev, sme);
+ err = brcmf_set_set_cipher(ndev, sme);
if (err) {
WL_ERR("wl_set_set_cipher failed (%d)\n", err);
goto done;
}
- err = brcmf_set_key_mgmt(dev, sme);
+ err = brcmf_set_key_mgmt(ndev, sme);
if (err) {
WL_ERR("wl_set_key_mgmt failed (%d)\n", err);
goto done;
}
- err = brcmf_set_set_sharedkey(dev, sme);
+ err = brcmf_set_wep_sharedkey(ndev, sme);
if (err) {
- WL_ERR("wl_set_set_sharedkey failed (%d)\n", err);
+ WL_ERR("brcmf_set_wep_sharedkey failed (%d)\n", err);
goto done;
}
- brcmf_update_prof(cfg_priv, NULL, sme->bssid, WL_PROF_BSSID);
- /*
- ** Join with specific BSSID and cached SSID
- ** If SSID is zero join based on BSSID only
- */
memset(&join_params, 0, sizeof(join_params));
- join_params_size = sizeof(join_params.ssid);
+ join_params_size = sizeof(join_params.ssid_le);
- join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
- memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
- join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
- brcmf_update_prof(cfg_priv, NULL, &join_params.ssid, WL_PROF_SSID);
+ ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), sme->ssid_len);
+ memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len);
+ memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len);
+ join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
+ brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
- if (sme->bssid)
- memcpy(join_params.params.bssid, sme->bssid, ETH_ALEN);
- else
- memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
+ memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
- if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
+ if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN)
WL_CONN("ssid \"%s\", len (%d)\n",
- join_params.ssid.SSID, join_params.ssid.SSID_len);
- }
+ ssid.SSID, ssid.SSID_len);
brcmf_ch_to_chanspec(cfg_priv->channel,
&join_params, &join_params_size);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_SSID,
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
&join_params, join_params_size);
if (err)
WL_ERR("WLC_SET_SSID failed (%d)\n", err);
@@ -1458,24 +1419,24 @@ done:
}
static s32
-brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
u16 reason_code)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
- struct brcmf_scb_val scbval;
+ struct brcmf_scb_val_le scbval;
s32 err = 0;
WL_TRACE("Enter. Reason code = %d\n", reason_code);
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
- scbval.val = reason_code;
memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN);
- scbval.val = cpu_to_le32(scbval.val);
- err = brcmf_dev_ioctl(dev, BRCMF_C_DISASSOC, &scbval,
- sizeof(struct brcmf_scb_val));
- if (unlikely(err))
+ scbval.val = cpu_to_le32(reason_code);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval,
+ sizeof(struct brcmf_scb_val_le));
+ if (err)
WL_ERR("error (%d)\n", err);
cfg_priv->link_up = false;
@@ -1496,7 +1457,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
s32 disable = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
switch (type) {
case NL80211_TX_POWER_AUTOMATIC:
@@ -1518,9 +1480,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
}
/* Make sure radio is off or on as far as software is concerned */
disable = WL_RADIO_SW_DISABLE << 16;
- disable = cpu_to_le32(disable);
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_RADIO, &disable, sizeof(disable));
- if (unlikely(err))
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable);
+ if (err)
WL_ERR("WLC_SET_RADIO error (%d)\n", err);
if (dbm > 0xffff)
@@ -1528,8 +1489,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
else
txpwrmw = (u16) dbm;
err = brcmf_dev_intvar_set(ndev, "qtxpower",
- (s32) (brcmu_mw_to_qdbm(txpwrmw)));
- if (unlikely(err))
+ (s32) (brcmf_mw_to_qdbm(txpwrmw)));
+ if (err)
WL_ERR("qtxpower error (%d)\n", err);
cfg_priv->conf->tx_power = dbm;
@@ -1547,16 +1508,17 @@ static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("error (%d)\n", err);
goto done;
}
result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
- *dbm = (s32) brcmu_qdbm_to_mw(result);
+ *dbm = (s32) brcmf_qdbm_to_mw(result);
done:
WL_TRACE("Exit\n");
@@ -1564,31 +1526,30 @@ done:
}
static s32
-brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool unicast, bool multicast)
{
u32 index;
- s32 wsec;
+ u32 wsec;
s32 err = 0;
WL_TRACE("Enter\n");
WL_CONN("key index (%d)\n", key_idx);
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_WSEC, &wsec, sizeof(wsec));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec);
+ if (err) {
WL_ERR("WLC_GET_WSEC error (%d)\n", err);
goto done;
}
- wsec = le32_to_cpu(wsec);
if (wsec & WEP_ENABLED) {
/* Just select a new current key */
- index = (u32) key_idx;
- index = cpu_to_le32(index);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY_PRIMARY, &index,
- sizeof(index));
- if (unlikely(err))
+ index = key_idx;
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY,
+ &index);
+ if (err)
WL_ERR("error (%d)\n", err);
}
done:
@@ -1597,10 +1558,11 @@ done:
}
static s32
-brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
+brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, const u8 *mac_addr, struct key_params *params)
{
struct brcmf_wsec_key key;
+ struct brcmf_wsec_key_le key_le;
s32 err = 0;
memset(&key, 0, sizeof(key));
@@ -1613,12 +1575,9 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
/* check for key index change */
if (key.len == 0) {
/* key delete */
- swap_key_from_BE(&key);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
- if (unlikely(err)) {
- WL_ERR("key delete error (%d)\n", err);
+ err = send_key_to_dongle(ndev, &key);
+ if (err)
return err;
- }
} else {
if (key.len > sizeof(key.data)) {
WL_ERR("Invalid key length (%d)\n", key.len);
@@ -1671,11 +1630,12 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
return -EINVAL;
}
- swap_key_from_BE(&key);
+ convert_key_from_CPU(&key, &key_le);
- brcmf_netdev_wait_pend8021x(dev);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
- if (unlikely(err)) {
+ brcmf_netdev_wait_pend8021x(ndev);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le,
+ sizeof(key_le));
+ if (err) {
WL_ERR("WLC_SET_KEY error (%d)\n", err);
return err;
}
@@ -1684,7 +1644,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
}
static s32
-brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params)
{
@@ -1696,18 +1656,19 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
WL_TRACE("Enter\n");
WL_CONN("key index (%d)\n", key_idx);
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
if (mac_addr) {
WL_TRACE("Exit");
- return brcmf_add_keyext(wiphy, dev, key_idx, mac_addr, params);
+ return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
}
memset(&key, 0, sizeof(key));
key.len = (u32) params->key_len;
key.index = (u32) key_idx;
- if (unlikely(key.len > sizeof(key.data))) {
+ if (key.len > sizeof(key.data)) {
WL_ERR("Too long key length (%u)\n", key.len);
err = -EINVAL;
goto done;
@@ -1745,32 +1706,27 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
goto done;
}
- /* Set the new key/index */
- swap_key_from_BE(&key);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
- if (unlikely(err)) {
- WL_ERR("WLC_SET_KEY error (%d)\n", err);
+ err = send_key_to_dongle(ndev, &key); /* Set the new key/index */
+ if (err)
goto done;
- }
val = WEP_ENABLED;
- err = brcmf_dev_intvar_get(dev, "wsec", &wsec);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_get(ndev, "wsec", &wsec);
+ if (err) {
WL_ERR("get wsec error (%d)\n", err);
goto done;
}
wsec &= ~(WEP_ENABLED);
wsec |= val;
- err = brcmf_dev_intvar_set(dev, "wsec", wsec);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
+ if (err) {
WL_ERR("set wsec error (%d)\n", err);
goto done;
}
val = 1; /* assume shared key. otherwise 0 */
- val = cpu_to_le32(val);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_AUTH, &val, sizeof(val));
- if (unlikely(err))
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val);
+ if (err)
WL_ERR("WLC_SET_AUTH error (%d)\n", err);
done:
WL_TRACE("Exit\n");
@@ -1778,7 +1734,7 @@ done:
}
static s32
-brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool pairwise, const u8 *mac_addr)
{
struct brcmf_wsec_key key;
@@ -1787,7 +1743,9 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
s32 wsec;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
+
memset(&key, 0, sizeof(key));
key.index = (u32) key_idx;
@@ -1795,25 +1753,23 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
key.algo = CRYPTO_ALGO_OFF;
WL_CONN("key index (%d)\n", key_idx);
+
/* Set the new key/index */
- swap_key_from_BE(&key);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
- if (unlikely(err)) {
+ err = send_key_to_dongle(ndev, &key);
+ if (err) {
if (err == -EINVAL) {
if (key.index >= DOT11_MAX_DEFAULT_KEYS)
/* we ignore this key index in this case */
WL_ERR("invalid key index (%d)\n", key_idx);
- } else
- WL_ERR("WLC_SET_KEY error (%d)\n", err);
-
+ }
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
goto done;
}
val = 0;
- err = brcmf_dev_intvar_get(dev, "wsec", &wsec);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_get(ndev, "wsec", &wsec);
+ if (err) {
WL_ERR("get wsec error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
@@ -1821,8 +1777,8 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
}
wsec &= ~(WEP_ENABLED);
wsec |= val;
- err = brcmf_dev_intvar_set(dev, "wsec", wsec);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
+ if (err) {
WL_ERR("set wsec error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
@@ -1830,9 +1786,8 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
}
val = 0; /* assume open key. otherwise 1 */
- val = cpu_to_le32(val);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_AUTH, &val, sizeof(val));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val);
+ if (err) {
WL_ERR("WLC_SET_AUTH error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
@@ -1843,12 +1798,11 @@ done:
}
static s32
-brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
void (*callback) (void *cookie, struct key_params * params))
{
struct key_params params;
- struct brcmf_wsec_key key;
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
struct brcmf_cfg80211_security *sec;
s32 wsec;
@@ -1856,23 +1810,18 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
WL_TRACE("Enter\n");
WL_CONN("key index (%d)\n", key_idx);
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
- memset(&key, 0, sizeof(key));
- key.index = key_idx;
- swap_key_to_BE(&key);
memset(&params, 0, sizeof(params));
- params.key_len = (u8) min_t(u8, WLAN_MAX_KEY_LEN, key.len);
- memcpy(params.key, key.data, params.key_len);
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_WSEC, &wsec, sizeof(wsec));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec);
+ if (err) {
WL_ERR("WLC_GET_WSEC error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
goto done;
}
- wsec = le32_to_cpu(wsec);
switch (wsec) {
case WEP_ENABLED:
sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
@@ -1906,30 +1855,29 @@ done:
static s32
brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
- struct net_device *dev, u8 key_idx)
+ struct net_device *ndev, u8 key_idx)
{
WL_INFO("Not supported\n");
- CHECK_SYS_UP();
return -EOPNOTSUPP;
}
static s32
-brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
u8 *mac, struct station_info *sinfo)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
- struct brcmf_scb_val scb_val;
+ struct brcmf_scb_val_le scb_val;
int rssi;
s32 rate;
s32 err = 0;
u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID);
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
- if (unlikely
- (memcmp(mac, bssid, ETH_ALEN))) {
+ if (memcmp(mac, bssid, ETH_ALEN)) {
WL_ERR("Wrong Mac address cfg_mac-%X:%X:%X:%X:%X:%X"
"wl_bssid-%X:%X:%X:%X:%X:%X\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
@@ -1940,23 +1888,22 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
}
/* Report the current tx rate */
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_RATE, &rate, sizeof(rate));
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate);
if (err) {
WL_ERR("Could not get rate (%d)\n", err);
} else {
- rate = le32_to_cpu(rate);
sinfo->filled |= STATION_INFO_TX_BITRATE;
sinfo->txrate.legacy = rate * 5;
WL_CONN("Rate %d Mbps\n", rate / 2);
}
if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
- scb_val.val = 0;
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_RSSI, &scb_val,
- sizeof(struct brcmf_scb_val));
- if (unlikely(err)) {
+ scb_val.val = cpu_to_le32(0);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
+ sizeof(struct brcmf_scb_val_le));
+ if (err)
WL_ERR("Could not get rssi (%d)\n", err);
- }
+
rssi = le32_to_cpu(scb_val.val);
sinfo->filled |= STATION_INFO_SIGNAL;
sinfo->signal = rssi;
@@ -1969,63 +1916,51 @@ done:
}
static s32
-brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
bool enabled, s32 timeout)
{
s32 pm;
s32 err = 0;
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+
+ /*
+ * Powersave enable/disable request is coming from the
+ * cfg80211 even before the interface is up. In that
+ * scenario, driver will be storing the power save
+ * preference in cfg_priv struct to apply this to
+ * FW later while initializing the dongle
+ */
+ cfg_priv->pwr_save = enabled;
+ if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
+
+ WL_INFO("Device is not ready,"
+ "storing the value in cfg_priv struct\n");
+ goto done;
+ }
pm = enabled ? PM_FAST : PM_OFF;
- pm = cpu_to_le32(pm);
WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_PM, &pm, sizeof(pm));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm);
+ if (err) {
if (err == -ENODEV)
WL_ERR("net_device is not ready yet\n");
else
WL_ERR("error (%d)\n", err);
}
+done:
WL_TRACE("Exit\n");
return err;
}
-static __used u32 brcmf_find_msb(u16 bit16)
-{
- u32 ret = 0;
-
- if (bit16 & 0xff00) {
- ret += 8;
- bit16 >>= 8;
- }
-
- if (bit16 & 0xf0) {
- ret += 4;
- bit16 >>= 4;
- }
-
- if (bit16 & 0xc) {
- ret += 2;
- bit16 >>= 2;
- }
-
- if (bit16 & 2)
- ret += bit16 & 2;
- else if (bit16)
- ret += bit16;
-
- return ret;
-}
-
static s32
-brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
const u8 *addr,
const struct cfg80211_bitrate_mask *mask)
{
- struct wl_rateset rateset;
+ struct brcm_rateset_le rateset_le;
s32 rate;
s32 val;
s32 err_bg;
@@ -2034,28 +1969,28 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
/* addr param is always NULL. ignore it */
/* Get current rateset */
- err = brcmf_dev_ioctl(dev, BRCM_GET_CURR_RATESET, &rateset,
- sizeof(rateset));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le,
+ sizeof(rateset_le));
+ if (err) {
WL_ERR("could not get current rateset (%d)\n", err);
goto done;
}
- rateset.count = le32_to_cpu(rateset.count);
-
- legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy);
+ legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF);
if (!legacy)
- legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy);
+ legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy &
+ 0xFFFF);
val = wl_g_rates[legacy - 1].bitrate * 100000;
- if (val < rateset.count)
+ if (val < le32_to_cpu(rateset_le.count))
/* Select rate by rateset index */
- rate = rateset.rates[val] & 0x7f;
+ rate = rateset_le.rates[val] & 0x7f;
else
/* Specified rate in bps */
rate = val / 500000;
@@ -2067,9 +2002,9 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
* Set rate override,
* Since the is a/b/g-blind, both a/bg_rate are enforced.
*/
- err_bg = brcmf_dev_intvar_set(dev, "bg_rate", rate);
- err_a = brcmf_dev_intvar_set(dev, "a_rate", rate);
- if (unlikely(err_bg && err_a)) {
+ err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate);
+ err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate);
+ if (err_bg && err_a) {
WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
err = err_bg | err_a;
}
@@ -2079,6 +2014,483 @@ done:
return err;
}
+static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
+ struct brcmf_bss_info *bi)
+{
+ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
+ struct ieee80211_channel *notify_channel;
+ struct cfg80211_bss *bss;
+ struct ieee80211_supported_band *band;
+ s32 err = 0;
+ u16 channel;
+ u32 freq;
+ u64 notify_timestamp;
+ u16 notify_capability;
+ u16 notify_interval;
+ u8 *notify_ie;
+ size_t notify_ielen;
+ s32 notify_signal;
+
+ if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
+ WL_ERR("Bss info is larger than buffer. Discarding\n");
+ return 0;
+ }
+
+ channel = bi->ctl_ch ? bi->ctl_ch :
+ CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+ freq = ieee80211_channel_to_frequency(channel, band->band);
+ notify_channel = ieee80211_get_channel(wiphy, freq);
+
+ notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
+ notify_capability = le16_to_cpu(bi->capability);
+ notify_interval = le16_to_cpu(bi->beacon_period);
+ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
+ notify_ielen = le32_to_cpu(bi->ie_length);
+ notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
+
+ WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ bi->BSSID[0], bi->BSSID[1], bi->BSSID[2],
+ bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]);
+ WL_CONN("Channel: %d(%d)\n", channel, freq);
+ WL_CONN("Capability: %X\n", notify_capability);
+ WL_CONN("Beacon interval: %d\n", notify_interval);
+ WL_CONN("Signal: %d\n", notify_signal);
+ WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
+
+ bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
+ notify_timestamp, notify_capability, notify_interval, notify_ie,
+ notify_ielen, notify_signal, GFP_KERNEL);
+
+ if (!bss) {
+ WL_ERR("cfg80211_inform_bss_frame error\n");
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_scan_results *bss_list;
+ struct brcmf_bss_info *bi = NULL; /* must be initialized */
+ s32 err = 0;
+ int i;
+
+ bss_list = cfg_priv->bss_list;
+ if (bss_list->version != BRCMF_BSS_INFO_VERSION) {
+ WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
+ bss_list->version);
+ return -EOPNOTSUPP;
+ }
+ WL_SCAN("scanned AP count (%d)\n", bss_list->count);
+ for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) {
+ bi = next_bss(bss_list, bi);
+ err = brcmf_inform_single_bss(cfg_priv, bi);
+ if (err)
+ break;
+ }
+ return err;
+}
+
+static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
+ struct net_device *ndev, const u8 *bssid)
+{
+ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
+ struct ieee80211_channel *notify_channel;
+ struct brcmf_bss_info *bi = NULL;
+ struct ieee80211_supported_band *band;
+ u8 *buf = NULL;
+ s32 err = 0;
+ u16 channel;
+ u32 freq;
+ u64 notify_timestamp;
+ u16 notify_capability;
+ u16 notify_interval;
+ u8 *notify_ie;
+ size_t notify_ielen;
+ s32 notify_signal;
+
+ WL_TRACE("Enter\n");
+
+ buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+ if (buf == NULL) {
+ err = -ENOMEM;
+ goto CleanUp;
+ }
+
+ *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
+
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
+ if (err) {
+ WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
+ goto CleanUp;
+ }
+
+ bi = (struct brcmf_bss_info *)(buf + 4);
+
+ channel = bi->ctl_ch ? bi->ctl_ch :
+ CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+ freq = ieee80211_channel_to_frequency(channel, band->band);
+ notify_channel = ieee80211_get_channel(wiphy, freq);
+
+ notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
+ notify_capability = le16_to_cpu(bi->capability);
+ notify_interval = le16_to_cpu(bi->beacon_period);
+ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
+ notify_ielen = le32_to_cpu(bi->ie_length);
+ notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
+
+ WL_CONN("channel: %d(%d)\n", channel, freq);
+ WL_CONN("capability: %X\n", notify_capability);
+ WL_CONN("beacon interval: %d\n", notify_interval);
+ WL_CONN("signal: %d\n", notify_signal);
+ WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
+
+ cfg80211_inform_bss(wiphy, notify_channel, bssid,
+ notify_timestamp, notify_capability, notify_interval,
+ notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
+
+CleanUp:
+
+ kfree(buf);
+
+ WL_TRACE("Exit\n");
+
+ return err;
+}
+
+static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ return cfg_priv->conf->mode == WL_MODE_IBSS;
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ */
+static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
+{
+ struct brcmf_tlv *elt;
+ int totlen;
+
+ elt = (struct brcmf_tlv *) buf;
+ totlen = buflen;
+
+ /* find tagged parameter */
+ while (totlen >= 2) {
+ int len = elt->len;
+
+ /* validate remaining totlen */
+ if ((elt->id == key) && (totlen >= (len + 2)))
+ return elt;
+
+ elt = (struct brcmf_tlv *) ((u8 *) elt + (len + 2));
+ totlen -= (len + 2);
+ }
+
+ return NULL;
+}
+
+static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_bss_info *bi;
+ struct brcmf_ssid *ssid;
+ struct brcmf_tlv *tim;
+ u16 beacon_interval;
+ u8 dtim_period;
+ size_t ie_len;
+ u8 *ie;
+ s32 err = 0;
+
+ WL_TRACE("Enter\n");
+ if (brcmf_is_ibssmode(cfg_priv))
+ return err;
+
+ ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID);
+
+ *(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
+ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO,
+ cfg_priv->extra_buf, WL_EXTRA_BUF_MAX);
+ if (err) {
+ WL_ERR("Could not get bss info %d\n", err);
+ goto update_bss_info_out;
+ }
+
+ bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4);
+ err = brcmf_inform_single_bss(cfg_priv, bi);
+ if (err)
+ goto update_bss_info_out;
+
+ ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
+ ie_len = le32_to_cpu(bi->ie_length);
+ beacon_interval = le16_to_cpu(bi->beacon_period);
+
+ tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
+ if (tim)
+ dtim_period = tim->data[1];
+ else {
+ /*
+ * active scan was done so we could not get dtim
+ * information out of probe response.
+ * so we speficially query dtim information to dongle.
+ */
+ u32 var;
+ err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv),
+ "dtim_assoc", &var);
+ if (err) {
+ WL_ERR("wl dtim_assoc failed (%d)\n", err);
+ goto update_bss_info_out;
+ }
+ dtim_period = (u8)var;
+ }
+
+ brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT);
+ brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
+
+update_bss_info_out:
+ WL_TRACE("Exit");
+ return err;
+}
+
+static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
+ struct brcmf_ssid ssid;
+
+ if (cfg_priv->iscan_on) {
+ iscan->state = WL_ISCAN_STATE_IDLE;
+
+ if (iscan->timer_on) {
+ del_timer_sync(&iscan->timer);
+ iscan->timer_on = 0;
+ }
+
+ cancel_work_sync(&iscan->work);
+
+ /* Abort iscan running in FW */
+ memset(&ssid, 0, sizeof(ssid));
+ brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT);
+ }
+}
+
+static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
+ bool aborted)
+{
+ struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
+ struct net_device *ndev = cfg_to_ndev(cfg_priv);
+
+ if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
+ WL_ERR("Scan complete while device not scanning\n");
+ return;
+ }
+ if (cfg_priv->scan_request) {
+ WL_SCAN("ISCAN Completed scan: %s\n",
+ aborted ? "Aborted" : "Done");
+ cfg80211_scan_done(cfg_priv->scan_request, aborted);
+ brcmf_set_mpc(ndev, 1);
+ cfg_priv->scan_request = NULL;
+ }
+ cfg_priv->iscan_kickstart = false;
+}
+
+static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
+{
+ if (iscan->state != WL_ISCAN_STATE_IDLE) {
+ WL_SCAN("wake up iscan\n");
+ schedule_work(&iscan->work);
+ return 0;
+ }
+
+ return -EIO;
+}
+
+static s32
+brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
+ struct brcmf_scan_results **bss_list)
+{
+ struct brcmf_iscan_results list;
+ struct brcmf_scan_results *results;
+ struct brcmf_scan_results_le *results_le;
+ struct brcmf_iscan_results *list_buf;
+ s32 err = 0;
+
+ memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
+ list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
+ results = &list_buf->results;
+ results_le = &list_buf->results_le;
+ results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
+ results->version = 0;
+ results->count = 0;
+
+ memset(&list, 0, sizeof(list));
+ list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
+ err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list,
+ BRCMF_ISCAN_RESULTS_FIXED_SIZE,
+ iscan->scan_buf, WL_ISCAN_BUF_MAX);
+ if (err) {
+ WL_ERR("error (%d)\n", err);
+ return err;
+ }
+ results->buflen = le32_to_cpu(results_le->buflen);
+ results->version = le32_to_cpu(results_le->version);
+ results->count = le32_to_cpu(results_le->count);
+ WL_SCAN("results->count = %d\n", results_le->count);
+ WL_SCAN("results->buflen = %d\n", results_le->buflen);
+ *status = le32_to_cpu(list_buf->status_le);
+ WL_SCAN("status = %d\n", *status);
+ *bss_list = results;
+
+ return err;
+}
+
+static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
+ s32 err = 0;
+
+ iscan->state = WL_ISCAN_STATE_IDLE;
+ brcmf_inform_bss(cfg_priv);
+ brcmf_notify_iscan_complete(iscan, false);
+
+ return err;
+}
+
+static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
+ s32 err = 0;
+
+ /* Reschedule the timer */
+ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
+ iscan->timer_on = 1;
+
+ return err;
+}
+
+static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
+ s32 err = 0;
+
+ brcmf_inform_bss(cfg_priv);
+ brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
+ /* Reschedule the timer */
+ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
+ iscan->timer_on = 1;
+
+ return err;
+}
+
+static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
+ s32 err = 0;
+
+ iscan->state = WL_ISCAN_STATE_IDLE;
+ brcmf_notify_iscan_complete(iscan, true);
+
+ return err;
+}
+
+static void brcmf_cfg80211_iscan_handler(struct work_struct *work)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan =
+ container_of(work, struct brcmf_cfg80211_iscan_ctrl,
+ work);
+ struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
+ struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
+ u32 status = BRCMF_SCAN_RESULTS_PARTIAL;
+
+ if (iscan->timer_on) {
+ del_timer_sync(&iscan->timer);
+ iscan->timer_on = 0;
+ }
+
+ if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) {
+ status = BRCMF_SCAN_RESULTS_ABORTED;
+ WL_ERR("Abort iscan\n");
+ }
+
+ el->handler[status](cfg_priv);
+}
+
+static void brcmf_iscan_timer(unsigned long data)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan =
+ (struct brcmf_cfg80211_iscan_ctrl *)data;
+
+ if (iscan) {
+ iscan->timer_on = 0;
+ WL_SCAN("timer expired\n");
+ brcmf_wakeup_iscan(iscan);
+ }
+}
+
+static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
+
+ if (cfg_priv->iscan_on) {
+ iscan->state = WL_ISCAN_STATE_IDLE;
+ INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler);
+ }
+
+ return 0;
+}
+
+static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
+{
+ memset(el, 0, sizeof(*el));
+ el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
+ el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
+ el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
+ el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
+ el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
+}
+
+static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
+ int err = 0;
+
+ if (cfg_priv->iscan_on) {
+ iscan->ndev = cfg_to_ndev(cfg_priv);
+ brcmf_init_iscan_eloop(&iscan->el);
+ iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
+ init_timer(&iscan->timer);
+ iscan->timer.data = (unsigned long) iscan;
+ iscan->timer.function = brcmf_iscan_timer;
+ err = brcmf_invoke_iscan(cfg_priv);
+ if (!err)
+ iscan->data = cfg_priv;
+ }
+
+ return err;
+}
+
+static void brcmf_delay(u32 ms)
+{
+ if (ms < 1000 / HZ) {
+ cond_resched();
+ mdelay(ms);
+ } else {
+ msleep(ms);
+ }
+}
+
static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
@@ -2090,10 +2502,6 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
*/
WL_TRACE("Enter\n");
-#if defined(CONFIG_PM_SLEEP)
- atomic_set(&brcmf_mmc_suspend, false);
-#endif /* defined(CONFIG_PM_SLEEP) */
-
if (test_bit(WL_STATUS_READY, &cfg_priv->status))
brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
@@ -2131,9 +2539,7 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
* generated due to DISASSOC call to the fw to keep
* the state fw and WPA_Supplicant state consistent
*/
- rtnl_unlock();
brcmf_delay(500);
- rtnl_lock();
}
set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
@@ -2155,81 +2561,123 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
brcmf_set_mpc(ndev, 1);
}
-#if defined(CONFIG_PM_SLEEP)
- atomic_set(&brcmf_mmc_suspend, true);
-#endif /* defined(CONFIG_PM_SLEEP) */
-
WL_TRACE("Exit\n");
return 0;
}
static __used s32
-brcmf_update_pmklist(struct net_device *dev,
+brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len)
+{
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
+ u32 buflen;
+
+ buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf,
+ WL_DCMD_LEN_MAX);
+ BUG_ON(!buflen);
+
+ return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf,
+ buflen);
+}
+
+static s32
+brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf,
+ s32 buf_len)
+{
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
+ u32 len;
+ s32 err = 0;
+
+ len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf,
+ WL_DCMD_LEN_MAX);
+ BUG_ON(!len);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf,
+ WL_DCMD_LEN_MAX);
+ if (err) {
+ WL_ERR("error (%d)\n", err);
+ return err;
+ }
+ memcpy(buf, cfg_priv->dcmd_buf, buf_len);
+
+ return err;
+}
+
+static __used s32
+brcmf_update_pmklist(struct net_device *ndev,
struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
{
int i, j;
+ int pmkid_len;
- WL_CONN("No of elements %d\n", pmk_list->pmkids.npmkid);
- for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
+ pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
+
+ WL_CONN("No of elements %d\n", pmkid_len);
+ for (i = 0; i < pmkid_len; i++) {
WL_CONN("PMKID[%d]: %pM =\n", i,
&pmk_list->pmkids.pmkid[i].BSSID);
for (j = 0; j < WLAN_PMKID_LEN; j++)
WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
}
- if (likely(!err))
- brcmf_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list,
+ if (!err)
+ brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list,
sizeof(*pmk_list));
return err;
}
static s32
-brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_pmksa *pmksa)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
- struct _pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
+ struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
s32 err = 0;
int i;
+ int pmkid_len;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
- for (i = 0; i < pmkids->npmkid; i++)
+ pmkid_len = le32_to_cpu(pmkids->npmkid);
+ for (i = 0; i < pmkid_len; i++)
if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
break;
if (i < WL_NUM_PMKIDS_MAX) {
memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
- if (i == pmkids->npmkid)
- pmkids->npmkid++;
+ if (i == pmkid_len) {
+ pmkid_len++;
+ pmkids->npmkid = cpu_to_le32(pmkid_len);
+ }
} else
err = -EINVAL;
WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
- pmkids->pmkid[pmkids->npmkid].BSSID);
+ pmkids->pmkid[pmkid_len].BSSID);
for (i = 0; i < WLAN_PMKID_LEN; i++)
- WL_CONN("%02x\n", pmkids->pmkid[pmkids->npmkid].PMKID[i]);
+ WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
- err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
+ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
WL_TRACE("Exit\n");
return err;
}
static s32
-brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_pmksa *pmksa)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
- struct _pmkid_list pmkid;
+ struct pmkid_list pmkid;
s32 err = 0;
- int i;
+ int i, pmkid_len;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
+
memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
@@ -2238,17 +2686,18 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
for (i = 0; i < WLAN_PMKID_LEN; i++)
WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
- for (i = 0; i < cfg_priv->pmk_list->pmkids.npmkid; i++)
+ pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid);
+ for (i = 0; i < pmkid_len; i++)
if (!memcmp
(pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
ETH_ALEN))
break;
- if ((cfg_priv->pmk_list->pmkids.npmkid > 0)
- && (i < cfg_priv->pmk_list->pmkids.npmkid)) {
+ if ((pmkid_len > 0)
+ && (i < pmkid_len)) {
memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
- sizeof(pmkid_t));
- for (; i < (cfg_priv->pmk_list->pmkids.npmkid - 1); i++) {
+ sizeof(struct pmkid));
+ for (; i < (pmkid_len - 1); i++) {
memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
&cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
ETH_ALEN);
@@ -2256,11 +2705,11 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
&cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
WLAN_PMKID_LEN);
}
- cfg_priv->pmk_list->pmkids.npmkid--;
+ cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
} else
err = -EINVAL;
- err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
+ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
WL_TRACE("Exit\n");
return err;
@@ -2268,16 +2717,17 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
}
static s32
-brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
+brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
- err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
+ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
WL_TRACE("Exit\n");
return err;
@@ -2326,25 +2776,24 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
}
static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
- struct device *dev)
+ struct device *ndev)
{
struct wireless_dev *wdev;
s32 err = 0;
wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
- if (unlikely(!wdev)) {
- WL_ERR("Could not allocate wireless device\n");
+ if (!wdev)
return ERR_PTR(-ENOMEM);
- }
+
wdev->wiphy =
wiphy_new(&wl_cfg80211_ops,
sizeof(struct brcmf_cfg80211_priv) + sizeof_iface);
- if (unlikely(!wdev->wiphy)) {
+ if (!wdev->wiphy) {
WL_ERR("Couldn not allocate wiphy device\n");
err = -ENOMEM;
goto wiphy_new_out;
}
- set_wiphy_dev(wdev->wiphy, dev);
+ set_wiphy_dev(wdev->wiphy, ndev);
wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
wdev->wiphy->interface_modes =
@@ -2360,16 +2809,12 @@ static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
wdev->wiphy->cipher_suites = __wl_cipher_suites;
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
-#ifndef WL_POWERSAVE_DISABLED
wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
* save mode
* by default
*/
-#else
- wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
-#endif /* !WL_POWERSAVE_DISABLED */
err = wiphy_register(wdev->wiphy);
- if (unlikely(err < 0)) {
+ if (err < 0) {
WL_ERR("Couldn not register wiphy device (%d)\n", err);
goto wiphy_register_out;
}
@@ -2386,175 +2831,16 @@ wiphy_new_out:
static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct wireless_dev *wdev = cfg_to_wdev(cfg_priv);
+ struct wireless_dev *wdev = cfg_priv->wdev;
- if (unlikely(!wdev)) {
+ if (!wdev) {
WL_ERR("wdev is invalid\n");
return;
}
wiphy_unregister(wdev->wiphy);
wiphy_free(wdev->wiphy);
kfree(wdev);
- cfg_to_wdev(cfg_priv) = NULL;
-}
-
-static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_scan_results *bss_list;
- struct brcmf_bss_info *bi = NULL; /* must be initialized */
- s32 err = 0;
- int i;
-
- bss_list = cfg_priv->bss_list;
- if (unlikely(bss_list->version != BRCMF_BSS_INFO_VERSION)) {
- WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
- bss_list->version);
- return -EOPNOTSUPP;
- }
- WL_SCAN("scanned AP count (%d)\n", bss_list->count);
- bi = next_bss(bss_list, bi);
- for_each_bss(bss_list, bi, i) {
- err = brcmf_inform_single_bss(cfg_priv, bi);
- if (unlikely(err))
- break;
- }
- return err;
-}
-
-
-static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
- struct brcmf_bss_info *bi)
-{
- struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
- struct ieee80211_channel *notify_channel;
- struct cfg80211_bss *bss;
- struct ieee80211_supported_band *band;
- s32 err = 0;
- u16 channel;
- u32 freq;
- u64 notify_timestamp;
- u16 notify_capability;
- u16 notify_interval;
- u8 *notify_ie;
- size_t notify_ielen;
- s32 notify_signal;
-
- if (unlikely(le32_to_cpu(bi->length) > WL_BSS_INFO_MAX)) {
- WL_ERR("Bss info is larger than buffer. Discarding\n");
- return 0;
- }
-
- channel = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
-
- if (channel <= CH_MAX_2G_CHANNEL)
- band = wiphy->bands[IEEE80211_BAND_2GHZ];
- else
- band = wiphy->bands[IEEE80211_BAND_5GHZ];
-
- freq = ieee80211_channel_to_frequency(channel, band->band);
- notify_channel = ieee80211_get_channel(wiphy, freq);
-
- notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
- notify_capability = le16_to_cpu(bi->capability);
- notify_interval = le16_to_cpu(bi->beacon_period);
- notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
- notify_ielen = le16_to_cpu(bi->ie_length);
- notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
-
- WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
- bi->BSSID[0], bi->BSSID[1], bi->BSSID[2],
- bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]);
- WL_CONN("Channel: %d(%d)\n", channel, freq);
- WL_CONN("Capability: %X\n", notify_capability);
- WL_CONN("Beacon interval: %d\n", notify_interval);
- WL_CONN("Signal: %d\n", notify_signal);
- WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
-
- bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
- notify_timestamp, notify_capability, notify_interval, notify_ie,
- notify_ielen, notify_signal, GFP_KERNEL);
-
- if (unlikely(!bss)) {
- WL_ERR("cfg80211_inform_bss_frame error\n");
- return -EINVAL;
- }
-
- return err;
-}
-
-static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *dev, const u8 *bssid)
-{
- struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
- struct ieee80211_channel *notify_channel;
- struct brcmf_bss_info *bi = NULL;
- struct ieee80211_supported_band *band;
- u8 *buf = NULL;
- s32 err = 0;
- u16 channel;
- u32 freq;
- u64 notify_timestamp;
- u16 notify_capability;
- u16 notify_interval;
- u8 *notify_ie;
- size_t notify_ielen;
- s32 notify_signal;
-
- WL_TRACE("Enter\n");
-
- buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
- if (buf == NULL) {
- WL_ERR("kzalloc() failed\n");
- err = -ENOMEM;
- goto CleanUp;
- }
-
- *(u32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
-
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
- if (unlikely(err)) {
- WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
- goto CleanUp;
- }
-
- bi = (struct brcmf_bss_info *)(buf + 4);
-
- channel = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
-
- if (channel <= CH_MAX_2G_CHANNEL)
- band = wiphy->bands[IEEE80211_BAND_2GHZ];
- else
- band = wiphy->bands[IEEE80211_BAND_5GHZ];
-
- freq = ieee80211_channel_to_frequency(channel, band->band);
- notify_channel = ieee80211_get_channel(wiphy, freq);
-
- notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
- notify_capability = le16_to_cpu(bi->capability);
- notify_interval = le16_to_cpu(bi->beacon_period);
- notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
- notify_ielen = le16_to_cpu(bi->ie_length);
- notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
-
- WL_CONN("channel: %d(%d)\n", channel, freq);
- WL_CONN("capability: %X\n", notify_capability);
- WL_CONN("beacon interval: %d\n", notify_interval);
- WL_CONN("signal: %d\n", notify_signal);
- WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
-
- cfg80211_inform_bss(wiphy, notify_channel, bssid,
- notify_timestamp, notify_capability, notify_interval,
- notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
-
-CleanUp:
-
- kfree(buf);
-
- WL_TRACE("Exit\n");
-
- return err;
+ cfg_priv->wdev = NULL;
}
static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
@@ -2606,110 +2892,22 @@ static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
return false;
}
-static s32
-brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data)
-{
- s32 err = 0;
-
- if (brcmf_is_linkup(cfg_priv, e)) {
- WL_CONN("Linkup\n");
- if (brcmf_is_ibssmode(cfg_priv)) {
- brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
- WL_PROF_BSSID);
- wl_inform_ibss(cfg_priv, ndev, e->addr);
- cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
- clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
- set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
- } else
- brcmf_bss_connect_done(cfg_priv, ndev, e, data, true);
- } else if (brcmf_is_linkdown(cfg_priv, e)) {
- WL_CONN("Linkdown\n");
- if (brcmf_is_ibssmode(cfg_priv)) {
- clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
- if (test_and_clear_bit(WL_STATUS_CONNECTED,
- &cfg_priv->status))
- brcmf_link_down(cfg_priv);
- } else {
- brcmf_bss_connect_done(cfg_priv, ndev, e, data, false);
- if (test_and_clear_bit(WL_STATUS_CONNECTED,
- &cfg_priv->status)) {
- cfg80211_disconnected(ndev, 0, NULL, 0,
- GFP_KERNEL);
- brcmf_link_down(cfg_priv);
- }
- }
- brcmf_init_prof(cfg_priv->profile);
- } else if (brcmf_is_nonetwork(cfg_priv, e)) {
- if (brcmf_is_ibssmode(cfg_priv))
- clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
- else
- brcmf_bss_connect_done(cfg_priv, ndev, e, data, false);
- }
-
- return err;
-}
-
-static s32
-brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data)
-{
- s32 err = 0;
- u32 event = be32_to_cpu(e->event_type);
- u32 status = be32_to_cpu(e->status);
-
- if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
- if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
- brcmf_bss_roaming_done(cfg_priv, ndev, e, data);
- else
- brcmf_bss_connect_done(cfg_priv, ndev, e, data, true);
- }
-
- return err;
-}
-
-static __used s32
-brcmf_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
-{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
- u32 buflen;
-
- buflen = brcmu_mkiovar(name, buf, len, cfg_priv->ioctl_buf,
- WL_IOCTL_LEN_MAX);
- BUG_ON(!buflen);
-
- return brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, cfg_priv->ioctl_buf,
- buflen);
-}
-
-static s32
-brcmf_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
- s32 buf_len)
+static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
- u32 len;
- s32 err = 0;
-
- len = brcmu_mkiovar(name, NULL, 0, cfg_priv->ioctl_buf,
- WL_IOCTL_LEN_MAX);
- BUG_ON(!len);
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, (void *)cfg_priv->ioctl_buf,
- WL_IOCTL_LEN_MAX);
- if (unlikely(err)) {
- WL_ERR("error (%d)\n", err);
- return err;
- }
- memcpy(buf, cfg_priv->ioctl_buf, buf_len);
+ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
- return err;
+ kfree(conn_info->req_ie);
+ conn_info->req_ie = NULL;
+ conn_info->req_ie_len = 0;
+ kfree(conn_info->resp_ie);
+ conn_info->resp_ie = NULL;
+ conn_info->resp_ie_len = 0;
}
static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
{
struct net_device *ndev = cfg_to_ndev(cfg_priv);
- struct brcmf_cfg80211_assoc_ielen *assoc_info;
+ struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
u32 req_len;
u32 resp_len;
@@ -2719,18 +2917,19 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf,
WL_ASSOC_INFO_MAX);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("could not get assoc info (%d)\n", err);
return err;
}
- assoc_info = (struct brcmf_cfg80211_assoc_ielen *)cfg_priv->extra_buf;
- req_len = assoc_info->req_len;
- resp_len = assoc_info->resp_len;
+ assoc_info =
+ (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf;
+ req_len = le32_to_cpu(assoc_info->req_len);
+ resp_len = le32_to_cpu(assoc_info->resp_len);
if (req_len) {
err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
cfg_priv->extra_buf,
WL_ASSOC_INFO_MAX);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("could not get assoc req (%d)\n", err);
return err;
}
@@ -2746,7 +2945,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
cfg_priv->extra_buf,
WL_ASSOC_INFO_MAX);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("could not get assoc resp (%d)\n", err);
return err;
}
@@ -2764,121 +2963,19 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
return err;
}
-static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
-
- kfree(conn_info->req_ie);
- conn_info->req_ie = NULL;
- conn_info->req_ie_len = 0;
- kfree(conn_info->resp_ie);
- conn_info->resp_ie = NULL;
- conn_info->resp_ie_len = 0;
-}
-
-
-static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
- size_t *join_params_size)
-{
- chanspec_t chanspec = 0;
-
- if (ch != 0) {
- join_params->params.chanspec_num = 1;
- join_params->params.chanspec_list[0] = ch;
-
- if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
- chanspec |= WL_CHANSPEC_BAND_2G;
- else
- chanspec |= WL_CHANSPEC_BAND_5G;
-
- chanspec |= WL_CHANSPEC_BW_20;
- chanspec |= WL_CHANSPEC_CTL_SB_NONE;
-
- *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
- join_params->params.chanspec_num * sizeof(chanspec_t);
-
- join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
- join_params->params.chanspec_list[0] |= chanspec;
- join_params->params.chanspec_list[0] =
- cpu_to_le16(join_params->params.chanspec_list[0]);
-
- join_params->params.chanspec_num =
- cpu_to_le32(join_params->params.chanspec_num);
-
- WL_CONN("join_params->params.chanspec_list[0]= %#X,"
- "channel %d, chanspec %#X\n",
- join_params->params.chanspec_list[0], ch, chanspec);
- }
-}
-
-static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_bss_info *bi;
- struct brcmf_ssid *ssid;
- struct brcmu_tlv *tim;
- u16 beacon_interval;
- u8 dtim_period;
- size_t ie_len;
- u8 *ie;
- s32 err = 0;
-
- WL_TRACE("Enter\n");
- if (brcmf_is_ibssmode(cfg_priv))
- return err;
-
- ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID);
-
- *(u32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
- err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO,
- cfg_priv->extra_buf, WL_EXTRA_BUF_MAX);
- if (unlikely(err)) {
- WL_ERR("Could not get bss info %d\n", err);
- goto update_bss_info_out;
- }
-
- bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4);
- err = brcmf_inform_single_bss(cfg_priv, bi);
- if (unlikely(err))
- goto update_bss_info_out;
-
- ie = ((u8 *)bi) + bi->ie_offset;
- ie_len = bi->ie_length;
- beacon_interval = cpu_to_le16(bi->beacon_period);
-
- tim = brcmu_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
- if (tim)
- dtim_period = tim->data[1];
- else {
- /*
- * active scan was done so we could not get dtim
- * information out of probe response.
- * so we speficially query dtim information to dongle.
- */
- u32 var;
- err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv),
- "dtim_assoc", &var);
- if (unlikely(err)) {
- WL_ERR("wl dtim_assoc failed (%d)\n", err);
- goto update_bss_info_out;
- }
- dtim_period = (u8)var;
- }
-
- brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT);
- brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
-
-update_bss_info_out:
- WL_TRACE("Exit");
- return err;
-}
-
static s32
brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data)
+ const struct brcmf_event_msg *e)
{
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
+ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
+ struct brcmf_channel_info_le channel_le;
+ struct ieee80211_channel *notify_channel;
+ struct ieee80211_supported_band *band;
+ u32 freq;
s32 err = 0;
+ u32 target_channel;
WL_TRACE("Enter\n");
@@ -2886,7 +2983,21 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
brcmf_update_bss_info(cfg_priv);
- cfg80211_roamed(ndev, NULL,
+ brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
+ sizeof(channel_le));
+
+ target_channel = le32_to_cpu(channel_le.target_channel);
+ WL_CONN("Roamed to channel %d\n", target_channel);
+
+ if (target_channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+ freq = ieee80211_channel_to_frequency(target_channel, band->band);
+ notify_channel = ieee80211_get_channel(wiphy, freq);
+
+ cfg80211_roamed(ndev, notify_channel,
(u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
conn_info->req_ie, conn_info->req_ie_len,
conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
@@ -2900,7 +3011,7 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
static s32
brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
struct net_device *ndev, const struct brcmf_event_msg *e,
- void *data, bool completed)
+ bool completed)
{
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
s32 err = 0;
@@ -2934,6 +3045,57 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
}
static s32
+brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
+ struct net_device *ndev,
+ const struct brcmf_event_msg *e, void *data)
+{
+ s32 err = 0;
+
+ if (brcmf_is_linkup(cfg_priv, e)) {
+ WL_CONN("Linkup\n");
+ if (brcmf_is_ibssmode(cfg_priv)) {
+ brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
+ WL_PROF_BSSID);
+ wl_inform_ibss(cfg_priv, ndev, e->addr);
+ cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
+ set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
+ } else
+ brcmf_bss_connect_done(cfg_priv, ndev, e, true);
+ } else if (brcmf_is_linkdown(cfg_priv, e)) {
+ WL_CONN("Linkdown\n");
+ brcmf_link_down(cfg_priv);
+ brcmf_init_prof(cfg_priv->profile);
+ } else if (brcmf_is_nonetwork(cfg_priv, e)) {
+ if (brcmf_is_ibssmode(cfg_priv))
+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
+ else
+ brcmf_bss_connect_done(cfg_priv, ndev, e, false);
+ }
+
+ return err;
+}
+
+static s32
+brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
+ struct net_device *ndev,
+ const struct brcmf_event_msg *e, void *data)
+{
+ s32 err = 0;
+ u32 event = be32_to_cpu(e->event_type);
+ u32 status = be32_to_cpu(e->status);
+
+ if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
+ if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
+ brcmf_bss_roaming_done(cfg_priv, ndev, e);
+ else
+ brcmf_bss_connect_done(cfg_priv, ndev, e, true);
+ }
+
+ return err;
+}
+
+static s32
brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
struct net_device *ndev,
const struct brcmf_event_msg *e, void *data)
@@ -2941,7 +3103,6 @@ brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
u16 flags = be16_to_cpu(e->flags);
enum nl80211_key_type key_type;
- rtnl_lock();
if (flags & BRCMF_EVENT_MSG_GROUP)
key_type = NL80211_KEYTYPE_GROUP;
else
@@ -2949,7 +3110,6 @@ brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
NULL, GFP_KERNEL);
- rtnl_unlock();
return 0;
}
@@ -2959,11 +3119,12 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
struct net_device *ndev,
const struct brcmf_event_msg *e, void *data)
{
- struct brcmf_channel_info channel_inform;
- struct brcmf_scan_results *bss_list;
+ struct brcmf_channel_info_le channel_inform_le;
+ struct brcmf_scan_results_le *bss_list_le;
u32 len = WL_SCAN_BUF_MAX;
s32 err = 0;
bool scan_abort = false;
+ u32 scan_channel;
WL_TRACE("Enter\n");
@@ -2972,42 +3133,39 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
}
- if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING,
- &cfg_priv->status))) {
+ if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
WL_ERR("Scan complete while device not scanning\n");
scan_abort = true;
err = -EINVAL;
goto scan_done_out;
}
- err = brcmf_dev_ioctl(ndev, BRCMF_C_GET_CHANNEL, &channel_inform,
- sizeof(channel_inform));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le,
+ sizeof(channel_inform_le));
+ if (err) {
WL_ERR("scan busy (%d)\n", err);
scan_abort = true;
goto scan_done_out;
}
- channel_inform.scan_channel = le32_to_cpu(channel_inform.scan_channel);
- if (unlikely(channel_inform.scan_channel)) {
-
- WL_CONN("channel_inform.scan_channel (%d)\n",
- channel_inform.scan_channel);
- }
+ scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
+ if (scan_channel)
+ WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
cfg_priv->bss_list = cfg_priv->scan_results;
- bss_list = cfg_priv->bss_list;
- memset(bss_list, 0, len);
- bss_list->buflen = cpu_to_le32(len);
+ bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list;
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SCAN_RESULTS, bss_list, len);
- if (unlikely(err)) {
+ memset(cfg_priv->scan_results, 0, len);
+ bss_list_le->buflen = cpu_to_le32(len);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
+ cfg_priv->scan_results, len);
+ if (err) {
WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
err = -EINVAL;
scan_abort = true;
goto scan_done_out;
}
- bss_list->buflen = le32_to_cpu(bss_list->buflen);
- bss_list->version = le32_to_cpu(bss_list->version);
- bss_list->count = le32_to_cpu(bss_list->count);
+ cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
+ cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version);
+ cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count);
err = brcmf_inform_bss(cfg_priv);
if (err) {
@@ -3038,11 +3196,6 @@ static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
conf->tx_power = -1;
}
-static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
-{
- memset(prof, 0, sizeof(*prof));
-}
-
static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
{
memset(el, 0, sizeof(*el));
@@ -3053,54 +3206,58 @@ static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
}
+static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ kfree(cfg_priv->scan_results);
+ cfg_priv->scan_results = NULL;
+ kfree(cfg_priv->bss_info);
+ cfg_priv->bss_info = NULL;
+ kfree(cfg_priv->conf);
+ cfg_priv->conf = NULL;
+ kfree(cfg_priv->profile);
+ cfg_priv->profile = NULL;
+ kfree(cfg_priv->scan_req_int);
+ cfg_priv->scan_req_int = NULL;
+ kfree(cfg_priv->dcmd_buf);
+ cfg_priv->dcmd_buf = NULL;
+ kfree(cfg_priv->extra_buf);
+ cfg_priv->extra_buf = NULL;
+ kfree(cfg_priv->iscan);
+ cfg_priv->iscan = NULL;
+ kfree(cfg_priv->pmk_list);
+ cfg_priv->pmk_list = NULL;
+}
+
static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
{
cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
- if (unlikely(!cfg_priv->scan_results)) {
- WL_ERR("Scan results alloc failed\n");
+ if (!cfg_priv->scan_results)
goto init_priv_mem_out;
- }
cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
- if (unlikely(!cfg_priv->conf)) {
- WL_ERR("wl_conf alloc failed\n");
+ if (!cfg_priv->conf)
goto init_priv_mem_out;
- }
cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
- if (unlikely(!cfg_priv->profile)) {
- WL_ERR("wl_profile alloc failed\n");
+ if (!cfg_priv->profile)
goto init_priv_mem_out;
- }
cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
- if (unlikely(!cfg_priv->bss_info)) {
- WL_ERR("Bss information alloc failed\n");
+ if (!cfg_priv->bss_info)
goto init_priv_mem_out;
- }
cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
GFP_KERNEL);
- if (unlikely(!cfg_priv->scan_req_int)) {
- WL_ERR("Scan req alloc failed\n");
+ if (!cfg_priv->scan_req_int)
goto init_priv_mem_out;
- }
- cfg_priv->ioctl_buf = kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
- if (unlikely(!cfg_priv->ioctl_buf)) {
- WL_ERR("Ioctl buf alloc failed\n");
+ cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
+ if (!cfg_priv->dcmd_buf)
goto init_priv_mem_out;
- }
cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
- if (unlikely(!cfg_priv->extra_buf)) {
- WL_ERR("Extra buf alloc failed\n");
+ if (!cfg_priv->extra_buf)
goto init_priv_mem_out;
- }
cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
- if (unlikely(!cfg_priv->iscan)) {
- WL_ERR("Iscan buf alloc failed\n");
+ if (!cfg_priv->iscan)
goto init_priv_mem_out;
- }
cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
- if (unlikely(!cfg_priv->pmk_list)) {
- WL_ERR("pmk list alloc failed\n");
+ if (!cfg_priv->pmk_list)
goto init_priv_mem_out;
- }
return 0;
@@ -3110,301 +3267,111 @@ init_priv_mem_out:
return -ENOMEM;
}
-static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
-{
- kfree(cfg_priv->scan_results);
- cfg_priv->scan_results = NULL;
- kfree(cfg_priv->bss_info);
- cfg_priv->bss_info = NULL;
- kfree(cfg_priv->conf);
- cfg_priv->conf = NULL;
- kfree(cfg_priv->profile);
- cfg_priv->profile = NULL;
- kfree(cfg_priv->scan_req_int);
- cfg_priv->scan_req_int = NULL;
- kfree(cfg_priv->ioctl_buf);
- cfg_priv->ioctl_buf = NULL;
- kfree(cfg_priv->extra_buf);
- cfg_priv->extra_buf = NULL;
- kfree(cfg_priv->iscan);
- cfg_priv->iscan = NULL;
- kfree(cfg_priv->pmk_list);
- cfg_priv->pmk_list = NULL;
-}
-
-static s32 brcmf_create_event_handler(struct brcmf_cfg80211_priv *cfg_priv)
-{
- sema_init(&cfg_priv->event_sync, 0);
- cfg_priv->event_tsk = kthread_run(brcmf_event_handler, cfg_priv,
- "wl_event_handler");
- if (IS_ERR(cfg_priv->event_tsk)) {
- cfg_priv->event_tsk = NULL;
- WL_ERR("failed to create event thread\n");
- return -ENOMEM;
- }
- return 0;
-}
-
-static void brcmf_destroy_event_handler(struct brcmf_cfg80211_priv *cfg_priv)
-{
- if (cfg_priv->event_tsk) {
- send_sig(SIGTERM, cfg_priv->event_tsk, 1);
- kthread_stop(cfg_priv->event_tsk);
- cfg_priv->event_tsk = NULL;
- }
-}
+/*
+* retrieve first queued event from head
+*/
-static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv)
+static struct brcmf_cfg80211_event_q *brcmf_deq_event(
+ struct brcmf_cfg80211_priv *cfg_priv)
{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
+ struct brcmf_cfg80211_event_q *e = NULL;
- if (cfg_priv->iscan_on && iscan->tsk) {
- iscan->state = WL_ISCAN_STATE_IDLE;
- send_sig(SIGTERM, iscan->tsk, 1);
- kthread_stop(iscan->tsk);
- iscan->tsk = NULL;
+ spin_lock_irq(&cfg_priv->evt_q_lock);
+ if (!list_empty(&cfg_priv->evt_q_list)) {
+ e = list_first_entry(&cfg_priv->evt_q_list,
+ struct brcmf_cfg80211_event_q, evt_q_list);
+ list_del(&e->evt_q_list);
}
-}
-
-static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
- bool aborted)
-{
- struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
- struct net_device *ndev = cfg_to_ndev(cfg_priv);
+ spin_unlock_irq(&cfg_priv->evt_q_lock);
- if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING,
- &cfg_priv->status))) {
- WL_ERR("Scan complete while device not scanning\n");
- return;
- }
- if (likely(cfg_priv->scan_request)) {
- WL_SCAN("ISCAN Completed scan: %s\n",
- aborted ? "Aborted" : "Done");
- cfg80211_scan_done(cfg_priv->scan_request, aborted);
- brcmf_set_mpc(ndev, 1);
- cfg_priv->scan_request = NULL;
- }
- cfg_priv->iscan_kickstart = false;
+ return e;
}
-static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
-{
- if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
- WL_SCAN("wake up iscan\n");
- up(&iscan->sync);
- return 0;
- }
-
- return -EIO;
-}
+/*
+** push event to tail of the queue
+*/
static s32
-brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
- struct brcmf_scan_results **bss_list)
-{
- struct brcmf_iscan_results list;
- struct brcmf_scan_results *results;
- struct brcmf_iscan_results *list_buf;
- s32 err = 0;
-
- memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
- list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
- results = &list_buf->results;
- results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
- results->version = 0;
- results->count = 0;
-
- memset(&list, 0, sizeof(list));
- list.results.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
- err = brcmf_dev_iovar_getbuf(iscan->dev, "iscanresults", &list,
- BRCMF_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
- WL_ISCAN_BUF_MAX);
- if (unlikely(err)) {
- WL_ERR("error (%d)\n", err);
- return err;
- }
- results->buflen = le32_to_cpu(results->buflen);
- results->version = le32_to_cpu(results->version);
- results->count = le32_to_cpu(results->count);
- WL_SCAN("results->count = %d\n", results->count);
- WL_SCAN("results->buflen = %d\n", results->buflen);
- *status = le32_to_cpu(list_buf->status);
- *bss_list = results;
-
- return err;
-}
-
-static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
- s32 err = 0;
-
- iscan->state = WL_ISCAN_STATE_IDLE;
- rtnl_lock();
- brcmf_inform_bss(cfg_priv);
- brcmf_notify_iscan_complete(iscan, false);
- rtnl_unlock();
-
- return err;
-}
-
-static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
- s32 err = 0;
-
- /* Reschedule the timer */
- mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
- iscan->timer_on = 1;
-
- return err;
-}
-
-static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv)
+brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
+ const struct brcmf_event_msg *msg)
{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
+ struct brcmf_cfg80211_event_q *e;
s32 err = 0;
- rtnl_lock();
- brcmf_inform_bss(cfg_priv);
- brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
- rtnl_unlock();
- /* Reschedule the timer */
- mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
- iscan->timer_on = 1;
-
- return err;
-}
+ e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
-static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
- s32 err = 0;
+ e->etype = event;
+ memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
- iscan->state = WL_ISCAN_STATE_IDLE;
- rtnl_lock();
- brcmf_notify_iscan_complete(iscan, true);
- rtnl_unlock();
+ spin_lock_irq(&cfg_priv->evt_q_lock);
+ list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
+ spin_unlock_irq(&cfg_priv->evt_q_lock);
return err;
}
-static s32 brcmf_iscan_thread(void *data)
+static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
{
- struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
- struct brcmf_cfg80211_iscan_ctrl *iscan =
- (struct brcmf_cfg80211_iscan_ctrl *)data;
- struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
- struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
- u32 status;
- int err = 0;
-
- sched_setscheduler(current, SCHED_FIFO, &param);
- allow_signal(SIGTERM);
- status = BRCMF_SCAN_RESULTS_PARTIAL;
- while (likely(!down_interruptible(&iscan->sync))) {
- if (kthread_should_stop())
- break;
- if (iscan->timer_on) {
- del_timer_sync(&iscan->timer);
- iscan->timer_on = 0;
- }
- rtnl_lock();
- err = brcmf_get_iscan_results(iscan, &status,
- &cfg_priv->bss_list);
- if (unlikely(err)) {
- status = BRCMF_SCAN_RESULTS_ABORTED;
- WL_ERR("Abort iscan\n");
- }
- rtnl_unlock();
- el->handler[status](cfg_priv);
- }
- if (iscan->timer_on) {
- del_timer_sync(&iscan->timer);
- iscan->timer_on = 0;
- }
- WL_SCAN("ISCAN thread terminated\n");
-
- return 0;
+ kfree(e);
}
-static void brcmf_iscan_timer(unsigned long data)
+static void brcmf_cfg80211_event_handler(struct work_struct *work)
{
- struct brcmf_cfg80211_iscan_ctrl *iscan =
- (struct brcmf_cfg80211_iscan_ctrl *)data;
+ struct brcmf_cfg80211_priv *cfg_priv =
+ container_of(work, struct brcmf_cfg80211_priv,
+ event_work);
+ struct brcmf_cfg80211_event_q *e;
- if (iscan) {
- iscan->timer_on = 0;
- WL_SCAN("timer expired\n");
- brcmf_wakeup_iscan(iscan);
+ e = brcmf_deq_event(cfg_priv);
+ if (unlikely(!e)) {
+ WL_ERR("event queue empty...\n");
+ return;
}
-}
-static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
- int err = 0;
-
- if (cfg_priv->iscan_on && !iscan->tsk) {
- iscan->state = WL_ISCAN_STATE_IDLE;
- sema_init(&iscan->sync, 0);
- iscan->tsk = kthread_run(brcmf_iscan_thread, iscan, "wl_iscan");
- if (IS_ERR(iscan->tsk)) {
- WL_ERR("Could not create iscan thread\n");
- iscan->tsk = NULL;
- return -ENOMEM;
- }
- }
+ do {
+ WL_INFO("event type (%d)\n", e->etype);
+ if (cfg_priv->el.handler[e->etype])
+ cfg_priv->el.handler[e->etype](cfg_priv,
+ cfg_to_ndev(cfg_priv),
+ &e->emsg, e->edata);
+ else
+ WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
+ brcmf_put_event(e);
+ } while ((e = brcmf_deq_event(cfg_priv)));
- return err;
}
-static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
+static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
{
- memset(el, 0, sizeof(*el));
- el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
- el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
- el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
- el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
- el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
+ spin_lock_init(&cfg_priv->evt_q_lock);
+ INIT_LIST_HEAD(&cfg_priv->evt_q_list);
}
-static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
+static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
- int err = 0;
+ struct brcmf_cfg80211_event_q *e;
- if (cfg_priv->iscan_on) {
- iscan->dev = cfg_to_ndev(cfg_priv);
- iscan->state = WL_ISCAN_STATE_IDLE;
- brcmf_init_iscan_eloop(&iscan->el);
- iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
- init_timer(&iscan->timer);
- iscan->timer.data = (unsigned long) iscan;
- iscan->timer.function = brcmf_iscan_timer;
- sema_init(&iscan->sync, 0);
- iscan->tsk = kthread_run(brcmf_iscan_thread, iscan, "wl_iscan");
- if (IS_ERR(iscan->tsk)) {
- WL_ERR("Could not create iscan thread\n");
- iscan->tsk = NULL;
- return -ENOMEM;
- }
- iscan->data = cfg_priv;
+ spin_lock_irq(&cfg_priv->evt_q_lock);
+ while (!list_empty(&cfg_priv->evt_q_list)) {
+ e = list_first_entry(&cfg_priv->evt_q_list,
+ struct brcmf_cfg80211_event_q, evt_q_list);
+ list_del(&e->evt_q_list);
+ kfree(e);
}
-
- return err;
+ spin_unlock_irq(&cfg_priv->evt_q_lock);
}
static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
s32 err = 0;
cfg_priv->scan_request = NULL;
- cfg_priv->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
+ cfg_priv->pwr_save = true;
cfg_priv->iscan_on = true; /* iscan on & off switch.
we enable iscan per default */
- cfg_priv->roam_on = false; /* roam on & off switch.
+ cfg_priv->roam_on = true; /* roam on & off switch.
we enable roam per default */
cfg_priv->iscan_kickstart = false;
@@ -3413,14 +3380,13 @@ static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
cfg_priv->dongle_up = false; /* dongle is not up yet */
brcmf_init_eq(cfg_priv);
err = brcmf_init_priv_mem(cfg_priv);
- if (unlikely(err))
+ if (err)
return err;
- if (unlikely(brcmf_create_event_handler(cfg_priv)))
- return -ENOMEM;
+ INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler);
brcmf_init_eloop_handler(&cfg_priv->el);
mutex_init(&cfg_priv->usr_sync);
err = brcmf_init_iscan(cfg_priv);
- if (unlikely(err))
+ if (err)
return err;
brcmf_init_conf(cfg_priv->conf);
brcmf_init_prof(cfg_priv->profile);
@@ -3431,7 +3397,7 @@ static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
{
- brcmf_destroy_event_handler(cfg_priv);
+ cancel_work_sync(&cfg_priv->event_work);
cfg_priv->dongle_up = false; /* dongle down */
brcmf_flush_eq(cfg_priv);
brcmf_link_down(cfg_priv);
@@ -3439,27 +3405,29 @@ static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
brcmf_deinit_priv_mem(cfg_priv);
}
-s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data)
+struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
+ struct device *busdev,
+ void *data)
{
struct wireless_dev *wdev;
struct brcmf_cfg80211_priv *cfg_priv;
struct brcmf_cfg80211_iface *ci;
+ struct brcmf_cfg80211_dev *cfg_dev;
s32 err = 0;
- if (unlikely(!ndev)) {
+ if (!ndev) {
WL_ERR("ndev is invalid\n");
- return -ENODEV;
+ return NULL;
}
- cfg80211_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
- if (unlikely(!cfg80211_dev)) {
- WL_ERR("wl_cfg80211_dev is invalid\n");
- return -ENOMEM;
+ cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
+ if (!cfg_dev)
+ return NULL;
+
+ wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev);
+ if (IS_ERR(wdev)) {
+ kfree(cfg_dev);
+ return NULL;
}
- WL_INFO("func %p\n", brcmf_cfg80211_get_sdio_func());
- wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface),
- &brcmf_cfg80211_get_sdio_func()->dev);
- if (IS_ERR(wdev))
- return -ENOMEM;
wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
cfg_priv = wdev_to_cfg(wdev);
@@ -3471,67 +3439,30 @@ s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data)
SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
wdev->netdev = ndev;
err = wl_init_priv(cfg_priv);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("Failed to init iwm_priv (%d)\n", err);
goto cfg80211_attach_out;
}
- brcmf_set_drvdata(cfg80211_dev, ci);
+ brcmf_set_drvdata(cfg_dev, ci);
- return err;
+ return cfg_dev;
cfg80211_attach_out:
brcmf_free_wdev(cfg_priv);
- return err;
+ kfree(cfg_dev);
+ return NULL;
}
-void brcmf_cfg80211_detach(void)
+void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev)
{
struct brcmf_cfg80211_priv *cfg_priv;
- cfg_priv = WL_PRIV_GET();
+ cfg_priv = brcmf_priv_get(cfg_dev);
wl_deinit_priv(cfg_priv);
brcmf_free_wdev(cfg_priv);
- brcmf_set_drvdata(cfg80211_dev, NULL);
- kfree(cfg80211_dev);
- cfg80211_dev = NULL;
- brcmf_clear_sdio_func();
-}
-
-static void brcmf_wakeup_event(struct brcmf_cfg80211_priv *cfg_priv)
-{
- up(&cfg_priv->event_sync);
-}
-
-static s32 brcmf_event_handler(void *data)
-{
- struct brcmf_cfg80211_priv *cfg_priv =
- (struct brcmf_cfg80211_priv *)data;
- struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
- struct brcmf_cfg80211_event_q *e;
-
- sched_setscheduler(current, SCHED_FIFO, &param);
- allow_signal(SIGTERM);
- while (likely(!down_interruptible(&cfg_priv->event_sync))) {
- if (kthread_should_stop())
- break;
- e = brcmf_deq_event(cfg_priv);
- if (unlikely(!e)) {
- WL_ERR("event queue empty...\n");
- BUG();
- }
- WL_INFO("event type (%d)\n", e->etype);
- if (cfg_priv->el.handler[e->etype]) {
- cfg_priv->el.handler[e->etype](cfg_priv,
- cfg_to_ndev(cfg_priv),
- &e->emsg, e->edata);
- } else {
- WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
- }
- brcmf_put_event(e);
- }
- WL_INFO("was terminated\n");
- return 0;
+ brcmf_set_drvdata(cfg_dev, NULL);
+ kfree(cfg_dev);
}
void
@@ -3541,95 +3472,8 @@ brcmf_cfg80211_event(struct net_device *ndev,
u32 event_type = be32_to_cpu(e->event_type);
struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
- if (likely(!brcmf_enq_event(cfg_priv, event_type, e, data)))
- brcmf_wakeup_event(cfg_priv);
-}
-
-static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
-{
- brcmf_init_eq_lock(cfg_priv);
- INIT_LIST_HEAD(&cfg_priv->eq_list);
-}
-
-static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_event_q *e;
-
- brcmf_lock_eq(cfg_priv);
- while (!list_empty(&cfg_priv->eq_list)) {
- e = list_first_entry(&cfg_priv->eq_list,
- struct brcmf_cfg80211_event_q, eq_list);
- list_del(&e->eq_list);
- kfree(e);
- }
- brcmf_unlock_eq(cfg_priv);
-}
-
-/*
-* retrieve first queued event from head
-*/
-
-static struct brcmf_cfg80211_event_q *brcmf_deq_event(
- struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_event_q *e = NULL;
-
- brcmf_lock_eq(cfg_priv);
- if (likely(!list_empty(&cfg_priv->eq_list))) {
- e = list_first_entry(&cfg_priv->eq_list,
- struct brcmf_cfg80211_event_q, eq_list);
- list_del(&e->eq_list);
- }
- brcmf_unlock_eq(cfg_priv);
-
- return e;
-}
-
-/*
-** push event to tail of the queue
-*/
-
-static s32
-brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
- const struct brcmf_event_msg *msg, void *data)
-{
- struct brcmf_cfg80211_event_q *e;
- s32 err = 0;
-
- e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL);
- if (unlikely(!e)) {
- WL_ERR("event alloc failed\n");
- return -ENOMEM;
- }
-
- e->etype = event;
- memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
-
- brcmf_lock_eq(cfg_priv);
- list_add_tail(&e->eq_list, &cfg_priv->eq_list);
- brcmf_unlock_eq(cfg_priv);
-
- return err;
-}
-
-static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
-{
- kfree(e);
-}
-
-void brcmf_cfg80211_sdio_func(void *func)
-{
- cfg80211_sdio_func = (struct sdio_func *)func;
-}
-
-static void brcmf_clear_sdio_func(void)
-{
- cfg80211_sdio_func = NULL;
-}
-
-struct sdio_func *brcmf_cfg80211_get_sdio_func(void)
-{
- return cfg80211_sdio_func;
+ if (!brcmf_enq_event(cfg_priv, event_type, e))
+ schedule_work(&cfg_priv->event_work);
}
static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
@@ -3655,9 +3499,8 @@ static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
WL_ERR("invalid type (%d)\n", iftype);
return err;
}
- infra = cpu_to_le32(infra);
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_INFRA, &infra, sizeof(infra));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
+ if (err) {
WL_ERR("WLC_SET_INFRA error (%d)\n", err);
return err;
}
@@ -3675,10 +3518,10 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
WL_TRACE("Enter\n");
/* Setup event_msgs */
- brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
- sizeof(iovbuf));
- err = brcmf_dev_ioctl(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
- if (unlikely(err)) {
+ brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
+ iovbuf, sizeof(iovbuf));
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
+ if (err) {
WL_ERR("Get event_msgs error (%d)\n", err);
goto dongle_eventmsg_out;
}
@@ -3704,10 +3547,10 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
setbit(eventmask, BRCMF_E_JOIN_START);
setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
- brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
- sizeof(iovbuf));
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
- if (unlikely(err)) {
+ brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
+ iovbuf, sizeof(iovbuf));
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
+ if (err) {
WL_ERR("Set event_msgs error (%d)\n", err);
goto dongle_eventmsg_out;
}
@@ -3721,20 +3564,23 @@ static s32
brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
{
s8 iovbuf[32];
- s32 roamtrigger[2];
- s32 roam_delta[2];
s32 err = 0;
+ __le32 roamtrigger[2];
+ __le32 roam_delta[2];
+ __le32 bcn_to_le;
+ __le32 roamvar_le;
/*
* Setup timeout if Beacons are lost and roam is
* off to report link down
*/
if (roamvar) {
- brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout,
- sizeof(bcn_timeout), iovbuf, sizeof(iovbuf));
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR,
+ bcn_to_le = cpu_to_le32(bcn_timeout);
+ brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le,
+ sizeof(bcn_to_le), iovbuf, sizeof(iovbuf));
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
iovbuf, sizeof(iovbuf));
- if (unlikely(err)) {
+ if (err) {
WL_ERR("bcn_timeout error (%d)\n", err);
goto dongle_rom_out;
}
@@ -3745,28 +3591,29 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
* to take care of roaming
*/
WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
- brcmu_mkiovar("roam_off", (char *)&roamvar,
- sizeof(roamvar), iovbuf, sizeof(iovbuf));
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
- if (unlikely(err)) {
+ roamvar_le = cpu_to_le32(roamvar);
+ brcmf_c_mkiovar("roam_off", (char *)&roamvar_le,
+ sizeof(roamvar_le), iovbuf, sizeof(iovbuf));
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
+ if (err) {
WL_ERR("roam_off error (%d)\n", err);
goto dongle_rom_out;
}
- roamtrigger[0] = WL_ROAM_TRIGGER_LEVEL;
- roamtrigger[1] = BRCM_BAND_ALL;
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_ROAM_TRIGGER,
+ roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
+ roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER,
(void *)roamtrigger, sizeof(roamtrigger));
- if (unlikely(err)) {
+ if (err) {
WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
goto dongle_rom_out;
}
- roam_delta[0] = WL_ROAM_DELTA;
- roam_delta[1] = BRCM_BAND_ALL;
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_ROAM_DELTA,
+ roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
+ roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA,
(void *)roam_delta, sizeof(roam_delta));
- if (unlikely(err)) {
+ if (err) {
WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
goto dongle_rom_out;
}
@@ -3777,12 +3624,15 @@ dongle_rom_out:
static s32
brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
- s32 scan_unassoc_time, s32 scan_passive_time)
+ s32 scan_unassoc_time, s32 scan_passive_time)
{
s32 err = 0;
+ __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time);
+ __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time);
+ __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time);
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
- &scan_assoc_time, sizeof(scan_assoc_time));
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+ &scan_assoc_tm_le, sizeof(scan_assoc_tm_le));
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO("Scan assoc time is not supported\n");
@@ -3790,8 +3640,8 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
WL_ERR("Scan assoc time error (%d)\n", err);
goto dongle_scantime_out;
}
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
- &scan_unassoc_time, sizeof(scan_unassoc_time));
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+ &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le));
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO("Scan unassoc time is not supported\n");
@@ -3800,8 +3650,8 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
goto dongle_scantime_out;
}
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
- &scan_passive_time, sizeof(scan_passive_time));
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
+ &scan_passive_tm_le, sizeof(scan_passive_tm_le));
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO("Scan passive time is not supported\n");
@@ -3814,10 +3664,40 @@ dongle_scantime_out:
return err;
}
-s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv, bool need_lock)
+static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct wiphy *wiphy;
+ s32 phy_list;
+ s8 phy;
+ s32 err = 0;
+
+ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
+ &phy_list, sizeof(phy_list));
+ if (err) {
+ WL_ERR("error (%d)\n", err);
+ return err;
+ }
+
+ phy = ((char *)&phy_list)[1];
+ WL_INFO("%c phy\n", phy);
+ if (phy == 'n' || phy == 'a') {
+ wiphy = cfg_to_wiphy(cfg_priv);
+ wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
+ }
+
+ return err;
+}
+
+static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ return wl_update_wiphybands(cfg_priv);
+}
+
+static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv)
{
struct net_device *ndev;
struct wireless_dev *wdev;
+ s32 power_mode;
s32 err = 0;
if (cfg_priv->dongle_up)
@@ -3825,31 +3705,35 @@ s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv, bool need_lock)
ndev = cfg_to_ndev(cfg_priv);
wdev = ndev->ieee80211_ptr;
- if (need_lock)
- rtnl_lock();
brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
err = brcmf_dongle_eventmsg(ndev);
- if (unlikely(err))
+ if (err)
goto default_conf_out;
+
+ power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF;
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode);
+ if (err)
+ goto default_conf_out;
+ WL_INFO("power save set to %s\n",
+ (power_mode ? "enabled" : "disabled"));
+
err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
WL_BEACON_TIMEOUT);
- if (unlikely(err))
+ if (err)
goto default_conf_out;
err = brcmf_dongle_mode(ndev, wdev->iftype);
- if (unlikely(err && err != -EINPROGRESS))
+ if (err && err != -EINPROGRESS)
goto default_conf_out;
err = brcmf_dongle_probecap(cfg_priv);
- if (unlikely(err))
+ if (err)
goto default_conf_out;
/* -EINPROGRESS: Call commit handler */
default_conf_out:
- if (need_lock)
- rtnl_unlock();
cfg_priv->dongle_up = true;
@@ -3857,30 +3741,40 @@ default_conf_out:
}
-static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
+static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct wiphy *wiphy;
- s32 phy_list;
- s8 phy;
+ char buf[10+IFNAMSIZ];
+ struct dentry *fd;
s32 err = 0;
- err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
- &phy_list, sizeof(phy_list));
- if (unlikely(err)) {
- WL_ERR("error (%d)\n", err);
- return err;
+ sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
+ cfg_priv->debugfsdir = debugfs_create_dir(buf,
+ cfg_to_wiphy(cfg_priv)->debugfsdir);
+
+ fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
+ (u16 *)&cfg_priv->profile->beacon_interval);
+ if (!fd) {
+ err = -ENOMEM;
+ goto err_out;
}
- phy = ((char *)&phy_list)[1];
- WL_INFO("%c phy\n", phy);
- if (phy == 'n' || phy == 'a') {
- wiphy = cfg_to_wiphy(cfg_priv);
- wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
+ fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
+ (u8 *)&cfg_priv->profile->dtim_period);
+ if (!fd) {
+ err = -ENOMEM;
+ goto err_out;
}
+err_out:
return err;
}
+static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ debugfs_remove_recursive(cfg_priv->debugfsdir);
+ cfg_priv->debugfsdir = NULL;
+}
+
static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
{
s32 err = 0;
@@ -3889,8 +3783,8 @@ static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
brcmf_debugfs_add_netdev_params(cfg_priv);
- err = brcmf_config_dongle(cfg_priv, false);
- if (unlikely(err))
+ err = brcmf_config_dongle(cfg_priv);
+ if (err)
return err;
brcmf_invoke_iscan(cfg_priv);
@@ -3914,9 +3808,7 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
generated due to DISASSOC call to the fw to keep
the state fw and WPA_Supplicant state consistent
*/
- rtnl_unlock();
brcmf_delay(500);
- rtnl_lock();
}
set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
@@ -3931,17 +3823,18 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
+ brcmf_link_down(cfg_priv);
brcmf_debugfs_remove_netdev(cfg_priv);
return 0;
}
-s32 brcmf_cfg80211_up(void)
+s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev)
{
struct brcmf_cfg80211_priv *cfg_priv;
s32 err = 0;
- cfg_priv = WL_PRIV_GET();
+ cfg_priv = brcmf_priv_get(cfg_dev);
mutex_lock(&cfg_priv->usr_sync);
err = __brcmf_cfg80211_up(cfg_priv);
mutex_unlock(&cfg_priv->usr_sync);
@@ -3949,12 +3842,12 @@ s32 brcmf_cfg80211_up(void)
return err;
}
-s32 brcmf_cfg80211_down(void)
+s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev)
{
struct brcmf_cfg80211_priv *cfg_priv;
s32 err = 0;
- cfg_priv = WL_PRIV_GET();
+ cfg_priv = brcmf_priv_get(cfg_dev);
mutex_lock(&cfg_priv->usr_sync);
err = __brcmf_cfg80211_down(cfg_priv);
mutex_unlock(&cfg_priv->usr_sync);
@@ -3962,78 +3855,13 @@ s32 brcmf_cfg80211_down(void)
return err;
}
-static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
-{
- return wl_update_wiphybands(cfg_priv);
-}
-
-static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item)
-{
- switch (item) {
- case WL_PROF_SEC:
- return &cfg_priv->profile->sec;
- case WL_PROF_BSSID:
- return &cfg_priv->profile->bssid;
- case WL_PROF_SSID:
- return &cfg_priv->profile->ssid;
- }
- WL_ERR("invalid item (%d)\n", item);
- return NULL;
-}
-
-static s32
-brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
- const struct brcmf_event_msg *e, void *data, s32 item)
-{
- s32 err = 0;
- struct brcmf_ssid *ssid;
-
- switch (item) {
- case WL_PROF_SSID:
- ssid = (struct brcmf_ssid *) data;
- memset(cfg_priv->profile->ssid.SSID, 0,
- sizeof(cfg_priv->profile->ssid.SSID));
- memcpy(cfg_priv->profile->ssid.SSID,
- ssid->SSID, ssid->SSID_len);
- cfg_priv->profile->ssid.SSID_len = ssid->SSID_len;
- break;
- case WL_PROF_BSSID:
- if (data)
- memcpy(cfg_priv->profile->bssid, data, ETH_ALEN);
- else
- memset(cfg_priv->profile->bssid, 0, ETH_ALEN);
- break;
- case WL_PROF_SEC:
- memcpy(&cfg_priv->profile->sec, data,
- sizeof(cfg_priv->profile->sec));
- break;
- case WL_PROF_BEACONINT:
- cfg_priv->profile->beacon_interval = *(u16 *)data;
- break;
- case WL_PROF_DTIMPERIOD:
- cfg_priv->profile->dtim_period = *(u8 *)data;
- break;
- default:
- WL_ERR("unsupported item (%d)\n", item);
- err = -EOPNOTSUPP;
- break;
- }
-
- return err;
-}
-
-static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
-{
- return cfg_priv->conf->mode == WL_MODE_IBSS;
-}
-
static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
u8 t, u8 l, u8 *v)
{
struct brcmf_cfg80211_ie *ie = &cfg_priv->ie;
s32 err = 0;
- if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
+ if (ie->offset + l + 2 > WL_TLV_INFO_MAX) {
WL_ERR("ei crosses buffer boundary\n");
return -ENOSPC;
}
@@ -4044,109 +3872,3 @@ static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
return err;
}
-
-static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct net_device *dev = NULL;
- s32 err = 0;
-
- WL_TRACE("Enter\n");
-
- if (cfg_priv->link_up) {
- dev = cfg_to_ndev(cfg_priv);
- WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
- err = brcmf_dev_ioctl(dev, BRCMF_C_DISASSOC, NULL, 0);
- if (unlikely(err))
- WL_ERR("WLC_DISASSOC failed (%d)\n", err);
- cfg_priv->link_up = false;
- }
- WL_TRACE("Exit\n");
-}
-
-static void brcmf_lock_eq(struct brcmf_cfg80211_priv *cfg_priv)
-{
- spin_lock_irq(&cfg_priv->eq_lock);
-}
-
-static void brcmf_unlock_eq(struct brcmf_cfg80211_priv *cfg_priv)
-{
- spin_unlock_irq(&cfg_priv->eq_lock);
-}
-
-static void brcmf_init_eq_lock(struct brcmf_cfg80211_priv *cfg_priv)
-{
- spin_lock_init(&cfg_priv->eq_lock);
-}
-
-static void brcmf_delay(u32 ms)
-{
- if (ms < 1000 / HZ) {
- cond_resched();
- mdelay(ms);
- } else {
- msleep(ms);
- }
-}
-
-static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data)
-{
- dev->driver_data = data;
-}
-
-static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev)
-{
- void *data = NULL;
-
- if (dev)
- data = dev->driver_data;
- return data;
-}
-
-static void brcmf_set_mpc(struct net_device *ndev, int mpc)
-{
- s32 err = 0;
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
-
- if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
- err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
- if (unlikely(err)) {
- WL_ERR("fail to set mpc\n");
- return;
- }
- WL_INFO("MPC : %d\n", mpc);
- }
-}
-
-static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
-{
- char buf[10+IFNAMSIZ];
- struct dentry *fd;
- s32 err = 0;
-
- sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
- cfg_priv->debugfsdir = debugfs_create_dir(buf,
- cfg_to_wiphy(cfg_priv)->debugfsdir);
-
- fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
- (u16 *)&cfg_priv->profile->beacon_interval);
- if (!fd) {
- err = -ENOMEM;
- goto err_out;
- }
-
- fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
- (u8 *)&cfg_priv->profile->dtim_period);
- if (!fd) {
- err = -ENOMEM;
- goto err_out;
- }
-
-err_out:
- return err;
-}
-
-static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
-{
- debugfs_remove_recursive(cfg_priv->debugfsdir);
- cfg_priv->debugfsdir = NULL;
-}
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
index f26d08793ca8..62dc46144ede 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
@@ -103,10 +103,10 @@ do { \
* report it to cfg80211 through "connect"
* event
*/
-#define WL_IOCTL_LEN_MAX 1024
+#define WL_DCMD_LEN_MAX 1024
#define WL_EXTRA_BUF_MAX 2048
#define WL_ISCAN_BUF_MAX 2048 /*
- * the buf length can be BRCMF_C_IOCTL_MAXLEN
+ * the buf length can be BRCMF_DCMD_MAXLEN
* to reduce iteration
*/
#define WL_ISCAN_TIMER_INTERVAL_MS 3000
@@ -188,7 +188,7 @@ struct brcmf_cfg80211_dev {
/* basic structure of scan request */
struct brcmf_cfg80211_scan_req {
- struct brcmf_ssid ssid;
+ struct brcmf_ssid_le ssid_le;
};
/* basic structure of information element */
@@ -199,7 +199,7 @@ struct brcmf_cfg80211_ie {
/* event queue for cfg80211 main event */
struct brcmf_cfg80211_event_q {
- struct list_head eq_list;
+ struct list_head evt_q_list;
u32 etype;
struct brcmf_event_msg emsg;
s8 edata[1];
@@ -243,16 +243,15 @@ struct brcmf_cfg80211_iscan_eloop {
/* dongle iscan controller */
struct brcmf_cfg80211_iscan_ctrl {
- struct net_device *dev;
+ struct net_device *ndev;
struct timer_list timer;
u32 timer_ms;
u32 timer_on;
s32 state;
- struct task_struct *tsk;
- struct semaphore sync;
+ struct work_struct work;
struct brcmf_cfg80211_iscan_eloop el;
void *data;
- s8 ioctl_buf[BRCMF_C_IOCTL_SMLEN];
+ s8 dcmd_buf[BRCMF_DCMD_SMLEN];
s8 scan_buf[WL_ISCAN_BUF_MAX];
};
@@ -265,15 +264,15 @@ struct brcmf_cfg80211_connect_info {
};
/* assoc ie length */
-struct brcmf_cfg80211_assoc_ielen {
- u32 req_len;
- u32 resp_len;
+struct brcmf_cfg80211_assoc_ielen_le {
+ __le32 req_len;
+ __le32 resp_len;
};
/* wpa2 pmk list */
struct brcmf_cfg80211_pmk_list {
- pmkid_list_t pmkids;
- pmkid_t foo[MAXPMKID - 1];
+ struct pmkid_list pmkids;
+ struct pmkid foo[MAXPMKID - 1];
};
/* dongle private data of cfg80211 interface */
@@ -283,8 +282,8 @@ struct brcmf_cfg80211_priv {
struct cfg80211_scan_request *scan_request; /* scan request
object */
struct brcmf_cfg80211_event_loop el; /* main event loop */
- struct list_head eq_list; /* used for event queue */
- spinlock_t eq_lock; /* for event queue synchronization */
+ struct list_head evt_q_list; /* used for event queue */
+ spinlock_t evt_q_lock; /* for event queue synchronization */
struct mutex usr_sync; /* maily for dongle up/down synchronization */
struct brcmf_scan_results *bss_list; /* bss_list holding scanned
ap information */
@@ -295,13 +294,11 @@ struct brcmf_cfg80211_priv {
cfg80211 layer */
struct brcmf_cfg80211_ie ie; /* information element object for
internal purpose */
- struct semaphore event_sync; /* for synchronization of main event
- thread */
struct brcmf_cfg80211_profile *profile; /* holding dongle profile */
struct brcmf_cfg80211_iscan_ctrl *iscan; /* iscan controller */
struct brcmf_cfg80211_connect_info conn_info; /* association info */
struct brcmf_cfg80211_pmk_list *pmk_list; /* wpa2 pmk list */
- struct task_struct *event_tsk; /* task of main event handler thread */
+ struct work_struct event_work; /* event handler work struct */
unsigned long status; /* current dongle status */
void *pub;
u32 channel; /* current channel */
@@ -315,21 +312,45 @@ struct brcmf_cfg80211_priv {
bool dongle_up; /* indicate whether dongle up or not */
bool roam_on; /* on/off switch for dongle self-roaming */
bool scan_tried; /* indicates if first scan attempted */
- u8 *ioctl_buf; /* ioctl buffer */
- u8 *extra_buf; /* maily to grab assoc information */
+ u8 *dcmd_buf; /* dcmd buffer */
+ u8 *extra_buf; /* maily to grab assoc information */
struct dentry *debugfsdir;
- u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN)));
+ u8 ci[0] __aligned(NETDEV_ALIGN);
};
-#define cfg_to_wiphy(w) (w->wdev->wiphy)
-#define wiphy_to_cfg(w) ((struct brcmf_cfg80211_priv *)(wiphy_priv(w)))
-#define cfg_to_wdev(w) (w->wdev)
-#define wdev_to_cfg(w) ((struct brcmf_cfg80211_priv *)(wdev_priv(w)))
-#define cfg_to_ndev(w) (w->wdev->netdev)
-#define ndev_to_cfg(n) (wdev_to_cfg(n->ieee80211_ptr))
+static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_priv *w)
+{
+ return w->wdev->wiphy;
+}
+
+static inline struct brcmf_cfg80211_priv *wiphy_to_cfg(struct wiphy *w)
+{
+ return (struct brcmf_cfg80211_priv *)(wiphy_priv(w));
+}
+
+static inline struct brcmf_cfg80211_priv *wdev_to_cfg(struct wireless_dev *wd)
+{
+ return (struct brcmf_cfg80211_priv *)(wdev_priv(wd));
+}
+
+static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_priv *cfg)
+{
+ return cfg->wdev->netdev;
+}
+
+static inline struct brcmf_cfg80211_priv *ndev_to_cfg(struct net_device *ndev)
+{
+ return wdev_to_cfg(ndev->ieee80211_ptr);
+}
+
#define iscan_to_cfg(i) ((struct brcmf_cfg80211_priv *)(i->data))
#define cfg_to_iscan(w) (w->iscan)
-#define cfg_to_conn(w) (&w->conn_info)
+
+static inline struct
+brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg)
+{
+ return &cfg->conn_info;
+}
static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list,
struct brcmf_bss_info *bss)
@@ -340,17 +361,15 @@ static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list,
list->bss_info;
}
-#define for_each_bss(list, bss, __i) \
- for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss))
+extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
+ struct device *busdev,
+ void *data);
+extern void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg);
-extern s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data);
-extern void brcmf_cfg80211_detach(void);
/* event handler from dongle */
extern void brcmf_cfg80211_event(struct net_device *ndev,
const struct brcmf_event_msg *e, void *data);
-extern void brcmf_cfg80211_sdio_func(void *func); /* set sdio function info */
-extern struct sdio_func *brcmf_cfg80211_get_sdio_func(void);
-extern s32 brcmf_cfg80211_up(void); /* dongle up */
-extern s32 brcmf_cfg80211_down(void); /* dongle down */
+extern s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev);
+extern s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev);
#endif /* _wl_cfg80211_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/Makefile b/drivers/staging/brcm80211/brcmsmac/Makefile
index 1ea3e0c48f3e..c2eb2d0af386 100644
--- a/drivers/staging/brcm80211/brcmsmac/Makefile
+++ b/drivers/staging/brcm80211/brcmsmac/Makefile
@@ -15,25 +15,17 @@
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-ccflags-y := \
- -DWLC_HIGH \
- -DWLC_LOW \
- -DSTA \
- -DWME \
- -DWL11N \
- -DDBAND \
- -DBCMNVRAMR \
- -Idrivers/staging/brcm80211/brcmsmac \
- -Idrivers/staging/brcm80211/brcmsmac/phy \
- -Idrivers/staging/brcm80211/include
+ccflags-y := \
+ -D__CHECK_ENDIAN__ \
+ -Idrivers/net/wireless/brcm80211/brcmsmac \
+ -Idrivers/net/wireless/brcm80211/brcmsmac/phy \
+ -Idrivers/net/wireless/brcm80211/include
BRCMSMAC_OFILES := \
mac80211_if.o \
ucode_loader.o \
- alloc.o \
ampdu.o \
antsel.o \
- bmac.o \
channel.o \
main.o \
phy_shim.o \
@@ -50,7 +42,8 @@ BRCMSMAC_OFILES := \
otp.o \
srom.o \
dma.o \
- nicpci.o
+ nicpci.o \
+ brcms_trace_events.o
MODULEPFX := brcmsmac
diff --git a/drivers/staging/brcm80211/brcmsmac/aiutils.c b/drivers/staging/brcm80211/brcmsmac/aiutils.c
index a25901e9981b..025fa0eb6f47 100644
--- a/drivers/staging/brcm80211/brcmsmac/aiutils.c
+++ b/drivers/staging/brcm80211/brcmsmac/aiutils.c
@@ -12,7 +12,10 @@
* 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
*/
+
#include <linux/delay.h>
#include <linux/pci.h>
@@ -20,6 +23,7 @@
#include <chipcommon.h>
#include <brcmu_utils.h>
#include <brcm_hw_ids.h>
+#include <soc.h>
#include "types.h"
#include "pub.h"
#include "pmu.h"
@@ -28,48 +32,68 @@
#include "aiutils.h"
/* slow_clk_ctl */
-#define SCC_SS_MASK 0x00000007 /* slow clock source mask */
-#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */
-#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */
-#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */
-#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */
-#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled,
- * 0: LPO is enabled
- */
-#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock,
- * 0: power logic control
- */
-#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors
- * PLL clock disable requests from core
- */
-#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't
- * disable crystal when appropriate
- */
-#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */
-#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */
+ /* 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 */
-#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */
-#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */
-#define SYCC_FP 0x00000004 /* ForcePLLOn */
-#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */
-#define SYCC_HR 0x00000010 /* Force HT */
-#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */
+ /* 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
-#define CST4329_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */
-#define CST4329_SPROM_SEL 1 /* OTP is powered up, SPROM is present */
-#define CST4329_OTP_SEL 2 /* OTP is powered up, no SPROM */
-#define CST4329_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */
+ /* 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
-#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */
-#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */
+ /* 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
@@ -78,29 +102,44 @@
#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_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 */
-#define CCTRL4331_BT_COEXIST (1<<0) /* 0 disable */
-#define CCTRL4331_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */
-#define CCTRL4331_EXT_LNA (1<<2) /* 0 disable */
-#define CCTRL4331_SPROM_GPIO13_15 (1<<3) /* sprom/gpio13-15 mux */
-#define CCTRL4331_EXTPA_EN (1<<4) /* 0 ext pa disable, 1 ext pa enabled */
-#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) /* set drive out GPIO_CLK on sprom_cs pin */
-#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) /* use sprom_cs pin as PCIE mdio interface */
-#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) /* aband extpa will be at gpio2/5 and sprom_dout */
-#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) /* override core control on pipe_AuxClkEnable */
-#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */
-#define CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */
-#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */
-#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */
-#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */
+ /* 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 */
-#define CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */
+ /* crystal frequency 20/40Mhz */
+#define CST4331_XTAL_FREQ 0x00000001
#define CST4331_SPROM_PRESENT 0x00000002
#define CST4331_OTP_PRESENT 0x00000004
#define CST4331_LDO_RF 0x00000008
@@ -110,19 +149,26 @@
#define CST4319_SPI_CPULESSUSB 0x00000001
#define CST4319_SPI_CLK_POL 0x00000002
#define CST4319_SPI_CLK_PH 0x00000008
-#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 /* gpio [7:6], SDIO CIS selection */
+ /* gpio [7:6], SDIO CIS selection */
+#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0
#define CST4319_SPROM_OTP_SEL_SHIFT 6
-#define CST4319_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */
-#define CST4319_SPROM_SEL 0x00000040 /* use SPROM, OTP is powered up */
-#define CST4319_OTP_SEL 0x00000080 /* use OTP, OTP is powered up */
-#define CST4319_OTP_PWRDN 0x000000c0 /* use SPROM, OTP is powered down */
-#define CST4319_SDIO_USB_MODE 0x00000100 /* gpio [8], sdio/usb mode */
+ /* 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
-#define CST4319_PALDO_EXTPNP 0x00010000 /* PALDO is configured with external PNP */
+ /* 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
@@ -153,11 +199,8 @@
#define CST4313_SPROM_OTP_SEL_SHIFT 0
/* 4313 Chip specific ChipControl register bits */
-#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */
-
-#define BCM47162_DMP() ((sih->chip == BCM47162_CHIP_ID) && \
- (sih->chiprev == 0) && \
- (sii->coreid[sii->curidx] == MIPS74K_CORE_ID))
+ /* 12 mA drive strengh for later 4313 */
+#define CCTRL_4313_12MA_LED_DRIVE 0x00000007
/* Manufacturer Ids */
#define MFGID_ARM 0x43b
@@ -227,9 +270,12 @@
#define SD_SG32 0x00000008
#define SD_SZ_ALIGN 0x00000fff
-#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */
-#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal power-up */
-#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL power-down */
+/* 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 */
@@ -239,6 +285,82 @@
/* 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)
+
+/* Newer chips can access PCI/PCIE and CC core without requiring to change
+ * PCI BAR0 WIN
+ */
+#define SI_FAST(si) (((si)->pub.buscoretype == PCIE_CORE_ID) || \
+ (((si)->pub.buscoretype == PCI_CORE_ID) && \
+ (si)->pub.buscorerev >= 13))
+
+#define CCREGS_FAST(si) (((char __iomem *)((si)->curmap) + \
+ PCI_16KB0_CCREGS_OFFSET))
+
+#define IS_SIM(chippkg) \
+ ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
+
+/*
+ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts
+ * before after core switching to avoid invalid register accesss inside ISR.
+ */
+#define INTR_OFF(si, intr_val) \
+ if ((si)->intrsoff_fn && \
+ (si)->coreid[(si)->curidx] == (si)->dev_coreid) \
+ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg)
+
+#define INTR_RESTORE(si, intr_val) \
+ if ((si)->intrsrestore_fn && \
+ (si)->coreid[(si)->curidx] == (si)->dev_coreid) \
+ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val)
+
+#define PCI(si) ((si)->pub.buscoretype == PCI_CORE_ID)
+#define PCIE(si) ((si)->pub.buscoretype == PCIE_CORE_ID)
+
+#define PCI_FORCEHT(si) (PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID))
+
+#ifdef BCMDBG
+#define SI_MSG(args) printk args
+#else
+#define SI_MSG(args)
+#endif /* BCMDBG */
+
+#define GOODCOREADDR(x, b) \
+ (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
+ IS_ALIGNED((x), SI_CORE_SIZE))
+
+#define PCIEREGS(si) ((__iomem char *)((si)->curmap) + \
+ PCI_16KB0_PCIREGS_OFFSET)
+
struct aidmp {
u32 oobselina30; /* 0x000 */
u32 oobselina74; /* 0x004 */
@@ -360,7 +482,7 @@ struct aidmp {
/* EROM parsing */
static u32
-get_erom_ent(struct si_pub *sih, u32 **eromptr, u32 mask, u32 match)
+get_erom_ent(struct si_pub *sih, u32 __iomem **eromptr, u32 mask, u32 match)
{
u32 ent;
uint inv = 0, nom = 0;
@@ -386,16 +508,11 @@ get_erom_ent(struct si_pub *sih, u32 **eromptr, u32 mask, u32 match)
nom++;
}
- SI_VMSG(("%s: Returning ent 0x%08x\n", __func__, ent));
- if (inv + nom) {
- SI_VMSG((" after %d invalid and %d non-matching entries\n",
- inv, nom));
- }
return ent;
}
static u32
-get_asd(struct si_pub *sih, u32 **eromptr, uint sp, uint ad, uint st,
+get_asd(struct si_pub *sih, u32 __iomem **eromptr, uint sp, uint ad, uint st,
u32 *addrl, u32 *addrh, u32 *sizel, u32 *sizeh)
{
u32 asd, sz, szd;
@@ -423,9 +540,6 @@ get_asd(struct si_pub *sih, u32 **eromptr, uint sp, uint ad, uint st,
} else
*sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT);
- SI_VMSG((" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n",
- sp, ad, st, *sizeh, *sizel, *addrh, *addrl));
-
return asd;
}
@@ -434,45 +548,28 @@ static void ai_hwfixup(struct si_info *sii)
}
/* parse the enumeration rom to identify all cores */
-void ai_scan(struct si_pub *sih, void *regs)
+static void ai_scan(struct si_pub *sih, struct chipcregs __iomem *cc)
{
- struct si_info *sii = SI_INFO(sih);
- chipcregs_t *cc = (chipcregs_t *) regs;
- u32 erombase, *eromptr, *eromlim;
+ struct si_info *sii = (struct si_info *)sih;
- erombase = R_REG(&cc->eromptr);
-
- switch (sih->bustype) {
- case SI_BUS:
- eromptr = (u32 *) REG_MAP(erombase, SI_CORE_SIZE);
- break;
+ u32 erombase;
+ u32 __iomem *eromptr, *eromlim;
+ void __iomem *regs = cc;
- case PCI_BUS:
- /* Set wrappers address */
- sii->curwrap = (void *)((unsigned long)regs + SI_CORE_SIZE);
-
- /* Now point the window at the erom */
- pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase);
- eromptr = regs;
- break;
+ erombase = R_REG(&cc->eromptr);
- case SPI_BUS:
- case SDIO_BUS:
- eromptr = (u32 *)(unsigned long)erombase;
- break;
+ /* Set wrappers address */
+ sii->curwrap = (void *)((unsigned long)cc + SI_CORE_SIZE);
- default:
- SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n",
- sih->bustype));
- return;
- }
+ /* Now point the window at the erom */
+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase);
+ eromptr = regs;
eromlim = eromptr + (ER_REMAPCONTROL / sizeof(u32));
- SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n", regs, erombase, eromptr, eromlim));
while (eromptr < eromlim) {
u32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp;
u32 mpd, asd, addrl, addrh, sizel, sizeh;
- u32 *base;
+ u32 __iomem *base;
uint i, j, idx;
bool br;
@@ -481,8 +578,7 @@ void ai_scan(struct si_pub *sih, void *regs)
/* Grok a component */
cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI);
if (cia == (ER_END | ER_VALID)) {
- SI_VMSG(("Found END of erom after %d cores\n",
- sii->numcores));
+ /* Found END of erom */
ai_hwfixup(sii);
return;
}
@@ -490,7 +586,7 @@ void ai_scan(struct si_pub *sih, void *regs)
cib = get_erom_ent(sih, &eromptr, 0, 0);
if ((cib & ER_TAG) != ER_CI) {
- SI_ERROR(("CIA not followed by CIB\n"));
+ /* CIA not followed by CIB */
goto error;
}
@@ -502,8 +598,6 @@ void ai_scan(struct si_pub *sih, void *regs)
nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
- SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, " "nsw = %d, nmp = %d & nsp = %d\n", mfg, cid, crev, base, nmw, nsw, nmp, nsp));
-
if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0))
continue;
if ((nmw + nsw == 0)) {
@@ -511,9 +605,8 @@ void ai_scan(struct si_pub *sih, void *regs)
if (cid == OOB_ROUTER_CORE_ID) {
asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE,
&addrl, &addrh, &sizel, &sizeh);
- if (asd != 0) {
+ if (asd != 0)
sii->oob_router = addrl;
- }
}
continue;
}
@@ -527,12 +620,9 @@ void ai_scan(struct si_pub *sih, void *regs)
for (i = 0; i < nmp; i++) {
mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
if ((mpd & ER_TAG) != ER_MP) {
- SI_ERROR(("Not enough MP entries for component 0x%x\n", cid));
+ /* Not enough MP entries for component */
goto error;
}
- SI_VMSG((" Master port %d, mp: %d id: %d\n", i,
- (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT,
- (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT));
}
/* First Slave Address Descriptor should be port 0:
@@ -550,7 +640,7 @@ void ai_scan(struct si_pub *sih, void *regs)
br = true;
else if ((addrh != 0) || (sizeh != 0)
|| (sizel != SI_CORE_SIZE)) {
- SI_ERROR(("First Slave ASD for core 0x%04x malformed " "(0x%08x)\n", cid, asd));
+ /* First Slave ASD for core malformed */
goto error;
}
}
@@ -578,8 +668,7 @@ void ai_scan(struct si_pub *sih, void *regs)
&addrl, &addrh, &sizel, &sizeh);
} while (asd != 0);
if (j == 0) {
- SI_ERROR((" SP %d has no address descriptors\n",
- i));
+ /* SP has no address descriptors */
goto error;
}
}
@@ -590,11 +679,11 @@ void ai_scan(struct si_pub *sih, void *regs)
get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl,
&addrh, &sizel, &sizeh);
if (asd == 0) {
- SI_ERROR(("Missing descriptor for MW %d\n", i));
+ /* Missing descriptor for MW */
goto error;
}
if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
- SI_ERROR(("Master wrapper %d is not 4KB\n", i));
+ /* Master wrapper %d is not 4KB */
goto error;
}
if (i == 0)
@@ -608,11 +697,11 @@ void ai_scan(struct si_pub *sih, void *regs)
get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP,
&addrl, &addrh, &sizel, &sizeh);
if (asd == 0) {
- SI_ERROR(("Missing descriptor for SW %d\n", i));
+ /* Missing descriptor for SW */
goto error;
}
if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
- SI_ERROR(("Slave wrapper %d is not 4KB\n", i));
+ /* Slave wrapper is not 4KB */
goto error;
}
if ((nmw == 0) && (i == 0))
@@ -627,62 +716,35 @@ void ai_scan(struct si_pub *sih, void *regs)
sii->numcores++;
}
- SI_ERROR(("Reached end of erom without finding END"));
-
error:
+ /* Reached end of erom without finding END */
sii->numcores = 0;
return;
}
-/* This function changes the logical "focus" to the indicated core.
- * Return the current core's virtual address.
+/*
+ * This function changes the logical "focus" to the indicated core.
+ * Return the current core's virtual address. Since each core starts with the
+ * same set of registers (BIST, clock control, etc), the returned address
+ * contains the first register of this 'common' register block (not to be
+ * confused with 'common core').
*/
-void *ai_setcoreidx(struct si_pub *sih, uint coreidx)
+void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx)
{
- struct si_info *sii = SI_INFO(sih);
+ struct si_info *sii = (struct si_info *)sih;
u32 addr = sii->coresba[coreidx];
u32 wrap = sii->wrapba[coreidx];
- void *regs;
if (coreidx >= sii->numcores)
return NULL;
- switch (sih->bustype) {
- case SI_BUS:
- /* map new one */
- if (!sii->regs[coreidx]) {
- sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE);
- }
- sii->curmap = regs = sii->regs[coreidx];
- if (!sii->wrappers[coreidx]) {
- sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE);
- }
- sii->curwrap = sii->wrappers[coreidx];
- break;
-
- case PCI_BUS:
- /* point bar0 window */
- pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr);
- regs = sii->curmap;
- /* point bar0 2nd 4KB window */
- pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap);
- break;
-
- case SPI_BUS:
- case SDIO_BUS:
- sii->curmap = regs = (void *)(unsigned long)addr;
- sii->curwrap = (void *)(unsigned long)wrap;
- break;
-
- default:
- regs = NULL;
- break;
- }
-
- sii->curmap = regs;
+ /* point bar0 window */
+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr);
+ /* point bar0 2nd 4KB window */
+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap);
sii->curidx = coreidx;
- return regs;
+ return sii->curmap;
}
/* Return the number of address spaces in current core */
@@ -697,7 +759,7 @@ u32 ai_addrspace(struct si_pub *sih, uint asidx)
struct si_info *sii;
uint cidx;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
cidx = sii->curidx;
if (asidx == 0)
@@ -705,7 +767,7 @@ u32 ai_addrspace(struct si_pub *sih, uint asidx)
else if (asidx == 1)
return sii->coresba2[cidx];
else {
- SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", __func__, asidx));
+ /* Need to parse the erom again to find addr space */
return 0;
}
}
@@ -716,7 +778,7 @@ u32 ai_addrspacesize(struct si_pub *sih, uint asidx)
struct si_info *sii;
uint cidx;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
cidx = sii->curidx;
if (asidx == 0)
@@ -724,7 +786,7 @@ u32 ai_addrspacesize(struct si_pub *sih, uint asidx)
else if (asidx == 1)
return sii->coresba2_size[cidx];
else {
- SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", __func__, asidx));
+ /* Need to parse the erom again to find addr */
return 0;
}
}
@@ -734,11 +796,7 @@ uint ai_flag(struct si_pub *sih)
struct si_info *sii;
struct aidmp *ai;
- sii = SI_INFO(sih);
- if (BCM47162_DMP()) {
- SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __func__));
- return sii->curidx;
- }
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
return R_REG(&ai->oobselouta30) & 0x1f;
@@ -753,7 +811,7 @@ uint ai_corevendor(struct si_pub *sih)
struct si_info *sii;
u32 cia;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
cia = sii->cia[sii->curidx];
return (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
}
@@ -763,7 +821,7 @@ uint ai_corerev(struct si_pub *sih)
struct si_info *sii;
u32 cib;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
cib = sii->cib[sii->curidx];
return (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
}
@@ -773,7 +831,7 @@ bool ai_iscoreup(struct si_pub *sih)
struct si_info *sii;
struct aidmp *ai;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
return (((R_REG(&ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) ==
@@ -787,13 +845,7 @@ void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val)
struct aidmp *ai;
u32 w;
- sii = SI_INFO(sih);
-
- if (BCM47162_DMP()) {
- SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
- __func__));
- return;
- }
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
@@ -809,13 +861,7 @@ u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val)
struct aidmp *ai;
u32 w;
- sii = SI_INFO(sih);
- if (BCM47162_DMP()) {
- SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
- __func__));
- return 0;
- }
-
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
if (mask || val) {
@@ -826,18 +872,35 @@ u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val)
return R_REG(&ai->ioctrl);
}
+/* return true if PCIE capability exists in the pci config space */
+static bool ai_ispcie(struct si_info *sii)
+{
+ u8 cap_ptr;
+
+ cap_ptr =
+ pcicore_find_pci_capability(sii->pbus, PCI_CAP_ID_EXP, NULL,
+ NULL);
+ if (!cap_ptr)
+ return false;
+
+ return true;
+}
+
+static bool ai_buscore_prep(struct si_info *sii)
+{
+ /* kludge to enable the clock on the 4306 which lacks a slowclock */
+ if (!ai_ispcie(sii))
+ ai_clkctl_xtal(&sii->pub, XTAL | PLL, ON);
+ return true;
+}
+
u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val)
{
struct si_info *sii;
struct aidmp *ai;
u32 w;
- sii = SI_INFO(sih);
- if (BCM47162_DMP()) {
- SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0", __func__));
- return 0;
- }
-
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
if (mask || val) {
@@ -848,74 +911,13 @@ u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val)
return R_REG(&ai->iostatus);
}
-/* *************** from siutils.c ************** */
-/* local prototypes */
-static struct si_info *ai_doattach(struct si_info *sii, void *regs,
- uint bustype, void *sdh, char **vars,
- uint *varsz);
-static bool ai_buscore_prep(struct si_info *sii, uint bustype);
-static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
- u32 savewin, uint *origidx, void *regs);
-static void ai_nvram_process(struct si_info *sii, char *pvars);
-
-/* dev path concatenation util */
-static char *ai_devpathvar(struct si_pub *sih, char *var, int len,
- const char *name);
-static bool _ai_clkctl_cc(struct si_info *sii, uint mode);
-static bool ai_ispcie(struct si_info *sii);
-
-/* global variable to indicate reservation/release of gpio's */
-static u32 ai_gpioreservation;
-
-/*
- * Allocate a si handle.
- * devid - pci device id (used to determine chip#)
- * osh - opaque OS handle
- * regs - virtual address of initial core registers
- * bustype - pci/sb/sdio/etc
- * vars - pointer to a pointer area for "environment" variables
- * varsz - pointer to int to return the size of the vars
- */
-struct si_pub *ai_attach(void *regs, uint bustype,
- void *sdh, char **vars, uint *varsz)
-{
- struct si_info *sii;
-
- /* alloc struct si_info */
- sii = kmalloc(sizeof(struct si_info), GFP_ATOMIC);
- if (sii == NULL) {
- SI_ERROR(("si_attach: malloc failed!\n"));
- return NULL;
- }
-
- if (ai_doattach(sii, regs, bustype, sdh, vars, varsz) ==
- NULL) {
- kfree(sii);
- return NULL;
- }
- sii->vars = vars ? *vars : NULL;
- sii->varsz = varsz ? *varsz : 0;
-
- return (struct si_pub *) sii;
-}
-
-/* global kernel resource */
-static struct si_info ksii;
-
-static bool ai_buscore_prep(struct si_info *sii, uint bustype)
-{
- /* kludge to enable the clock on the 4306 which lacks a slowclock */
- if (bustype == PCI_BUS && !ai_ispcie(sii))
- ai_clkctl_xtal(&sii->pub, XTAL | PLL, ON);
- return true;
-}
-
-static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
- u32 savewin, uint *origidx, void *regs)
+static bool
+ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx)
{
bool pci, pcie;
uint i;
uint pciidx, pcieidx, pcirev, pcierev;
+ struct chipcregs __iomem *cc;
cc = ai_setcoreidx(&sii->pub, SI_CC_IDX);
@@ -955,25 +957,19 @@ static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
cid = ai_coreid(&sii->pub);
crev = ai_corerev(&sii->pub);
- /* Display cores found */
- SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
- i, cid, crev, sii->coresba[i], sii->regs[i]));
-
- if (bustype == PCI_BUS) {
- if (cid == PCI_CORE_ID) {
- pciidx = i;
- pcirev = crev;
- pci = true;
- } else if (cid == PCIE_CORE_ID) {
- pcieidx = i;
- pcierev = crev;
- pcie = true;
- }
+ if (cid == PCI_CORE_ID) {
+ pciidx = i;
+ pcirev = crev;
+ pci = true;
+ } else if (cid == PCIE_CORE_ID) {
+ pcieidx = i;
+ pcierev = crev;
+ pcie = true;
}
/* find the core idx before entering this func. */
if ((savewin && (savewin == sii->coresba[i])) ||
- (regs == sii->regs[i]))
+ (cc == sii->regs[i]))
*origidx = i;
}
@@ -993,25 +989,19 @@ static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
sii->pub.buscoreidx = pcieidx;
}
- SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx,
- sii->pub.buscoretype, sii->pub.buscorerev));
-
/* fixup necessary chip/core configurations */
- if (sii->pub.bustype == PCI_BUS) {
- if (SI_FAST(sii)) {
- if (!sii->pch) {
- sii->pch = (void *)pcicore_init(
- &sii->pub, sii->pbus,
- (void *)PCIEREGS(sii));
- if (sii->pch == NULL)
- return false;
- }
- }
- if (ai_pci_fixcfg(&sii->pub)) {
- SI_ERROR(("si_doattach: si_pci_fixcfg failed\n"));
- return false;
+ if (SI_FAST(sii)) {
+ if (!sii->pch) {
+ sii->pch = pcicore_init(&sii->pub, sii->pbus,
+ (__iomem void *)PCIEREGS(sii));
+ if (sii->pch == NULL)
+ return false;
}
}
+ if (ai_pci_fixcfg(&sii->pub)) {
+ /* si_doattach: si_pci_fixcfg failed */
+ return false;
+ }
/* return to the original core */
ai_setcoreidx(&sii->pub, *origidx);
@@ -1019,63 +1009,27 @@ static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
return true;
}
-static __used void ai_nvram_process(struct si_info *sii, char *pvars)
+/*
+ * get boardtype and boardrev
+ */
+static __used void ai_nvram_process(struct si_info *sii)
{
uint w = 0;
- /* get boardtype and boardrev */
- switch (sii->pub.bustype) {
- case PCI_BUS:
- /* do a pci config read to get subsystem id and subvendor id */
- pci_read_config_dword(sii->pbus, PCI_SUBSYSTEM_VENDOR_ID, &w);
- /* Let nvram variables override subsystem Vend/ID */
- sii->pub.boardvendor = (u16)ai_getdevpathintvar(&sii->pub,
- "boardvendor");
- if (sii->pub.boardvendor == 0)
- sii->pub.boardvendor = w & 0xffff;
- else
- SI_ERROR(("Overriding boardvendor: 0x%x instead of "
- "0x%x\n", sii->pub.boardvendor, w & 0xffff));
- sii->pub.boardtype = (u16)ai_getdevpathintvar(&sii->pub,
- "boardtype");
- if (sii->pub.boardtype == 0)
- sii->pub.boardtype = (w >> 16) & 0xffff;
- else
- SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n"
- , sii->pub.boardtype, (w >> 16) & 0xffff));
- break;
-
- sii->pub.boardvendor = getintvar(pvars, "manfid");
- sii->pub.boardtype = getintvar(pvars, "prodid");
- break;
-
- case SI_BUS:
- case JTAG_BUS:
- sii->pub.boardvendor = PCI_VENDOR_ID_BROADCOM;
- sii->pub.boardtype = getintvar(pvars, "prodid");
- if (pvars == NULL || (sii->pub.boardtype == 0)) {
- sii->pub.boardtype = getintvar(NULL, "boardtype");
- if (sii->pub.boardtype == 0)
- sii->pub.boardtype = 0xffff;
- }
- break;
- }
-
- if (sii->pub.boardtype == 0) {
- SI_ERROR(("si_doattach: unknown board type\n"));
- }
+ /* do a pci config read to get subsystem id and subvendor id */
+ pci_read_config_dword(sii->pbus, PCI_SUBSYSTEM_VENDOR_ID, &w);
- sii->pub.boardflags = getintvar(pvars, "boardflags");
+ sii->pub.boardvendor = w & 0xffff;
+ sii->pub.boardtype = (w >> 16) & 0xffff;
+ sii->pub.boardflags = getintvar(&sii->pub, BRCMS_SROM_BOARDFLAGS);
}
static struct si_info *ai_doattach(struct si_info *sii,
- void *regs, uint bustype, void *pbus,
- char **vars, uint *varsz)
+ void __iomem *regs, struct pci_dev *pbus)
{
struct si_pub *sih = &sii->pub;
u32 w, savewin;
- chipcregs_t *cc;
- char *pvars = NULL;
+ struct chipcregs __iomem *cc;
uint socitype;
uint origidx;
@@ -1088,37 +1042,18 @@ static struct si_info *ai_doattach(struct si_info *sii,
sii->curmap = regs;
sii->pbus = pbus;
- /* check to see if we are a si core mimic'ing a pci core */
- if (bustype == PCI_BUS) {
- pci_read_config_dword(sii->pbus, PCI_SPROM_CONTROL, &w);
- if (w == 0xffffffff) {
- SI_ERROR(("%s: incoming bus is PCI but it's a lie, "
- " switching to SI devid:0x%x\n",
- __func__, devid));
- bustype = SI_BUS;
- }
- }
-
/* find Chipcommon address */
- if (bustype == PCI_BUS) {
- pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin);
- if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
- savewin = SI_ENUM_BASE;
- pci_write_config_dword(sii->pbus, PCI_BAR0_WIN,
- SI_ENUM_BASE);
- cc = (chipcregs_t *) regs;
- } else {
- cc = (chipcregs_t *) REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
- }
+ pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin);
+ if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
+ savewin = SI_ENUM_BASE;
- sih->bustype = bustype;
+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN,
+ SI_ENUM_BASE);
+ cc = (struct chipcregs __iomem *) regs;
/* bus/core/clk setup for register access */
- if (!ai_buscore_prep(sii, bustype)) {
- SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
- bustype));
+ if (!ai_buscore_prep(sii))
return NULL;
- }
/*
* ChipID recognition.
@@ -1134,67 +1069,59 @@ static struct si_info *ai_doattach(struct si_info *sii,
sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
- sih->issim = IS_SIM(sih->chippkg);
+ sih->issim = false;
/* scan for cores */
if (socitype == SOCI_AI) {
SI_MSG(("Found chip type AI (0x%08x)\n", w));
/* pass chipc address instead of original core base */
- ai_scan(&sii->pub, (void *)cc);
+ ai_scan(&sii->pub, cc);
} else {
- SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
+ /* Found chip of unknown type */
return NULL;
}
/* no cores found, bail out */
- if (sii->numcores == 0) {
- SI_ERROR(("si_doattach: could not find any cores\n"));
+ if (sii->numcores == 0)
return NULL;
- }
+
/* bus/core/clk setup */
origidx = SI_CC_IDX;
- if (!ai_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
- SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
+ if (!ai_buscore_setup(sii, savewin, &origidx))
goto exit;
- }
/* Init nvram from sprom/otp if they exist */
- if (srom_var_init
- (&sii->pub, bustype, regs, vars, varsz)) {
- SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
+ if (srom_var_init(&sii->pub, cc))
goto exit;
- }
- pvars = vars ? *vars : NULL;
- ai_nvram_process(sii, pvars);
+
+ ai_nvram_process(sii);
/* === NVRAM, clock is ready === */
- cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0);
+ cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0);
W_REG(&cc->gpiopullup, 0);
W_REG(&cc->gpiopulldown, 0);
ai_setcoreidx(sih, origidx);
/* PMU specific initializations */
- if (PMUCTL_ENAB(sih)) {
+ if (sih->cccaps & CC_CAP_PMU) {
u32 xtalfreq;
si_pmu_init(sih);
si_pmu_chip_init(sih);
- xtalfreq = getintvar(pvars, "xtalfreq");
- /* If xtalfreq var not available, try to measure it */
- if (xtalfreq == 0)
- xtalfreq = si_pmu_measure_alpclk(sih);
+
+ xtalfreq = si_pmu_measure_alpclk(sih);
si_pmu_pll_init(sih, xtalfreq);
si_pmu_res_init(sih);
si_pmu_swreg_init(sih);
}
/* setup the GPIO based LED powersave register */
- w = getintvar(pvars, "leddc");
+ w = getintvar(sih, BRCMS_SROM_LEDDC);
if (w == 0)
w = DEFAULT_GPIOTIMERVAL;
- ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, gpiotimerval), ~0, w);
+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, gpiotimerval),
+ ~0, w);
- if (PCIE(sii)) {
- pcicore_attach(sii->pch, pvars, SI_DOATTACH);
- }
+ if (PCIE(sii))
+ pcicore_attach(sii->pch, SI_DOATTACH);
if (sih->chip == BCM43224_CHIP_ID) {
/*
@@ -1204,7 +1131,7 @@ static struct si_info *ai_doattach(struct si_info *sii,
if (sih->chiprev == 0) {
SI_MSG(("Applying 43224A0 WARs\n"));
ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol),
+ offsetof(struct chipcregs, chipcontrol),
CCTRL43224_GPIO_TOGGLE,
CCTRL43224_GPIO_TOGGLE);
si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
@@ -1228,45 +1155,58 @@ static struct si_info *ai_doattach(struct si_info *sii,
}
return sii;
+
exit:
- if (sih->bustype == PCI_BUS) {
- if (sii->pch)
- pcicore_deinit(sii->pch);
- sii->pch = NULL;
- }
+ if (sii->pch)
+ pcicore_deinit(sii->pch);
+ sii->pch = NULL;
return NULL;
}
+/*
+ * Allocate a si handle.
+ * devid - pci device id (used to determine chip#)
+ * osh - opaque OS handle
+ * regs - virtual address of initial core registers
+ */
+struct si_pub *
+ai_attach(void __iomem *regs, struct pci_dev *sdh)
+{
+ struct si_info *sii;
+
+ /* alloc struct si_info */
+ sii = kmalloc(sizeof(struct si_info), GFP_ATOMIC);
+ if (sii == NULL)
+ return NULL;
+
+ if (ai_doattach(sii, regs, sdh) == 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;
- uint idx;
struct si_pub *si_local = NULL;
memcpy(&si_local, &sih, sizeof(struct si_pub **));
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
if (sii == NULL)
return;
- if (sih->bustype == SI_BUS)
- for (idx = 0; idx < SI_MAXCORES; idx++)
- if (sii->regs[idx]) {
- iounmap(sii->regs[idx]);
- sii->regs[idx] = NULL;
- }
-
- if (sih->bustype == PCI_BUS) {
- if (sii->pch)
- pcicore_deinit(sii->pch);
- sii->pch = NULL;
- }
+ if (sii->pch)
+ pcicore_deinit(sii->pch);
+ sii->pch = NULL;
- if (sii != &ksii)
- kfree(sii);
+ srom_free_vars(sih);
+ kfree(sii);
}
/* register driver interrupt disabling and restoring callback functions */
@@ -1277,11 +1217,11 @@ ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn,
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
sii->intr_arg = intr_arg;
- sii->intrsoff_fn = (si_intrsoff_t) intrsoff_fn;
- sii->intrsrestore_fn = (si_intrsrestore_t) intrsrestore_fn;
- sii->intrsenabled_fn = (si_intrsenabled_t) intrsenabled_fn;
+ sii->intrsoff_fn = (u32 (*)(void *)) intrsoff_fn;
+ sii->intrsrestore_fn = (void (*) (void *, u32)) intrsrestore_fn;
+ sii->intrsenabled_fn = (bool (*)(void *)) intrsenabled_fn;
/* save current core id. when this function called, the current core
* must be the core which provides driver functions(il, et, wl, etc.)
*/
@@ -1292,7 +1232,7 @@ void ai_deregister_intr_callback(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
sii->intrsoff_fn = NULL;
}
@@ -1300,7 +1240,7 @@ uint ai_coreid(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
return sii->coreid[sii->curidx];
}
@@ -1308,7 +1248,7 @@ uint ai_coreidx(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
return sii->curidx;
}
@@ -1324,7 +1264,7 @@ uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit)
uint found;
uint i;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
found = 0;
@@ -1344,25 +1284,25 @@ uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit)
* Moreover, callers should keep interrupts off during switching
* out of and back to d11 core.
*/
-void *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit)
+void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit)
{
uint idx;
idx = ai_findcoreidx(sih, coreid, coreunit);
- if (!GOODIDX(idx))
+ if (idx >= SI_MAXCORES)
return NULL;
return ai_setcoreidx(sih, idx);
}
/* Turn off interrupt as required by ai_setcore, before switch core */
-void *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
- uint *intr_val)
+void __iomem *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
+ uint *intr_val)
{
- void *cc;
+ void __iomem *cc;
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
if (SI_FAST(sii)) {
/* Overloading the origidx variable to remember the coreid,
@@ -1371,9 +1311,9 @@ void *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
*/
*origidx = coreid;
if (coreid == CC_CORE_ID)
- return (void *)CCREGS_FAST(sii);
+ return CCREGS_FAST(sii);
else if (coreid == sih->buscoretype)
- return (void *)PCIEREGS(sii);
+ return PCIEREGS(sii);
}
INTR_OFF(sii, *intr_val);
*origidx = sii->curidx;
@@ -1386,7 +1326,7 @@ void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val)
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
if (SI_FAST(sii)
&& ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
return;
@@ -1397,7 +1337,7 @@ void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val)
void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val)
{
- struct si_info *sii = SI_INFO(sih);
+ struct si_info *sii = (struct si_info *)sih;
u32 *w = (u32 *) sii->curwrap;
W_REG(w + (offset / 4), val);
return;
@@ -1417,54 +1357,40 @@ uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
uint val)
{
uint origidx = 0;
- u32 *r = NULL;
+ u32 __iomem *r = NULL;
uint w;
uint intr_val = 0;
bool fast = false;
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
if (coreidx >= SI_MAXCORES)
return 0;
- if (sih->bustype == SI_BUS) {
- /* If internal bus, we can always get at everything */
+ /*
+ * If pci/pcie, we can get at pci/pcie regs
+ * and on newer cores to chipc
+ */
+ if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
+ /* Chipc registers are mapped at 12KB */
fast = true;
- /* map if does not exist */
- if (!sii->regs[coreidx]) {
- sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx],
- SI_CORE_SIZE);
- }
- r = (u32 *) ((unsigned char *) sii->regs[coreidx] + regoff);
- } else if (sih->bustype == PCI_BUS) {
+ r = (u32 __iomem *)((__iomem char *)sii->curmap +
+ PCI_16KB0_CCREGS_OFFSET + regoff);
+ } else if (sii->pub.buscoreidx == coreidx) {
/*
- * If pci/pcie, we can get at pci/pcie regs
- * and on newer cores to chipc
+ * pci registers are at either in the last 2KB of
+ * an 8KB window or, in pcie and pci rev 13 at 8KB
*/
- if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
- /* Chipc registers are mapped at 12KB */
-
- fast = true;
- r = (u32 *) ((char *)sii->curmap +
- PCI_16KB0_CCREGS_OFFSET + regoff);
- } else if (sii->pub.buscoreidx == coreidx) {
- /*
- * pci registers are at either in the last 2KB of
- * an 8KB window or, in pcie and pci rev 13 at 8KB
- */
- fast = true;
- if (SI_FAST(sii))
- r = (u32 *) ((char *)sii->curmap +
- PCI_16KB0_PCIREGS_OFFSET +
- regoff);
- else
- r = (u32 *) ((char *)sii->curmap +
- ((regoff >= SBCONFIGOFF) ?
- PCI_BAR0_PCISBR_OFFSET :
- PCI_BAR0_PCIREGS_OFFSET) +
- regoff);
- }
+ fast = true;
+ if (SI_FAST(sii))
+ r = (u32 __iomem *)((__iomem char *)sii->curmap +
+ PCI_16KB0_PCIREGS_OFFSET + regoff);
+ else
+ r = (u32 __iomem *)((__iomem char *)sii->curmap +
+ ((regoff >= SBCONFIGOFF) ?
+ PCI_BAR0_PCISBR_OFFSET :
+ PCI_BAR0_PCIREGS_OFFSET) + regoff);
}
if (!fast) {
@@ -1474,8 +1400,8 @@ uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
origidx = ai_coreidx(&sii->pub);
/* switch core */
- r = (u32 *) ((unsigned char *) ai_setcoreidx(&sii->pub, coreidx)
- + regoff);
+ r = (u32 __iomem *) ((unsigned char __iomem *)
+ ai_setcoreidx(&sii->pub, coreidx) + regoff);
}
/* mask and set */
@@ -1504,7 +1430,7 @@ void ai_core_disable(struct si_pub *sih, u32 bits)
u32 dummy;
struct aidmp *ai;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
@@ -1531,7 +1457,7 @@ void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits)
struct aidmp *ai;
u32 dummy;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
/*
@@ -1556,19 +1482,18 @@ void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits)
/* return the slow clock source - LPO, XTAL, or PCI */
static uint ai_slowclk_src(struct si_info *sii)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
u32 val;
if (sii->pub.ccrev < 6) {
- if (sii->pub.bustype == PCI_BUS) {
- pci_read_config_dword(sii->pbus, PCI_GPIO_OUT,
- &val);
- if (val & PCI_CFG_GPIO_SCS)
- return SCC_SS_PCI;
- }
+ pci_read_config_dword(sii->pbus, PCI_GPIO_OUT,
+ &val);
+ if (val & PCI_CFG_GPIO_SCS)
+ return SCC_SS_PCI;
return SCC_SS_XTAL;
} else if (sii->pub.ccrev < 10) {
- cc = (chipcregs_t *) ai_setcoreidx(&sii->pub, sii->curidx);
+ cc = (struct chipcregs __iomem *)
+ ai_setcoreidx(&sii->pub, sii->curidx);
return R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK;
} else /* Insta-clock */
return SCC_SS_XTAL;
@@ -1578,7 +1503,8 @@ static uint ai_slowclk_src(struct si_info *sii)
* 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_info *sii, bool max_freq, chipcregs_t *cc)
+static uint ai_slowclk_freq(struct si_info *sii, bool max_freq,
+ struct chipcregs __iomem *cc)
{
u32 slowclk;
uint div;
@@ -1612,9 +1538,9 @@ static uint ai_slowclk_freq(struct si_info *sii, bool max_freq, chipcregs_t *cc)
return 0;
}
-static void ai_clkctl_setdelay(struct si_info *sii, void *chipcregs)
+static void
+ai_clkctl_setdelay(struct si_info *sii, struct chipcregs __iomem *cc)
{
- chipcregs_t *cc = (chipcregs_t *) chipcregs;
uint slowmaxfreq, pll_delay, slowclk;
uint pll_on_delay, fref_sel_delay;
@@ -1646,21 +1572,22 @@ void ai_clkctl_init(struct si_pub *sih)
{
struct si_info *sii;
uint origidx = 0;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
bool fast;
- if (!CCCTL_ENAB(sih))
+ if (!(sih->cccaps & CC_CAP_PWR_CTL))
return;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
fast = SI_FAST(sii);
if (!fast) {
origidx = sii->curidx;
- cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0);
+ cc = (struct chipcregs __iomem *)
+ ai_setcore(sih, CC_CORE_ID, 0);
if (cc == NULL)
return;
} else {
- cc = (chipcregs_t *) CCREGS_FAST(sii);
+ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii);
if (cc == NULL)
return;
}
@@ -1670,7 +1597,7 @@ void ai_clkctl_init(struct si_pub *sih)
SET_REG(&cc->system_clk_ctl, SYCC_CD_MASK,
(ILP_DIV_1MHZ << SYCC_CD_SHIFT));
- ai_clkctl_setdelay(sii, (void *)cc);
+ ai_clkctl_setdelay(sii, cc);
if (!fast)
ai_setcoreidx(sih, origidx);
@@ -1684,21 +1611,21 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
{
struct si_info *sii;
uint origidx = 0;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint slowminfreq;
u16 fpdelay;
uint intr_val = 0;
bool fast;
- sii = SI_INFO(sih);
- if (PMUCTL_ENAB(sih)) {
+ sii = (struct si_info *)sih;
+ if (sih->cccaps & CC_CAP_PMU) {
INTR_OFF(sii, intr_val);
fpdelay = si_pmu_fast_pwrup_delay(sih);
INTR_RESTORE(sii, intr_val);
return fpdelay;
}
- if (!CCCTL_ENAB(sih))
+ if (!(sih->cccaps & CC_CAP_PWR_CTL))
return 0;
fast = SI_FAST(sii);
@@ -1706,11 +1633,12 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
if (!fast) {
origidx = sii->curidx;
INTR_OFF(sii, intr_val);
- cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0);
+ cc = (struct chipcregs __iomem *)
+ ai_setcore(sih, CC_CORE_ID, 0);
if (cc == NULL)
goto done;
} else {
- cc = (chipcregs_t *) CCREGS_FAST(sii);
+ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii);
if (cc == NULL)
goto done;
}
@@ -1733,99 +1661,68 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on)
struct si_info *sii;
u32 in, out, outen;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
- switch (sih->bustype) {
-
- case PCI_BUS:
- /* pcie core doesn't have any mapping to control the xtal pu */
- if (PCIE(sii))
- return -1;
+ /* pcie core doesn't have any mapping to control the xtal pu */
+ if (PCIE(sii))
+ return -1;
- pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in);
- pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out);
- pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen);
+ pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in);
+ pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out);
+ pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen);
- /*
- * Avoid glitching the clock if GPRS is already using it.
- * We can't actually read the state of the PLLPD so we infer it
- * by the value of XTAL_PU which *is* readable via gpioin.
- */
- if (on && (in & PCI_CFG_GPIO_XTAL))
- return 0;
+ /*
+ * Avoid glitching the clock if GPRS is already using it.
+ * We can't actually read the state of the PLLPD so we infer it
+ * by the value of XTAL_PU which *is* readable via gpioin.
+ */
+ if (on && (in & PCI_CFG_GPIO_XTAL))
+ return 0;
- if (what & XTAL)
- outen |= PCI_CFG_GPIO_XTAL;
- if (what & PLL)
- outen |= PCI_CFG_GPIO_PLL;
-
- if (on) {
- /* turn primary xtal on */
- if (what & XTAL) {
- out |= PCI_CFG_GPIO_XTAL;
- if (what & PLL)
- out |= PCI_CFG_GPIO_PLL;
- pci_write_config_dword(sii->pbus,
- PCI_GPIO_OUT, out);
- pci_write_config_dword(sii->pbus,
- PCI_GPIO_OUTEN, outen);
- udelay(XTAL_ON_DELAY);
- }
+ if (what & XTAL)
+ outen |= PCI_CFG_GPIO_XTAL;
+ if (what & PLL)
+ outen |= PCI_CFG_GPIO_PLL;
- /* turn pll on */
- if (what & PLL) {
- out &= ~PCI_CFG_GPIO_PLL;
- pci_write_config_dword(sii->pbus,
- PCI_GPIO_OUT, out);
- mdelay(2);
- }
- } else {
- if (what & XTAL)
- out &= ~PCI_CFG_GPIO_XTAL;
+ if (on) {
+ /* turn primary xtal on */
+ if (what & XTAL) {
+ out |= PCI_CFG_GPIO_XTAL;
if (what & PLL)
out |= PCI_CFG_GPIO_PLL;
pci_write_config_dword(sii->pbus,
PCI_GPIO_OUT, out);
pci_write_config_dword(sii->pbus,
PCI_GPIO_OUTEN, outen);
+ udelay(XTAL_ON_DELAY);
}
- default:
- return -1;
+ /* turn pll on */
+ if (what & PLL) {
+ out &= ~PCI_CFG_GPIO_PLL;
+ pci_write_config_dword(sii->pbus,
+ PCI_GPIO_OUT, out);
+ mdelay(2);
+ }
+ } else {
+ if (what & XTAL)
+ out &= ~PCI_CFG_GPIO_XTAL;
+ if (what & PLL)
+ out |= PCI_CFG_GPIO_PLL;
+ pci_write_config_dword(sii->pbus,
+ PCI_GPIO_OUT, out);
+ pci_write_config_dword(sii->pbus,
+ PCI_GPIO_OUTEN, outen);
}
return 0;
}
-/*
- * 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, uint mode)
-{
- struct si_info *sii;
-
- sii = SI_INFO(sih);
-
- /* chipcommon cores prior to rev6 don't support dynamic clock control */
- if (sih->ccrev < 6)
- return false;
-
- if (PCI_FORCEHT(sii))
- return mode == CLK_FAST;
-
- return _ai_clkctl_cc(sii, mode);
-}
-
/* clk control mechanism through chipcommon, no policy checking */
static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
{
uint origidx = 0;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
u32 scc;
uint intr_val = 0;
bool fast = SI_FAST(sii);
@@ -1837,20 +1734,15 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
if (!fast) {
INTR_OFF(sii, intr_val);
origidx = sii->curidx;
-
- if ((sii->pub.bustype == SI_BUS) &&
- ai_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
- (ai_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
- goto done;
-
- cc = (chipcregs_t *) ai_setcore(&sii->pub, CC_CORE_ID, 0);
+ cc = (struct chipcregs __iomem *)
+ ai_setcore(&sii->pub, CC_CORE_ID, 0);
} else {
- cc = (chipcregs_t *) CCREGS_FAST(sii);
+ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii);
if (cc == NULL)
goto done;
}
- if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
+ if (!(sii->pub.cccaps & CC_CAP_PWR_CTL) && (sii->pub.ccrev < 20))
goto done;
switch (mode) {
@@ -1870,7 +1762,7 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
}
/* wait for the PLL */
- if (PMUCTL_ENAB(&sii->pub)) {
+ if (sii->pub.cccaps & CC_CAP_PMU) {
u32 htavail = CCS_HTAVAIL;
SPINWAIT(((R_REG(&cc->clk_ctl_st) & htavail)
== 0), PMU_MAX_TRANSITION_DLY);
@@ -1913,7 +1805,31 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
return mode == CLK_FAST;
}
-/* Build device path. Support SI, PCI, and JTAG for now. */
+/*
+ * 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, uint mode)
+{
+ struct si_info *sii;
+
+ sii = (struct si_info *)sih;
+
+ /* chipcommon cores prior to rev6 don't support dynamic clock control */
+ if (sih->ccrev < 6)
+ return false;
+
+ if (PCI_FORCEHT(sii))
+ return mode == CLK_FAST;
+
+ return _ai_clkctl_cc(sii, mode);
+}
+
+/* Build device path */
int ai_devpath(struct si_pub *sih, char *path, int size)
{
int slen;
@@ -1921,22 +1837,10 @@ int ai_devpath(struct si_pub *sih, char *path, int size)
if (!path || size <= 0)
return -1;
- switch (sih->bustype) {
- case SI_BUS:
- case JTAG_BUS:
- slen = snprintf(path, (size_t) size, "sb/%u/", ai_coreidx(sih));
- break;
- case PCI_BUS:
- slen = snprintf(path, (size_t) size, "pci/%u/%u/",
- ((struct pci_dev *)((SI_INFO(sih))->pbus))->bus->number,
- PCI_SLOT(
- ((struct pci_dev *)((SI_INFO(sih))->pbus))->devfn));
- break;
-
- default:
- slen = -1;
- break;
- }
+ slen = snprintf(path, (size_t) size, "pci/%u/%u/",
+ ((struct si_info *)sih)->pbus->bus->number,
+ PCI_SLOT(((struct pci_dev *)
+ (((struct si_info *)(sih))->pbus))->devfn));
if (slen < 0 || slen >= size) {
path[0] = '\0';
@@ -1946,95 +1850,11 @@ int ai_devpath(struct si_pub *sih, char *path, int size)
return 0;
}
-/* Get a variable, but only if it has a devpath prefix */
-char *ai_getdevpathvar(struct si_pub *sih, const char *name)
-{
- char varname[SI_DEVPATH_BUFSZ + 32];
-
- ai_devpathvar(sih, varname, sizeof(varname), name);
-
- return getvar(NULL, varname);
-}
-
-/* Get a variable, but only if it has a devpath prefix */
-int ai_getdevpathintvar(struct si_pub *sih, const char *name)
-{
-#if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
- return getintvar(NULL, name);
-#else
- char varname[SI_DEVPATH_BUFSZ + 32];
-
- ai_devpathvar(sih, varname, sizeof(varname), name);
-
- return getintvar(NULL, varname);
-#endif
-}
-
-char *ai_getnvramflvar(struct si_pub *sih, const char *name)
-{
- return getvar(NULL, name);
-}
-
-/* Concatenate the dev path with a varname into the given 'var' buffer
- * and return the 'var' pointer. Nothing is done to the arguments if
- * len == 0 or var is NULL, var is still returned. On overflow, the
- * first char will be set to '\0'.
- */
-static char *ai_devpathvar(struct si_pub *sih, char *var, int len,
- const char *name)
-{
- uint path_len;
-
- if (!var || len <= 0)
- return var;
-
- if (ai_devpath(sih, var, len) == 0) {
- path_len = strlen(var);
-
- if (strlen(name) + 1 > (uint) (len - path_len))
- var[0] = '\0';
- else
- strncpy(var + path_len, name, len - path_len - 1);
- }
-
- return var;
-}
-
-/* return true if PCIE capability exists in the pci config space */
-static bool ai_ispcie(struct si_info *sii)
-{
- u8 cap_ptr;
-
- if (sii->pub.bustype != PCI_BUS)
- return false;
-
- cap_ptr =
- pcicore_find_pci_capability(sii->pbus, PCI_CAP_ID_EXP, NULL,
- NULL);
- if (!cap_ptr)
- return false;
-
- return true;
-}
-
-bool ai_pci_war16165(struct si_pub *sih)
-{
- struct si_info *sii;
-
- sii = SI_INFO(sih);
-
- return PCI(sii) && (sih->buscorerev <= 10);
-}
-
void ai_pci_up(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
-
- /* if not pci bus, we're done */
- if (sih->bustype != PCI_BUS)
- return;
+ sii = (struct si_info *)sih;
if (PCI_FORCEHT(sii))
_ai_clkctl_cc(sii, CLK_FAST);
@@ -2049,7 +1869,7 @@ void ai_pci_sleep(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
pcicore_sleep(sii->pch);
}
@@ -2059,11 +1879,7 @@ void ai_pci_down(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
-
- /* if not pci bus, we're done */
- if (sih->bustype != PCI_BUS)
- return;
+ sii = (struct si_info *)sih;
/* release FORCEHT since chip is going to "down" state */
if (PCI_FORCEHT(sii))
@@ -2079,14 +1895,11 @@ void ai_pci_down(struct si_pub *sih)
void ai_pci_setup(struct si_pub *sih, uint coremask)
{
struct si_info *sii;
- void *regs = NULL;
+ struct sbpciregs __iomem *regs = NULL;
u32 siflag = 0, w;
uint idx = 0;
- sii = SI_INFO(sih);
-
- if (sii->pub.bustype != PCI_BUS)
- return;
+ sii = (struct si_info *)sih;
if (PCI(sii)) {
/* get current core index */
@@ -2128,9 +1941,8 @@ void ai_pci_setup(struct si_pub *sih, uint coremask)
int ai_pci_fixcfg(struct si_pub *sih)
{
uint origidx;
- void *regs = NULL;
-
- struct si_info *sii = SI_INFO(sih);
+ void __iomem *regs = NULL;
+ struct si_info *sii = (struct si_info *)sih;
/* Fixup PI in SROM shadow area to enable the correct PCI core access */
/* save the current index */
@@ -2138,7 +1950,11 @@ int ai_pci_fixcfg(struct si_pub *sih)
/* check 'pi' is correct and fix it if not */
regs = ai_setcore(&sii->pub, sii->pub.buscoretype, 0);
- pcicore_fixcfg(sii->pch, regs);
+ if (sii->pub.buscoretype == PCIE_CORE_ID)
+ pcicore_fixcfg_pcie(sii->pch,
+ (struct sbpcieregs __iomem *)regs);
+ else if (sii->pub.buscoretype == PCI_CORE_ID)
+ pcicore_fixcfg_pci(sii->pch, (struct sbpciregs __iomem *)regs);
/* restore the original index */
ai_setcoreidx(&sii->pub, origidx);
@@ -2152,47 +1968,34 @@ u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority)
{
uint regoff;
- regoff = 0;
-
- /* gpios could be shared on router platforms
- * ignore reservation if it's high priority (e.g., test apps)
- */
- if ((priority != GPIO_HI_PRIORITY) &&
- (sih->bustype == SI_BUS) && (val || mask)) {
- mask = priority ? (ai_gpioreservation & mask) :
- ((ai_gpioreservation | mask) & ~(ai_gpioreservation));
- val &= mask;
- }
-
- regoff = offsetof(chipcregs_t, gpiocontrol);
+ regoff = offsetof(struct chipcregs, gpiocontrol);
return ai_corereg(sih, SI_CC_IDX, regoff, mask, val);
}
void ai_chipcontrl_epa4331(struct si_pub *sih, bool on)
{
struct si_info *sii;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
u32 val;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
origidx = ai_coreidx(sih);
- cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0);
+ cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0);
val = R_REG(&cc->chipcontrol);
if (on) {
- if (sih->chippkg == 9 || sih->chippkg == 0xb) {
+ if (sih->chippkg == 9 || sih->chippkg == 0xb)
/* Ext PA Controls for 4331 12x9 Package */
W_REG(&cc->chipcontrol, val |
- (CCTRL4331_EXTPA_EN |
- CCTRL4331_EXTPA_ON_GPIO2_5));
- } else {
+ CCTRL4331_EXTPA_EN |
+ CCTRL4331_EXTPA_ON_GPIO2_5);
+ else
/* Ext PA Controls for 4331 12x12 Package */
W_REG(&cc->chipcontrol,
- val | (CCTRL4331_EXTPA_EN));
- }
+ val | CCTRL4331_EXTPA_EN);
} else {
val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
W_REG(&cc->chipcontrol, val);
@@ -2205,13 +2008,13 @@ void ai_chipcontrl_epa4331(struct si_pub *sih, bool on)
void ai_epa_4313war(struct si_pub *sih)
{
struct si_info *sii;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
origidx = ai_coreidx(sih);
- cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0);
+ cc = ai_setcore(sih, CC_CORE_ID, 0);
/* EPA Fix */
W_REG(&cc->gpiocontrol,
@@ -2226,15 +2029,12 @@ bool ai_deviceremoved(struct si_pub *sih)
u32 w;
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
+
+ pci_read_config_dword(sii->pbus, PCI_VENDOR_ID, &w);
+ if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM)
+ return true;
- switch (sih->bustype) {
- case PCI_BUS:
- pci_read_config_dword(sii->pbus, PCI_VENDOR_ID, &w);
- if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM)
- return true;
- break;
- }
return false;
}
@@ -2243,13 +2043,13 @@ bool ai_is_sprom_available(struct si_pub *sih)
if (sih->ccrev >= 31) {
struct si_info *sii;
uint origidx;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
u32 sromctrl;
if ((sih->cccaps & CC_CAP_SROM) == 0)
return false;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
origidx = sii->curidx;
cc = ai_setcoreidx(sih, SI_CC_IDX);
sromctrl = R_REG(&cc->sromcontrol);
diff --git a/drivers/staging/brcm80211/brcmsmac/aiutils.h b/drivers/staging/brcm80211/brcmsmac/aiutils.h
index e245c278bebc..106a7424a7cd 100644
--- a/drivers/staging/brcm80211/brcmsmac/aiutils.h
+++ b/drivers/staging/brcm80211/brcmsmac/aiutils.h
@@ -23,26 +23,6 @@
* SOC Interconnect Address Map.
* All regions may not exist on all chips.
*/
-/* Physical SDRAM */
-#define SI_SDRAM_BASE 0x00000000
-/* Host Mode sb2pcitranslation0 (64 MB) */
-#define SI_PCI_MEM 0x08000000
-#define SI_PCI_MEM_SZ (64 * 1024 * 1024)
-/* Host Mode sb2pcitranslation1 (64 MB) */
-#define SI_PCI_CFG 0x0c000000
-/* Byteswapped Physical SDRAM */
-#define SI_SDRAM_SWAPPED 0x10000000
-/* Region 2 for sdram (512 MB) */
-#define SI_SDRAM_R2 0x80000000
-
-#ifdef SI_ENUM_BASE_VARIABLE
-#define SI_ENUM_BASE (sii->pub.si_enum_base)
-#else
-#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */
-#endif /* SI_ENUM_BASE_VARIABLE */
-
-/* Wrapper space base */
-#define SI_WRAP_BASE 0x18100000
/* each core gets 4Kbytes for registers */
#define SI_CORE_SIZE 0x1000
/*
@@ -52,39 +32,9 @@
*/
#define SI_MAXCORES 16
-/* On-chip RAM on chips that also have DDR */
-#define SI_FASTRAM 0x19000000
-#define SI_FASTRAM_SWAPPED 0x19800000
-
-/* Flash Region 2 (region 1 shadowed here) */
-#define SI_FLASH2 0x1c000000
-/* Size of Flash Region 2 */
-#define SI_FLASH2_SZ 0x02000000
-/* ARM Cortex-M3 ROM */
-#define SI_ARMCM3_ROM 0x1e000000
-/* MIPS Flash Region 1 */
-#define SI_FLASH1 0x1fc00000
-/* MIPS Size of Flash Region 1 */
-#define SI_FLASH1_SZ 0x00400000
-/* ARM7TDMI-S ROM */
-#define SI_ARM7S_ROM 0x20000000
-/* ARM Cortex-M3 SRAM Region 2 */
-#define SI_ARMCM3_SRAM2 0x60000000
-/* ARM7TDMI-S SRAM Region 2 */
-#define SI_ARM7S_SRAM2 0x80000000
-/* ARM Flash Region 1 */
-#define SI_ARM_FLASH1 0xffff0000
-/* ARM Size of Flash Region 1 */
-#define SI_ARM_FLASH1_SZ 0x00010000
-
-/* Client Mode sb2pcitranslation2 (1 GB) */
-#define SI_PCI_DMA 0x40000000
-/* Client Mode sb2pcitranslation2 (1 GB) */
-#define SI_PCI_DMA2 0x80000000
/* Client Mode sb2pcitranslation2 size in bytes */
#define SI_PCI_DMA_SZ 0x40000000
-/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), low 32 bits */
-#define SI_PCIE_DMA_L32 0x00000000
+
/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
#define SI_PCIE_DMA_H32 0x80000000
@@ -203,18 +153,6 @@
/* Minumum amount of flash we support */
#define FLASH_MIN 0x00020000 /* Minimum flash size */
-/* A boot/binary may have an embedded block that describes its size */
-#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */
-#define BISZ_MAGIC 0x4249535a /* Marked with value: 'BISZ' */
-#define BISZ_MAGIC_IDX 0 /* Word 0: magic */
-#define BISZ_TXTST_IDX 1 /* 1: text start */
-#define BISZ_TXTEND_IDX 2 /* 2: text end */
-#define BISZ_DATAST_IDX 3 /* 3: data start */
-#define BISZ_DATAEND_IDX 4 /* 4: data end */
-#define BISZ_BSSST_IDX 5 /* 5: bss start */
-#define BISZ_BSSEND_IDX 6 /* 6: bss end */
-#define BISZ_SIZE 7 /* descriptor size in 32-bit integers */
-
#define CC_SROM_OTP 0x800 /* SROM/OTP address space */
/* gpiotimerval */
@@ -224,93 +162,15 @@
#define CLKD_OTP 0x000f0000
#define CLKD_OTP_SHIFT 16
-/* 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
-
-/* 4330 chip-specific ChipStatus register bits */
-#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */
-#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */
-#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) /* SDIO */
-#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) /* gSPI */
-#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) /* USB packet-oriented */
-#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) /* USB Direct Access */
-#define CST4330_OTP_PRESENT 0x00000010
-#define CST4330_LPO_AUTODET_EN 0x00000020
-#define CST4330_ARMREMAP_0 0x00000040
-#define CST4330_SPROM_PRESENT 0x00000080 /* takes priority over OTP if both set */
-#define CST4330_ILPDIV_EN 0x00000100
-#define CST4330_LPO_SEL 0x00000200
-#define CST4330_RES_INIT_MODE_SHIFT 10
-#define CST4330_RES_INIT_MODE_MASK 0x00000c00
-#define CST4330_CBUCK_MODE_SHIFT 12
-#define CST4330_CBUCK_MODE_MASK 0x00003000
-#define CST4330_CBUCK_POWER_OK 0x00004000
-#define CST4330_BB_PLL_LOCKED 0x00008000
-
/* Package IDs */
-#define BCM4329_289PIN_PKG_ID 0 /* 4329 289-pin package id */
-#define BCM4329_182PIN_PKG_ID 1 /* 4329N 182-pin package id */
#define BCM4717_PKG_ID 9 /* 4717 package id */
#define BCM4718_PKG_ID 10 /* 4718 package id */
-#define HDLSIM_PKG_ID 14 /* HDL simulator package id */
-#define HWSIM_PKG_ID 15 /* Hardware simulator package id */
#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */
/* these are router chips */
#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */
#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */
#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */
-#define BCM5356_CHIP_ID 0x5356 /* 5356 chipcommon chipid */
-#define BCM5357_CHIP_ID 0x5357 /* 5357 chipcommon chipid */
-
-
-#define SI_INFO(sih) ((struct si_info *)sih)
-
-#define GOODCOREADDR(x, b) \
- (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
- IS_ALIGNED((x), SI_CORE_SIZE))
-#define GOODREGS(regs) \
- ((regs) != NULL && IS_ALIGNED((unsigned long)(regs), SI_CORE_SIZE))
-#define BADCOREADDR 0
-#define GOODIDX(idx) (((uint)idx) < SI_MAXCORES)
-#define NOREV -1 /* Invalid rev */
-
-/* Newer chips can access PCI/PCIE and CC core without requiring to change
- * PCI BAR0 WIN
- */
-#define SI_FAST(si) (((si)->pub.buscoretype == PCIE_CORE_ID) || \
- (((si)->pub.buscoretype == PCI_CORE_ID) && \
- (si)->pub.buscorerev >= 13))
-
-#define PCIEREGS(si) (((char *)((si)->curmap) + PCI_16KB0_PCIREGS_OFFSET))
-#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET))
-
-/*
- * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts
- * before after core switching to avoid invalid register accesss inside ISR.
- */
-#define INTR_OFF(si, intr_val) \
- if ((si)->intrsoff_fn && \
- (si)->coreid[(si)->curidx] == (si)->dev_coreid) \
- intr_val = (*(si)->intrsoff_fn)((si)->intr_arg)
-#define INTR_RESTORE(si, intr_val) \
- if ((si)->intrsrestore_fn && \
- (si)->coreid[(si)->curidx] == (si)->dev_coreid) \
- (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val)
/* dynamic clock control defines */
#define LPOMINFREQ 25000 /* low power oscillator min */
@@ -323,60 +183,6 @@
#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
-#define PCI(si) (((si)->pub.bustype == PCI_BUS) && \
- ((si)->pub.buscoretype == PCI_CORE_ID))
-#define PCIE(si) (((si)->pub.bustype == PCI_BUS) && \
- ((si)->pub.buscoretype == PCIE_CORE_ID))
-#define PCI_FORCEHT(si) \
- (PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID))
-
-/* GPIO Based LED powersave defines */
-#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */
-#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */
-
-#ifndef DEFAULT_GPIOTIMERVAL
-#define DEFAULT_GPIOTIMERVAL \
- ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
-#endif
-
-/*
- * Data structure to export all chip specific common variables
- * public (read-only) portion of aiutils handle returned by si_attach()
- */
-struct si_pub {
- uint bustype; /* SI_BUS, PCI_BUS */
- uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */
- uint buscorerev; /* buscore rev */
- uint buscoreidx; /* buscore index */
- int ccrev; /* chip common core rev */
- u32 cccaps; /* chip common capabilities */
- u32 cccaps_ext; /* chip common capabilities extension */
- int pmurev; /* pmu core rev */
- u32 pmucaps; /* pmu capabilities */
- uint boardtype; /* board type */
- uint boardvendor; /* board vendor */
- uint boardflags; /* board flags */
- uint boardflags2; /* board flags2 */
- uint chip; /* chip number */
- uint chiprev; /* chip revision */
- uint chippkg; /* chip package option */
- u32 chipst; /* chip status */
- bool issim; /* chip is in simulation or emulation */
- uint socirev; /* SOC interconnect rev */
- bool pci_pr32414;
-
-};
-
-/*
- * 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
- */
-
-#define BADIDX (SI_MAXCORES + 1)
-
/* clkctl xtal what flags */
#define XTAL 0x1 /* primary crystal oscillator (2050) */
#define PLL 0x2 /* main chip pll */
@@ -409,49 +215,39 @@ struct si_pub {
#define SI_PCIDOWN 2
#define SI_PCIUP 3
-/* PMU clock/power control */
-#if defined(BCMPMUCTL)
-#define PMUCTL_ENAB(sih) (BCMPMUCTL)
-#else
-#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU)
-#endif
-
-/* chipcommon clock/power control (exclusive with PMU's) */
-#if defined(BCMPMUCTL) && BCMPMUCTL
-#define CCCTL_ENAB(sih) (0)
-#define CCPLL_ENAB(sih) (0)
-#else
-#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL)
-#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK)
-#endif
-
-typedef void (*gpio_handler_t) (u32 stat, void *arg);
-
-/* External PA enable mask */
-#define GPIO_CTRL_EPA_EN_MASK 0x40
-
-#define SI_ERROR(args)
-
-#ifdef BCMDBG
-#define SI_MSG(args) printk args
-#else
-#define SI_MSG(args)
-#endif /* BCMDBG */
-
-/* Define SI_VMSG to printf for verbose debugging, but don't check it in */
-#define SI_VMSG(args)
+/*
+ * Data structure to export all chip specific common variables
+ * public (read-only) portion of aiutils handle returned by si_attach()
+ */
+struct si_pub {
+ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */
+ uint buscorerev; /* buscore rev */
+ uint buscoreidx; /* buscore index */
+ int ccrev; /* chip common core rev */
+ u32 cccaps; /* chip common capabilities */
+ u32 cccaps_ext; /* chip common capabilities extension */
+ int pmurev; /* pmu core rev */
+ u32 pmucaps; /* pmu capabilities */
+ uint boardtype; /* board type */
+ uint boardvendor; /* board vendor */
+ uint boardflags; /* board flags */
+ uint boardflags2; /* board flags2 */
+ uint chip; /* chip number */
+ uint chiprev; /* chip revision */
+ uint chippkg; /* chip package option */
+ u32 chipst; /* chip status */
+ bool issim; /* chip is in simulation or emulation */
+ uint socirev; /* SOC interconnect rev */
+ bool pci_pr32414;
-#define IS_SIM(chippkg) \
- ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
+};
-typedef u32(*si_intrsoff_t) (void *intr_arg);
-typedef void (*si_intrsrestore_t) (void *intr_arg, u32 arg);
-typedef bool(*si_intrsenabled_t) (void *intr_arg);
+struct pci_dev;
struct gpioh_item {
void *arg;
bool level;
- gpio_handler_t handler;
+ void (*handler) (u32 stat, void *arg);
u32 event;
struct gpioh_item *next;
};
@@ -459,20 +255,21 @@ struct gpioh_item {
/* misc si info needed by some of the routines */
struct si_info {
struct si_pub pub; /* back plane public state (must be first) */
- void *pbus; /* handle to bus (pci/sdio/..) */
+ struct pci_dev *pbus; /* handle to pci bus */
uint dev_coreid; /* the core provides driver functions */
void *intr_arg; /* interrupt callback function arg */
- si_intrsoff_t intrsoff_fn; /* turns chip interrupts off */
- si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */
- si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */
+ u32 (*intrsoff_fn) (void *intr_arg); /* turns chip interrupts off */
+ /* restore chip interrupts */
+ void (*intrsrestore_fn) (void *intr_arg, u32 arg);
+ /* check if interrupts are enabled */
+ bool (*intrsenabled_fn) (void *intr_arg);
- void *pch; /* PCI/E core handle */
+ struct pcicore_info *pch; /* PCI/E core handle */
- char *vars;
- uint varsz;
+ struct list_head var_list; /* list of srom variables */
- void *curmap; /* current regs va */
- void *regs[SI_MAXCORES]; /* other regs va */
+ void __iomem *curmap; /* current regs va */
+ void __iomem *regs[SI_MAXCORES]; /* other regs va */
uint curidx; /* current core index */
uint numcores; /* # discovered cores */
@@ -492,16 +289,22 @@ struct si_info {
u32 oob_router; /* oob router registers for axi */
};
-/* AMBA Interconnect exported externs */
-extern void ai_scan(struct si_pub *sih, void *regs);
+/*
+ * 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 */
extern uint ai_flag(struct si_pub *sih);
extern void ai_setint(struct si_pub *sih, int siflag);
extern uint ai_coreidx(struct si_pub *sih);
extern uint ai_corevendor(struct si_pub *sih);
extern uint ai_corerev(struct si_pub *sih);
extern bool ai_iscoreup(struct si_pub *sih);
-extern void *ai_setcoreidx(struct si_pub *sih, uint coreidx);
extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
extern void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val);
extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
@@ -515,12 +318,8 @@ extern u32 ai_addrspacesize(struct si_pub *sih, uint asidx);
extern void ai_write_wrap_reg(struct si_pub *sih, u32 offset, u32 val);
/* === exported functions === */
-extern struct si_pub *ai_attach(void *regs, uint bustype,
- void *sdh, char **vars, uint *varsz);
-
+extern struct si_pub *ai_attach(void __iomem *regs, struct pci_dev *sdh);
extern void ai_detach(struct si_pub *sih);
-extern bool ai_pci_war16165(struct si_pub *sih);
-
extern uint ai_coreid(struct si_pub *sih);
extern uint ai_corerev(struct si_pub *sih);
extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
@@ -530,10 +329,10 @@ extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
extern bool ai_iscoreup(struct si_pub *sih);
extern uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit);
-extern void *ai_setcoreidx(struct si_pub *sih, uint coreidx);
-extern void *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit);
-extern void *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
- uint *intr_val);
+extern void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx);
+extern void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit);
+extern void __iomem *ai_switch_core(struct si_pub *sih, uint coreid,
+ uint *origidx, uint *intr_val);
extern void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val);
extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits);
extern void ai_core_disable(struct si_pub *sih, u32 bits);
@@ -566,9 +365,6 @@ extern bool ai_is_sprom_available(struct si_pub *sih);
* Return 0 on success, nonzero otherwise.
*/
extern int ai_devpath(struct si_pub *sih, char *path, int size);
-/* Read variable with prepending the devpath to the name */
-extern char *ai_getdevpathvar(struct si_pub *sih, const char *name);
-extern int ai_getdevpathintvar(struct si_pub *sih, const char *name);
extern void ai_pci_sleep(struct si_pub *sih);
extern void ai_pci_down(struct si_pub *sih);
@@ -579,6 +375,4 @@ extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on);
/* Enable Ex-PA for 4313 */
extern void ai_epa_4313war(struct si_pub *sih);
-char *ai_getnvramflvar(struct si_pub *sih, const char *name);
-
#endif /* _BRCM_AIUTILS_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/alloc.c b/drivers/staging/brcm80211/brcmsmac/alloc.c
deleted file mode 100644
index 7f8dd7b396bf..000000000000
--- a/drivers/staging/brcm80211/brcmsmac/alloc.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * 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_utils.h>
-#include "types.h"
-#include "pub.h"
-#include "main.h"
-#include "alloc.h"
-
-static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit);
-static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg);
-static struct brcms_pub *brcms_c_pub_malloc(uint unit,
- uint *err, uint devid);
-static void brcms_c_pub_mfree(struct brcms_pub *pub);
-static void brcms_c_tunables_init(struct brcms_tunables *tunables, uint devid);
-
-static void brcms_c_tunables_init(struct brcms_tunables *tunables, uint devid)
-{
- tunables->ntxd = NTXD;
- tunables->nrxd = NRXD;
- tunables->rxbufsz = RXBUFSZ;
- tunables->nrxbufpost = NRXBUFPOST;
- tunables->maxscb = MAXSCB;
- tunables->ampdunummpdu = AMPDU_NUM_MPDU;
- tunables->maxpktcb = MAXPKTCB;
- tunables->maxucodebss = BRCMS_MAX_UCODE_BSS;
- tunables->maxucodebss4 = BRCMS_MAX_UCODE_BSS4;
- tunables->maxbss = MAXBSS;
- tunables->datahiwat = BRCMS_DATAHIWAT;
- tunables->ampdudatahiwat = BRCMS_AMPDUDATAHIWAT;
- tunables->rxbnd = RXBND;
- tunables->txsbnd = TXSBND;
-}
-
-static struct brcms_pub *brcms_c_pub_malloc(uint unit, uint *err, uint devid)
-{
- struct brcms_pub *pub;
-
- pub = kzalloc(sizeof(struct brcms_pub), GFP_ATOMIC);
- if (pub == NULL) {
- *err = 1001;
- goto fail;
- }
-
- pub->tunables = kzalloc(sizeof(struct brcms_tunables), GFP_ATOMIC);
- if (pub->tunables == NULL) {
- *err = 1028;
- goto fail;
- }
-
- /* need to init the tunables now */
- brcms_c_tunables_init(pub->tunables, devid);
-
- pub->multicast = kzalloc(ETH_ALEN * MAXMULTILIST, GFP_ATOMIC);
- if (pub->multicast == NULL) {
- *err = 1003;
- goto fail;
- }
-
- return pub;
-
- fail:
- brcms_c_pub_mfree(pub);
- return NULL;
-}
-
-static void brcms_c_pub_mfree(struct brcms_pub *pub)
-{
- if (pub == NULL)
- return;
-
- kfree(pub->multicast);
- kfree(pub->tunables);
- kfree(pub);
-}
-
-static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit)
-{
- struct brcms_bss_cfg *cfg;
-
- cfg = kzalloc(sizeof(struct brcms_bss_cfg), GFP_ATOMIC);
- if (cfg == NULL)
- goto fail;
-
- cfg->current_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
- if (cfg->current_bss == NULL)
- goto fail;
-
- return cfg;
-
- fail:
- brcms_c_bsscfg_mfree(cfg);
- return NULL;
-}
-
-static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg)
-{
- if (cfg == NULL)
- return;
-
- kfree(cfg->maclist);
- kfree(cfg->current_bss);
- kfree(cfg);
-}
-
-static void brcms_c_bsscfg_ID_assign(struct brcms_c_info *wlc,
- struct brcms_bss_cfg *bsscfg)
-{
- bsscfg->ID = wlc->next_bsscfg_ID;
- wlc->next_bsscfg_ID++;
-}
-
-/*
- * The common driver entry routine. Error codes should be unique
- */
-struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err, uint devid)
-{
- struct brcms_c_info *wlc;
-
- wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC);
- if (wlc == NULL) {
- *err = 1002;
- goto fail;
- }
-
- /* allocate struct brcms_c_pub state structure */
- wlc->pub = brcms_c_pub_malloc(unit, err, devid);
- if (wlc->pub == NULL) {
- *err = 1003;
- goto fail;
- }
- wlc->pub->wlc = wlc;
-
- /* allocate struct brcms_hardware state structure */
-
- wlc->hw = kzalloc(sizeof(struct brcms_hardware), GFP_ATOMIC);
- if (wlc->hw == NULL) {
- *err = 1005;
- goto fail;
- }
- wlc->hw->wlc = wlc;
-
- wlc->hw->bandstate[0] =
- kzalloc(sizeof(struct brcms_hw_band) * MAXBANDS, GFP_ATOMIC);
- if (wlc->hw->bandstate[0] == NULL) {
- *err = 1006;
- goto fail;
- } else {
- int i;
-
- for (i = 1; i < MAXBANDS; i++) {
- wlc->hw->bandstate[i] = (struct brcms_hw_band *)
- ((unsigned long)wlc->hw->bandstate[0] +
- (sizeof(struct brcms_hw_band) * i));
- }
- }
-
- wlc->modulecb =
- kzalloc(sizeof(struct modulecb) * BRCMS_MAXMODULES, GFP_ATOMIC);
- if (wlc->modulecb == NULL) {
- *err = 1009;
- goto fail;
- }
-
- wlc->default_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
- if (wlc->default_bss == NULL) {
- *err = 1010;
- goto fail;
- }
-
- wlc->cfg = brcms_c_bsscfg_malloc(unit);
- if (wlc->cfg == NULL) {
- *err = 1011;
- goto fail;
- }
- brcms_c_bsscfg_ID_assign(wlc, wlc->cfg);
-
- wlc->wsec_def_keys[0] =
- kzalloc(sizeof(struct wsec_key) * BRCMS_DEFAULT_KEYS,
- GFP_ATOMIC);
- if (wlc->wsec_def_keys[0] == NULL) {
- *err = 1015;
- goto fail;
- } else {
- int i;
- for (i = 1; i < BRCMS_DEFAULT_KEYS; i++) {
- wlc->wsec_def_keys[i] = (struct wsec_key *)
- ((unsigned long)wlc->wsec_def_keys[0] +
- (sizeof(struct wsec_key) * i));
- }
- }
-
- wlc->protection = kzalloc(sizeof(struct brcms_protection),
- GFP_ATOMIC);
- if (wlc->protection == NULL) {
- *err = 1016;
- goto fail;
- }
-
- wlc->stf = kzalloc(sizeof(struct brcms_stf), GFP_ATOMIC);
- if (wlc->stf == NULL) {
- *err = 1017;
- goto fail;
- }
-
- wlc->bandstate[0] =
- kzalloc(sizeof(struct brcms_band)*MAXBANDS, GFP_ATOMIC);
- if (wlc->bandstate[0] == NULL) {
- *err = 1025;
- goto fail;
- } else {
- int i;
-
- for (i = 1; i < MAXBANDS; i++) {
- wlc->bandstate[i] = (struct brcms_band *)
- ((unsigned long)wlc->bandstate[0]
- + (sizeof(struct brcms_band)*i));
- }
- }
-
- wlc->corestate = kzalloc(sizeof(struct brcms_core), GFP_ATOMIC);
- if (wlc->corestate == NULL) {
- *err = 1026;
- goto fail;
- }
-
- wlc->corestate->macstat_snapshot =
- kzalloc(sizeof(struct macstat), GFP_ATOMIC);
- if (wlc->corestate->macstat_snapshot == NULL) {
- *err = 1027;
- goto fail;
- }
-
- return wlc;
-
- fail:
- brcms_c_detach_mfree(wlc);
- return NULL;
-}
-
-void brcms_c_detach_mfree(struct brcms_c_info *wlc)
-{
- if (wlc == NULL)
- return;
-
- brcms_c_bsscfg_mfree(wlc->cfg);
- brcms_c_pub_mfree(wlc->pub);
- kfree(wlc->modulecb);
- kfree(wlc->default_bss);
- kfree(wlc->wsec_def_keys[0]);
- kfree(wlc->protection);
- kfree(wlc->stf);
- kfree(wlc->bandstate[0]);
- kfree(wlc->corestate->macstat_snapshot);
- kfree(wlc->corestate);
- kfree(wlc->hw->bandstate[0]);
- kfree(wlc->hw);
-
- /* free the wlc */
- kfree(wlc);
- wlc = NULL;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/ampdu.c b/drivers/staging/brcm80211/brcmsmac/ampdu.c
index fcaf61e3b134..7f27dbdb6b60 100644
--- a/drivers/staging/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/staging/brcm80211/brcmsmac/ampdu.c
@@ -22,19 +22,32 @@
#include "main.h"
#include "ampdu.h"
-#define AMPDU_MAX_MPDU 32 /* max number of mpdus in an ampdu */
-#define AMPDU_NUM_MPDU_LEGACY 16 /* max number of mpdus in an ampdu to a legacy */
-#define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */
-#define AMPDU_TX_BA_DEF_WSIZE 64 /* default Tx ba window size (in pdu) */
-#define AMPDU_RX_BA_DEF_WSIZE 64 /* max Rx ba window size (in pdu) */
-#define AMPDU_RX_BA_MAX_WSIZE 64 /* default Rx ba window size (in pdu) */
-#define AMPDU_MAX_DUR 5 /* max dur of tx ampdu (in msec) */
-#define AMPDU_DEF_RETRY_LIMIT 5 /* default tx retry limit */
-#define AMPDU_DEF_RR_RETRY_LIMIT 2 /* default tx retry limit at reg rate */
-#define AMPDU_DEF_TXPKT_WEIGHT 2 /* default weight of ampdu in txfifo */
-#define AMPDU_DEF_FFPLD_RSVD 2048 /* default ffpld reserved bytes */
-#define AMPDU_INI_FREE 10 /* # of inis to be freed on detach */
-#define AMPDU_SCB_MAX_RELEASE 20 /* max # of mpdus released at a time */
+/* max number of mpdus in an ampdu */
+#define AMPDU_MAX_MPDU 32
+/* max number of mpdus in an ampdu to a legacy */
+#define AMPDU_NUM_MPDU_LEGACY 16
+/* max Tx ba window size (in pdu) */
+#define AMPDU_TX_BA_MAX_WSIZE 64
+/* default Tx ba window size (in pdu) */
+#define AMPDU_TX_BA_DEF_WSIZE 64
+/* default Rx ba window size (in pdu) */
+#define AMPDU_RX_BA_DEF_WSIZE 64
+/* max Rx ba window size (in pdu) */
+#define AMPDU_RX_BA_MAX_WSIZE 64
+/* max dur of tx ampdu (in msec) */
+#define AMPDU_MAX_DUR 5
+/* default tx retry limit */
+#define AMPDU_DEF_RETRY_LIMIT 5
+/* default tx retry limit at reg rate */
+#define AMPDU_DEF_RR_RETRY_LIMIT 2
+/* default weight of ampdu in txfifo */
+#define AMPDU_DEF_TXPKT_WEIGHT 2
+/* default ffpld reserved bytes */
+#define AMPDU_DEF_FFPLD_RSVD 2048
+/* # of inis to be freed on detach */
+#define AMPDU_INI_FREE 10
+/* max # of mpdus released at a time */
+#define AMPDU_SCB_MAX_RELEASE 20
#define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */
#define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu
@@ -47,6 +60,11 @@
* accumulate between resets.
*/
+#define AMPDU_DELIMITER_LEN 4
+
+/* max allowed number of mpdus in an ampdu (2 streams) */
+#define AMPDU_NUM_MPDU 16
+
#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
@@ -54,49 +72,77 @@
AMPDU_DELIMITER_LEN + 3\
+ DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
+/* modulo add/sub, bound = 2^k */
+#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
+#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
+
/* structure to hold tx fifo information and pre-loading state
* counters specific to tx underflows of ampdus
* some counters might be redundant with the ones in wlc or ampdu structures.
* This allows to maintain a specific state independently of
* how often and/or when the wlc counters are updated.
+ *
+ * ampdu_pld_size: number of bytes to be pre-loaded
+ * mcs2ampdu_table: per-mcs max # of mpdus in an ampdu
+ * prev_txfunfl: num of underflows last read from the HW macstats counter
+ * accum_txfunfl: num of underflows since we modified pld params
+ * accum_txampdu: num of tx ampdu since we modified pld params
+ * prev_txampdu: previous reading of tx ampdu
+ * dmaxferrate: estimated dma avg xfer rate in kbits/sec
*/
struct brcms_fifo_info {
- u16 ampdu_pld_size; /* number of bytes to be pre-loaded */
- u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; /* per-mcs max # of mpdus in an ampdu */
- u16 prev_txfunfl; /* num of underflows last read from the HW macstats counter */
- u32 accum_txfunfl; /* num of underflows since we modified pld params */
- u32 accum_txampdu; /* num of tx ampdu since we modified pld params */
- u32 prev_txampdu; /* previous reading of tx ampdu */
- u32 dmaxferrate; /* estimated dma avg xfer rate in kbits/sec */
+ u16 ampdu_pld_size;
+ u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];
+ u16 prev_txfunfl;
+ u32 accum_txfunfl;
+ u32 accum_txampdu;
+ u32 prev_txampdu;
+ u32 dmaxferrate;
};
-/* AMPDU module specific state */
+/* AMPDU module specific state
+ *
+ * wlc: pointer to main wlc structure
+ * scb_handle: scb cubby handle to retrieve data from scb
+ * ini_enable: per-tid initiator enable/disable of ampdu
+ * ba_tx_wsize: Tx ba window size (in pdu)
+ * ba_rx_wsize: Rx ba window size (in pdu)
+ * retry_limit: mpdu transmit retry limit
+ * rr_retry_limit: mpdu transmit retry limit at regular rate
+ * retry_limit_tid: per-tid mpdu transmit retry limit
+ * rr_retry_limit_tid: per-tid mpdu transmit retry limit at regular rate
+ * mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec
+ * max_pdu: max pdus allowed in ampdu
+ * dur: max duration of an ampdu (in msec)
+ * txpkt_weight: weight of ampdu in txfifo; reduces rate lag
+ * rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes
+ * ffpld_rsvd: number of bytes to reserve for preload
+ * max_txlen: max size of ampdu per mcs, bw and sgi
+ * mfbr: enable multiple fallback rate
+ * tx_max_funl: underflows should be kept such that
+ * (tx_max_funfl*underflows) < tx frames
+ * fifo_tb: table of fifo infos
+ */
struct ampdu_info {
- struct brcms_c_info *wlc; /* pointer to main wlc structure */
- int scb_handle; /* scb cubby handle to retrieve data from scb */
- u8 ini_enable[AMPDU_MAX_SCB_TID]; /* per-tid initiator enable/disable of ampdu */
- u8 ba_tx_wsize; /* Tx ba window size (in pdu) */
- u8 ba_rx_wsize; /* Rx ba window size (in pdu) */
- u8 retry_limit; /* mpdu transmit retry limit */
- u8 rr_retry_limit; /* mpdu transmit retry limit at regular rate */
- u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; /* per-tid mpdu transmit retry limit */
- /* per-tid mpdu transmit retry limit at regular rate */
+ struct brcms_c_info *wlc;
+ int scb_handle;
+ u8 ini_enable[AMPDU_MAX_SCB_TID];
+ u8 ba_tx_wsize;
+ u8 ba_rx_wsize;
+ u8 retry_limit;
+ u8 rr_retry_limit;
+ u8 retry_limit_tid[AMPDU_MAX_SCB_TID];
u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
- u8 mpdu_density; /* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
- s8 max_pdu; /* max pdus allowed in ampdu */
- u8 dur; /* max duration of an ampdu (in msec) */
- u8 txpkt_weight; /* weight of ampdu in txfifo; reduces rate lag */
- u8 rx_factor; /* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
- u32 ffpld_rsvd; /* number of bytes to reserve for preload */
- u32 max_txlen[MCS_TABLE_SIZE][2][2]; /* max size of ampdu per mcs, bw and sgi */
- void *ini_free[AMPDU_INI_FREE]; /* array of ini's to be freed on detach */
- bool mfbr; /* enable multiple fallback rate */
- u32 tx_max_funl; /* underflows should be kept such that
- * (tx_max_funfl*underflows) < tx frames
- */
- /* table of fifo infos */
+ u8 mpdu_density;
+ s8 max_pdu;
+ u8 dur;
+ u8 txpkt_weight;
+ u8 rx_factor;
+ u32 ffpld_rsvd;
+ u32 max_txlen[MCS_TABLE_SIZE][2][2];
+ bool mfbr;
+ u32 tx_max_funl;
struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO];
-
};
/* used for flushing ampdu packets */
@@ -105,32 +151,75 @@ struct cb_del_ampdu_pars {
u16 tid;
};
-#define AMPDU_CLEANUPFLAG_RX (0x1)
-#define AMPDU_CLEANUPFLAG_TX (0x2)
+static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
+{
+ u32 rate, mcs;
-#define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
-#define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
+ for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
+ /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
+ /* 20MHz, No SGI */
+ rate = mcs_2_rate(mcs, false, false);
+ ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
+ /* 40 MHz, No SGI */
+ rate = mcs_2_rate(mcs, true, false);
+ ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
+ /* 20MHz, SGI */
+ rate = mcs_2_rate(mcs, false, true);
+ ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
+ /* 40 MHz, SGI */
+ rate = mcs_2_rate(mcs, true, true);
+ ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
+ }
+}
-static void brcms_c_ffpld_init(struct ampdu_info *ampdu);
-static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int f);
-static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
+static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
+{
+ if (BRCMS_PHY_11N_CAP(ampdu->wlc->band))
+ return true;
+ else
+ return false;
+}
-static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu,
- u8 dur);
-static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
- struct scb *scb);
-static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu);
+static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
+{
+ struct brcms_c_info *wlc = ampdu->wlc;
-#define brcms_c_ampdu_txflowcontrol(a, b, c) do {} while (0)
+ wlc->pub->_ampdu = false;
-static void
-brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
- struct scb *scb,
- struct sk_buff *p, struct tx_status *txs,
- u32 frmtxstatus, u32 frmtxstatus2);
+ if (on) {
+ if (!(wlc->pub->_n_enab & SUPPORT_11N)) {
+ wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
+ "nmode enabled\n", wlc->pub->unit);
+ return -ENOTSUPP;
+ }
+ if (!brcms_c_ampdu_cap(ampdu)) {
+ wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
+ "ampdu capable\n", wlc->pub->unit);
+ return -ENOTSUPP;
+ }
+ wlc->pub->_ampdu = on;
+ }
+
+ return 0;
+}
+
+static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
+{
+ int i, j;
+ struct brcms_fifo_info *fifo;
+
+ for (j = 0; j < NUM_FFPLD_FIFO; j++) {
+ fifo = (ampdu->fifo_tb + j);
+ fifo->ampdu_pld_size = 0;
+ for (i = 0; i <= FFPLD_MAX_MCS; i++)
+ fifo->mcs2ampdu_table[i] = 255;
+ fifo->dmaxferrate = 0;
+ fifo->accum_txampdu = 0;
+ fifo->prev_txfunfl = 0;
+ fifo->accum_txfunfl = 0;
-static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu);
-static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on);
+ }
+}
struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
{
@@ -138,11 +227,9 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
int i;
ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
- if (!ampdu) {
- wiphy_err(wlc->wiphy, "wl%d: brcms_c_ampdu_attach: out of mem"
- "\n", wlc->pub->unit);
+ if (!ampdu)
return NULL;
- }
+
ampdu->wlc = wlc;
for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
@@ -163,7 +250,10 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
- /* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
+ /*
+ * bump max ampdu rcv size to 64k for all 11n
+ * devices except 4321A0 and 4321A1
+ */
if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
else
@@ -189,27 +279,16 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
void brcms_c_ampdu_detach(struct ampdu_info *ampdu)
{
- int i;
-
- if (!ampdu)
- return;
-
- /* free all ini's which were to be freed on callbacks which were never called */
- for (i = 0; i < AMPDU_INI_FREE; i++) {
- kfree(ampdu->ini_free[i]);
- }
-
- brcms_c_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
kfree(ampdu);
}
static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
struct scb *scb)
{
- struct scb_ampdu *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+ struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
int i;
- scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
+ scb_ampdu->max_pdu = AMPDU_NUM_MPDU;
/* go back to legacy size if some preloading is occurring */
for (i = 0; i < NUM_FFPLD_FIFO; i++) {
@@ -221,7 +300,8 @@ static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
if (ampdu->max_pdu != AUTO)
scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
- scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
+ scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu,
+ AMPDU_SCB_MAX_RELEASE);
if (scb_ampdu->max_rx_ampdu_bytes)
scb_ampdu->release = min_t(u8, scb_ampdu->release,
@@ -234,24 +314,38 @@ static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu)
{
- brcms_c_scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
+ brcms_c_scb_ampdu_update_config(ampdu, &ampdu->wlc->pri_scb);
}
-static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
+static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
{
- int i, j;
- struct brcms_fifo_info *fifo;
+ int i;
+ u32 phy_rate, dma_rate, tmp;
+ u8 max_mpdu;
+ struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f);
- for (j = 0; j < NUM_FFPLD_FIFO; j++) {
- fifo = (ampdu->fifo_tb + j);
- fifo->ampdu_pld_size = 0;
- for (i = 0; i <= FFPLD_MAX_MCS; i++)
- fifo->mcs2ampdu_table[i] = 255;
- fifo->dmaxferrate = 0;
- fifo->accum_txampdu = 0;
- fifo->prev_txfunfl = 0;
- fifo->accum_txfunfl = 0;
+ /* recompute the dma rate */
+ /* note : we divide/multiply by 100 to avoid integer overflows */
+ max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
+ AMPDU_NUM_MPDU_LEGACY);
+ phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
+ dma_rate =
+ (((phy_rate / 100) *
+ (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
+ / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
+ fifo->dmaxferrate = dma_rate;
+ /* fill up the mcs2ampdu table; do not recalc the last mcs */
+ dma_rate = dma_rate >> 7;
+ for (i = 0; i < FFPLD_MAX_MCS; i++) {
+ /* shifting to keep it within integer range */
+ phy_rate = mcs_2_rate(i, true, false) >> 7;
+ if (phy_rate > dma_rate) {
+ tmp = ((fifo->ampdu_pld_size * phy_rate) /
+ ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
+ tmp = min_t(u32, tmp, 255);
+ fifo->mcs2ampdu_table[i] = (u8) tmp;
+ }
}
}
@@ -264,7 +358,7 @@ static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
{
struct ampdu_info *ampdu = wlc->ampdu;
- u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
+ u32 phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
u32 txunfl_ratio;
u8 max_mpdu;
u32 current_ampdu_cnt = 0;
@@ -275,7 +369,7 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
u16 cur_txunfl;
/* return if we got here for a different reason than underflows */
- cur_txunfl = brcms_c_read_shm(wlc,
+ cur_txunfl = brcms_b_read_shm(wlc->hw,
M_UCODE_MACSTAT +
offsetof(struct macstat, txfunfl[fid]));
new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
@@ -289,7 +383,7 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
return 1;
/* check if fifo is big enough */
- if (brcms_c_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz))
+ if (brcms_b_xmtfifo_sz_get(wlc->hw, fid, &xmtfifo_sz))
return -1;
if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
@@ -317,13 +411,13 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
if (txunfl_ratio > ampdu->tx_max_funl) {
- if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
+ if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT)
fifo->accum_txfunfl = 0;
- }
+
return 0;
}
- max_mpdu =
- min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
+ max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
+ AMPDU_NUM_MPDU_LEGACY);
/* In case max value max_pdu is already lower than
the fifo depth, there is nothing more we can do.
@@ -345,11 +439,12 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
brcms_c_scb_ampdu_update_config_all(ampdu);
/*
- compute a new dma xfer rate for max_mpdu @ max mcs.
- This is the minimum dma rate that
- can achieve no underflow condition for the current mpdu size.
+ * compute a new dma xfer rate for max_mpdu @ max mcs.
+ * This is the minimum dma rate that can achieve no
+ * underflow condition for the current mpdu size.
+ *
+ * note : we divide/multiply by 100 to avoid integer overflows
*/
- /* note : we divide/multiply by 100 to avoid integer overflows */
fifo->dmaxferrate =
(((phy_rate / 100) *
(max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
@@ -379,38 +474,6 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
return 0;
}
-static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
-{
- int i;
- u32 phy_rate, dma_rate, tmp;
- u8 max_mpdu;
- struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f);
-
- /* recompute the dma rate */
- /* note : we divide/multiply by 100 to avoid integer overflows */
- max_mpdu =
- min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
- phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
- dma_rate =
- (((phy_rate / 100) *
- (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
- / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
- fifo->dmaxferrate = dma_rate;
-
- /* fill up the mcs2ampdu table; do not recalc the last mcs */
- dma_rate = dma_rate >> 7;
- for (i = 0; i < FFPLD_MAX_MCS; i++) {
- /* shifting to keep it within integer range */
- phy_rate = MCS_RATE(i, true, false) >> 7;
- if (phy_rate > dma_rate) {
- tmp = ((fifo->ampdu_pld_size * phy_rate) /
- ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
- tmp = min_t(u32, tmp, 255);
- fifo->mcs2ampdu_table[i] = (u8) tmp;
- }
- }
-}
-
void
brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
u8 ba_wsize, /* negotiated ba window size (in pdu) */
@@ -419,8 +482,8 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
struct scb_ampdu *scb_ampdu;
struct scb_ampdu_tid_ini *ini;
struct ampdu_info *ampdu = wlc->ampdu;
- struct scb *scb = wlc->pub->global_scb;
- scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+ struct scb *scb = &wlc->pri_scb;
+ scb_ampdu = &scb->scb_ampdu;
if (!ampdu->ini_enable[tid]) {
wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
@@ -428,7 +491,7 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
return;
}
- ini = SCB_AMPDU_INI(scb_ampdu, tid);
+ ini = &scb_ampdu->ini[tid];
ini->tid = tid;
ini->scb = scb_ampdu->scb;
ini->ba_wsize = ba_wsize;
@@ -460,8 +523,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
struct scb_ampdu_tid_ini *ini;
u8 mcs = 0;
bool use_rts = false, use_cts = false;
- ratespec_t rspec = 0, rspec_fallback = 0;
- ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
+ u32 rspec = 0, rspec_fallback = 0;
+ u32 rts_rspec = 0, rts_rspec_fallback = 0;
u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
struct ieee80211_rts *rts;
u8 rr_retry_limit;
@@ -479,17 +542,16 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
f = ampdu->fifo_tb + prio2fifo[tid];
- scb = wlc->pub->global_scb;
- scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+ scb = &wlc->pri_scb;
+ scb_ampdu = &scb->scb_ampdu;
ini = &scb_ampdu->ini[tid];
/* Let pressure continue to build ... */
qlen = pktq_plen(&qi->q, prec);
if (ini->tx_in_transit > 0 &&
- qlen < min(scb_ampdu->max_pdu, ini->ba_wsize)) {
+ qlen < min(scb_ampdu->max_pdu, ini->ba_wsize))
/* Collect multiple MPDU's to be sent in the next AMPDU */
return -EBUSY;
- }
/* at this point we intend to transmit an AMPDU */
rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
@@ -614,7 +676,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
}
is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
- sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
+ sgi = plcp3_issgi(plcp3) ? 1 : 0;
mcs = plcp0 & ~MIMO_PLCP_40MHZ;
max_ampdu_bytes =
min(scb_ampdu->max_rx_ampdu_bytes,
@@ -622,7 +684,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
if (is40)
mimo_ctlchbw =
- CHSPEC_SB_UPPER(BRCMS_BAND_PI_RADIO_CHANSPEC)
+ CHSPEC_SB_UPPER(wlc_phy_chanspec_get(
+ wlc->band->pi))
? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
/* rebuild the rspec and rspec_fallback */
@@ -632,9 +695,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
if (fbr_iscck) /* CCK */
- rspec_fallback =
- CCK_RSPEC(CCK_PHY2MAC_RATE
- (txh->FragPLCPFallback[0]));
+ rspec_fallback = cck_rspec(cck_phy2mac_rate
+ (txh->FragPLCPFallback[0]));
else { /* MIMO */
rspec_fallback = RSPEC_MIMORATE;
rspec_fallback |=
@@ -657,7 +719,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
/* if (first mpdu for host agg) */
/* test whether to add more */
- if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
+ if ((mcs_2_rate(mcs, true, false) >= f->dmaxferrate) &&
(count == f->mcs2ampdu_table[mcs])) {
BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
" ampdu at %d for mcs %d\n",
@@ -665,13 +727,16 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
break;
}
- if (count == scb_ampdu->max_pdu) {
+ if (count == scb_ampdu->max_pdu)
break;
- }
- /* check to see if the next pkt is a candidate for aggregation */
+ /*
+ * check to see if the next pkt is
+ * a candidate for aggregation
+ */
p = pktq_ppeek(&qi->q, prec);
- tx_info = IEEE80211_SKB_CB(p); /* tx_info must be checked with current p */
+ /* tx_info must be checked with current p */
+ tx_info = IEEE80211_SKB_CB(p);
if (p) {
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
@@ -686,8 +751,11 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
continue;
}
- /* check if there are enough descriptors available */
- if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
+ /*
+ * check if there are enough
+ * descriptors available
+ */
+ if (*wlc->core->txavail[fifo] <= seg_cnt + 1) {
wiphy_err(wiphy, "%s: No fifo space "
"!!\n", __func__);
p = NULL;
@@ -745,7 +813,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
}
/* set the preload length */
- if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
+ if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
dma_len = min(dma_len, f->ampdu_pld_size);
txh->PreloadSize = cpu_to_le16(dma_len);
} else
@@ -797,10 +865,10 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
/* inform rate_sel if it this is a rate probe pkt */
frameid = le16_to_cpu(txh->TxFrameID);
- if (frameid & TXFID_RATE_PROBE_MASK) {
+ if (frameid & TXFID_RATE_PROBE_MASK)
wiphy_err(wiphy, "%s: XXX what to do with "
"TXFID_RATE_PROBE_MASK!?\n", __func__);
- }
+
for (i = 0; i < count; i++)
brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1),
ampdu->txpkt_weight);
@@ -810,62 +878,6 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
return err;
}
-void
-brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
- struct sk_buff *p, struct tx_status *txs)
-{
- struct scb_ampdu *scb_ampdu;
- struct brcms_c_info *wlc = ampdu->wlc;
- struct scb_ampdu_tid_ini *ini;
- u32 s1 = 0, s2 = 0;
- struct ieee80211_tx_info *tx_info;
-
- tx_info = IEEE80211_SKB_CB(p);
-
- /* BMAC_NOTE: For the split driver, second level txstatus comes later
- * So if the ACK was received then wait for the second level else just
- * call the first one
- */
- if (txs->status & TX_STATUS_ACK_RCV) {
- u8 status_delay = 0;
-
- /* wait till the next 8 bytes of txstatus is available */
- while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
- udelay(1);
- status_delay++;
- if (status_delay > 10) {
- return; /* error condition */
- }
- }
-
- s2 = R_REG(&wlc->regs->frmtxstatus2);
- }
-
- if (likely(scb)) {
- scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
- ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
- brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
- } else {
- /* loop through all pkts and free */
- u8 queue = txs->frameid & TXFID_QUEUE_MASK;
- struct d11txh *txh;
- u16 mcl;
- while (p) {
- tx_info = IEEE80211_SKB_CB(p);
- txh = (struct d11txh *) p->data;
- mcl = le16_to_cpu(txh->MacTxControlLow);
- brcmu_pkt_buf_free_skb(p);
- /* break out if last packet of ampdu */
- if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
- TXC_AMPDU_LAST)
- break;
- p = GETNEXTTXP(wlc, queue);
- }
- brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
- }
- brcms_c_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
-}
-
static void
brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
struct ieee80211_tx_info *tx_info,
@@ -881,8 +893,6 @@ brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
}
}
-#define SHORTNAME "AMPDU status"
-
static void
brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
struct sk_buff *p, struct tx_status *txs,
@@ -912,10 +922,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
memset(hole, 0, sizeof(hole));
#endif
- scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+ scb_ampdu = &scb->scb_ampdu;
tid = (u8) (p->priority);
- ini = SCB_AMPDU_INI(scb_ampdu, tid);
+ ini = &scb_ampdu->ini[tid];
retry_limit = ampdu->retry_limit_tid[tid];
rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
memset(bitmap, 0, sizeof(bitmap));
@@ -923,9 +933,8 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
supr_status = txs->status & TX_STATUS_SUPR_MASK;
if (txs->status & TX_STATUS_ACK_RCV) {
- if (TX_STATUS_SUPR_UF == supr_status) {
+ if (TX_STATUS_SUPR_UF == supr_status)
update_rate = false;
- }
WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
start_seq = txs->sequence >> SEQNUM_SHIFT;
@@ -967,15 +976,17 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
supr_status == TX_STATUS_SUPR_EXPTIME) {
retry = false;
} else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
- /* TX underflow : try tuning pre-loading or ampdu size */
+ /* TX underflow:
+ * try tuning pre-loading or ampdu size
+ */
} else if (supr_status == TX_STATUS_SUPR_FRAG) {
- /* if there were underflows, but pre-loading is not active,
- notify rate adaptation.
+ /*
+ * if there were underflows, but pre-loading
+ * is not active, notify rate adaptation.
*/
if (brcms_c_ffpld_check_txfunfl(wlc,
- prio2fifo[tid]) > 0) {
+ prio2fifo[tid]) > 0)
tx_error = true;
- }
}
} else if (txs->phyerr) {
update_rate = false;
@@ -983,7 +994,7 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
"error (0x%x)\n", wlc->pub->unit,
txs->phyerr);
- if (WL_ERROR_ON()) {
+ if (brcm_msg_level & LOG_ERROR_VAL) {
brcmu_prpkt("txpkt (AMPDU)", p);
brcms_c_print_txdesc((struct d11txh *) p->data);
}
@@ -1019,7 +1030,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
ini->tx_in_transit--;
ini->txretry[index] = 0;
- /* ampdu_ack_len: number of acked aggregated frames */
+ /*
+ * ampdu_ack_len:
+ * number of acked aggregated frames
+ */
/* ampdu_len: number of aggregated frames */
brcms_c_ampdu_rate_status(wlc, tx_info, txs,
mcs);
@@ -1044,11 +1058,14 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
if (retry && (txrate[0].count < (int)retry_limit)) {
ini->txretry[index]++;
ini->tx_in_transit--;
- /* Use high prededence for retransmit to give some punch */
+ /*
+ * Use high prededence for retransmit to
+ * give some punch
+ */
/* brcms_c_txq_enq(wlc, scb, p,
* BRCMS_PRIO_TO_PREC(tid)); */
brcms_c_txq_enq(wlc, scb, p,
- BRCMS_PRIO_TO_HI_PREC(tid));
+ BRCMS_PRIO_TO_HI_PREC(tid));
} else {
/* Retry timeout */
ini->tx_in_transit--;
@@ -1060,7 +1077,7 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
skb_pull(p, D11_PHY_HDR_LEN);
skb_pull(p, D11_TXH_LEN);
wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_"
- "transit %d\n", SHORTNAME, seq,
+ "transit %d\n", "AMPDU status", seq,
ini->tx_in_transit);
ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
p);
@@ -1073,7 +1090,7 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
TXC_AMPDU_LAST)
break;
- p = GETNEXTTXP(wlc, queue);
+ p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
}
brcms_c_send_q(wlc);
@@ -1083,55 +1100,58 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
}
-static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
+void
+brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
+ struct sk_buff *p, struct tx_status *txs)
{
+ struct scb_ampdu *scb_ampdu;
struct brcms_c_info *wlc = ampdu->wlc;
+ struct scb_ampdu_tid_ini *ini;
+ u32 s1 = 0, s2 = 0;
+ struct ieee80211_tx_info *tx_info;
- wlc->pub->_ampdu = false;
-
- if (on) {
- if (!N_ENAB(wlc->pub)) {
- wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
- "nmode enabled\n", wlc->pub->unit);
- return -ENOTSUPP;
- }
- if (!brcms_c_ampdu_cap(ampdu)) {
- wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
- "ampdu capable\n", wlc->pub->unit);
- return -ENOTSUPP;
- }
- wlc->pub->_ampdu = on;
- }
+ tx_info = IEEE80211_SKB_CB(p);
- return 0;
-}
+ /* BMAC_NOTE: For the split driver, second level txstatus comes later
+ * So if the ACK was received then wait for the second level else just
+ * call the first one
+ */
+ if (txs->status & TX_STATUS_ACK_RCV) {
+ u8 status_delay = 0;
-static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
-{
- if (BRCMS_PHY_11N_CAP(ampdu->wlc->band))
- return true;
- else
- return false;
-}
+ /* wait till the next 8 bytes of txstatus is available */
+ while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
+ udelay(1);
+ status_delay++;
+ if (status_delay > 10)
+ return; /* error condition */
+ }
-static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
-{
- u32 rate, mcs;
+ s2 = R_REG(&wlc->regs->frmtxstatus2);
+ }
- for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
- /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
- /* 20MHz, No SGI */
- rate = MCS_RATE(mcs, false, false);
- ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
- /* 40 MHz, No SGI */
- rate = MCS_RATE(mcs, true, false);
- ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
- /* 20MHz, SGI */
- rate = MCS_RATE(mcs, false, true);
- ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
- /* 40 MHz, SGI */
- rate = MCS_RATE(mcs, true, true);
- ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
+ if (scb) {
+ scb_ampdu = &scb->scb_ampdu;
+ ini = &scb_ampdu->ini[p->priority];
+ brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
+ } else {
+ /* loop through all pkts and free */
+ u8 queue = txs->frameid & TXFID_QUEUE_MASK;
+ struct d11txh *txh;
+ u16 mcl;
+ while (p) {
+ tx_info = IEEE80211_SKB_CB(p);
+ txh = (struct d11txh *) p->data;
+ mcl = le16_to_cpu(txh->MacTxControlLow);
+ brcmu_pkt_buf_free_skb(p);
+ /* break out if last packet of ampdu */
+ if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
+ TXC_AMPDU_LAST)
+ break;
+ p = dma_getnexttxp(wlc->hw->di[queue],
+ DMA_RANGE_TRANSMITTED);
+ }
+ brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
}
}
@@ -1142,7 +1162,7 @@ void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc)
/* driver needs to write the ta in the template; ta is at offset 16 */
memset(template, 0, sizeof(template));
memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
- brcms_c_write_template_ram(wlc, (T_BA_TPL_BASE + 16),
+ brcms_b_write_template_ram(wlc->hw, (T_BA_TPL_BASE + 16),
(T_RAM_ACCESS_SZ * 2),
template);
}
@@ -1156,14 +1176,17 @@ void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
{
struct brcms_c_info *wlc = ampdu->wlc;
- /* Extend ucode internal watchdog timer to match larger received frames */
+ /*
+ * Extend ucode internal watchdog timer to
+ * match larger received frames
+ */
if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
IEEE80211_HT_MAX_AMPDU_64K) {
- brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
- brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
+ brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
+ brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
} else {
- brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
- brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
+ brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
+ brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
}
}
@@ -1211,9 +1234,8 @@ void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
ampdu_pars.sta = sta;
ampdu_pars.tid = tid;
- for (prec = 0; prec < pq->num_prec; prec++) {
+ for (prec = 0; prec < pq->num_prec; prec++)
brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
(void *)&ampdu_pars);
- }
brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
}
diff --git a/drivers/staging/brcm80211/brcmsmac/antsel.c b/drivers/staging/brcm80211/brcmsmac/antsel.c
index c4e76c093ae9..a47ce25cb9a2 100644
--- a/drivers/staging/brcm80211/brcmsmac/antsel.c
+++ b/drivers/staging/brcm80211/brcmsmac/antsel.c
@@ -18,7 +18,6 @@
#include <net/mac80211.h>
#include "types.h"
-#include "bmac.h"
#include "main.h"
#include "phy_shim.h"
#include "antsel.h"
@@ -50,55 +49,76 @@
#define ANT_SELCFG_NUM_2x4 4
#define ANT_SELCFG_DEF_2x4 0x02 /* default antenna configuration */
-/* static functions */
-static int brcms_c_antsel_cfgupd(struct antsel_info *asi,
- struct brcms_antselcfg *antsel);
-static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id);
-static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg);
-static void brcms_c_antsel_init_cfg(struct antsel_info *asi,
- struct brcms_antselcfg *antsel,
- bool auto_sel);
-
-const u16 mimo_2x4_div_antselpat_tbl[] = {
+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. */
};
-const u8 mimo_2x4_div_antselid_tbl[16] = {
+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 */
};
-const u16 mimo_2x3_div_antselpat_tbl[] = {
+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. */
};
-const u8 mimo_2x3_div_antselid_tbl[16] = {
+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 si_pub *sih = wlc->hw->sih;
asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC);
- if (!asi) {
- wiphy_err(wlc->wiphy, "wl%d: brcms_c_antsel_attach: out of "
- "mem\n", wlc->pub->unit);
+ if (!asi)
return NULL;
- }
asi->wlc = wlc;
asi->pub = wlc->pub;
asi->antsel_type = ANTSEL_NA;
asi->antsel_avail = false;
- asi->antsel_antswitch = (u8) getintvar(asi->pub->vars, "antswitch");
+ asi->antsel_antswitch = (u8) getintvar(sih, BRCMS_SROM_ANTSWITCH);
if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) {
switch (asi->antsel_antswitch) {
@@ -108,27 +128,26 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
/* 4321/2 board with 2x3 switch logic */
asi->antsel_type = ANTSEL_2x3;
/* Antenna selection availability */
- if (((u16) getintvar(asi->pub->vars, "aa2g") == 7) ||
- ((u16) getintvar(asi->pub->vars, "aa5g") == 7)) {
+ if (((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) ||
+ ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 7)) {
asi->antsel_avail = true;
- } else
- if (((u16) getintvar(asi->pub->vars, "aa2g") ==
- 3)
- || ((u16) getintvar(asi->pub->vars, "aa5g")
- == 3)) {
+ } else if (
+ (u16) getintvar(sih, BRCMS_SROM_AA2G) == 3 ||
+ (u16) getintvar(sih, BRCMS_SROM_AA5G) == 3) {
asi->antsel_avail = false;
} else {
asi->antsel_avail = false;
wiphy_err(wlc->wiphy, "antsel_attach: 2o3 "
"board cfg invalid\n");
}
+
break;
default:
break;
}
} else if ((asi->pub->sromrev == 4) &&
- ((u16) getintvar(asi->pub->vars, "aa2g") == 7) &&
- ((u16) getintvar(asi->pub->vars, "aa5g") == 0)) {
+ ((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) &&
+ ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 0)) {
/* hack to match old 4321CB2 cards with 2of3 antenna switch */
asi->antsel_type = ANTSEL_2x3;
asi->antsel_avail = true;
@@ -152,6 +171,64 @@ 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) ||
@@ -159,36 +236,23 @@ void brcms_c_antsel_init(struct antsel_info *asi)
brcms_c_antsel_cfgupd(asi, &asi->antcfg_11n);
}
-/* 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)
+/* boardlevel antenna selection: convert id to ant_cfg */
+static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id)
{
- 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;
+ u8 antcfg = ANT_SELCFG_DEF_2x2;
- } else { /* no antenna selection available */
+ 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;
- 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;
+ } 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
@@ -241,71 +305,3 @@ u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel)
return antselid;
}
-
-/* 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;
-}
-
-/* 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_c_write_shm(wlc, 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_c_write_shm(wlc, 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;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/bmac.c b/drivers/staging/brcm80211/brcmsmac/bmac.c
deleted file mode 100644
index b25c51705566..000000000000
--- a/drivers/staging/brcm80211/brcmsmac/bmac.c
+++ /dev/null
@@ -1,3593 +0,0 @@
-/*
- * 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/pci.h>
-#include <net/mac80211.h>
-
-#include <brcm_hw_ids.h>
-#include <aiutils.h>
-#include <chipcommon.h>
-#include "types.h"
-#include "rate.h"
-#include "phy/phy_hal.h"
-#include "channel.h"
-#include "main.h"
-#include "ucode_loader.h"
-#include "mac80211_if.h"
-#include "bmac.h"
-
-#define TIMER_INTERVAL_WATCHDOG_BMAC 1000 /* watchdog timer, in unit of ms */
-
-#define SYNTHPU_DLY_APHY_US 3700 /* a phy synthpu_dly time in us */
-#define SYNTHPU_DLY_BPHY_US 1050 /* b/g phy synthpu_dly time in us, default */
-#define SYNTHPU_DLY_NPHY_US 2048 /* n phy REV3 synthpu_dly time in us, default */
-#define SYNTHPU_DLY_LPPHY_US 300 /* lpphy synthpu_dly time in us */
-
-#define SYNTHPU_DLY_PHY_US_QT 100 /* QT synthpu_dly time in us */
-
-#ifndef BMAC_DUP_TO_REMOVE
-
-#define ANTCNT 10 /* vanilla M_MAX_ANTCNT value */
-
-#endif /* BMAC_DUP_TO_REMOVE */
-
-#define DMAREG(wlc_hw, direction, fifonum) \
- ((direction == DMA_TX) ? \
- (void *)&(wlc_hw->regs->fifo64regs[fifonum].dmaxmt) : \
- (void *)&(wlc_hw->regs->fifo64regs[fifonum].dmarcv))
-
-#define APHY_SLOT_TIME 9
-#define BPHY_SLOT_TIME 20
-
-/*
- * The following table lists the buffer memory allocated to xmt fifos in HW.
- * the size is in units of 256bytes(one block), total size is HW dependent
- * ucode has default fifo partition, sw can overwrite if necessary
- *
- * This is documented in twiki under the topic UcodeTxFifo. Please ensure
- * the twiki is updated before making changes.
- */
-
-#define XMTFIFOTBL_STARTREV 20 /* Starting corerev for the fifo size table */
-
-static u16 xmtfifo_sz[][NFIFO] = {
- {20, 192, 192, 21, 17, 5}, /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
- {9, 58, 22, 14, 14, 5}, /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
- {20, 192, 192, 21, 17, 5}, /* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */
- {20, 192, 192, 21, 17, 5}, /* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */
- {9, 58, 22, 14, 14, 5}, /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
-};
-
-static void brcms_b_clkctl_clk(struct brcms_hardware *wlc, uint mode);
-static void brcms_b_coreinit(struct brcms_c_info *wlc);
-
-/* used by wlc_wakeucode_init() */
-static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
- const struct d11init *inits);
-static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[],
- const uint nbytes);
-static void brcms_ucode_download(struct brcms_hardware *wlc);
-static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw);
-
-/* used by brcms_c_dpc() */
-static bool brcms_b_dotxstatus(struct brcms_hardware *wlc,
- struct tx_status *txs, u32 s2);
-static bool brcms_b_txstatus(struct brcms_hardware *wlc, bool bound,
- bool *fatal);
-static bool brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound);
-
-/* used by brcms_c_down() */
-static void brcms_c_flushqueues(struct brcms_c_info *wlc);
-
-static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs);
-static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw);
-static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw);
-static bool brcms_b_tx_fifo_suspended(struct brcms_hardware *wlc_hw,
- uint tx_fifo);
-static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
- uint tx_fifo);
-static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
- uint tx_fifo);
-
-/* Low Level Prototypes */
-static int brcms_b_bandtype(struct brcms_hardware *wlc_hw);
-static void brcms_b_info_init(struct brcms_hardware *wlc_hw);
-static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want);
-static u16 brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset,
- u32 sel);
-static void brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset,
- u16 v, u32 sel);
-static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk);
-static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme);
-static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw);
-static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw);
-static bool brcms_c_validboardtype(struct brcms_hardware *wlc);
-static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw);
-static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw);
-static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw);
-static void brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init);
-static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw);
-static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool want,
- mbool flags);
-static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw);
-static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw);
-static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc);
-static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask);
-static void brcms_c_gpio_init(struct brcms_c_info *wlc);
-static void brcms_c_write_hw_bcntemplate0(struct brcms_hardware *wlc_hw,
- void *bcn, int len);
-static void brcms_c_write_hw_bcntemplate1(struct brcms_hardware *wlc_hw,
- void *bcn, int len);
-static void brcms_b_bsinit(struct brcms_c_info *wlc, chanspec_t chanspec);
-static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit);
-static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
- chanspec_t chanspec);
-static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
- bool shortslot);
-static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw);
-static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw,
- u8 rate);
-
-/* === Low Level functions === */
-
-void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
-{
- wlc_hw->shortslot = shortslot;
-
- if (BAND_2G(brcms_b_bandtype(wlc_hw)) && wlc_hw->up) {
- brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
- brcms_b_update_slot_timing(wlc_hw, shortslot);
- brcms_c_enable_mac(wlc_hw->wlc);
- }
-}
-
-/*
- * Update the slot timing for standard 11b/g (20us slots)
- * or shortslot 11g (9us slots)
- * The PSM needs to be suspended for this call.
- */
-static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
- bool shortslot)
-{
- d11regs_t *regs;
-
- regs = wlc_hw->regs;
-
- if (shortslot) {
- /* 11g short slot: 11a timing */
- W_REG(&regs->ifs_slot, 0x0207); /* APHY_SLOT_TIME */
- brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
- } else {
- /* 11g long slot: 11b timing */
- W_REG(&regs->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */
- brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
- }
-}
-
-static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
-{
- struct wiphy *wiphy = wlc_hw->wlc->wiphy;
-
- /* init microcode host flags */
- brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs);
-
- /* do band-specific ucode IHR, SHM, and SCR inits */
- if (D11REV_IS(wlc_hw->corerev, 23)) {
- if (BRCMS_ISNPHY(wlc_hw->band)) {
- brcms_c_write_inits(wlc_hw, d11n0bsinitvals16);
- } else {
- wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
- " %d\n", __func__, wlc_hw->unit,
- wlc_hw->corerev);
- }
- } else {
- if (D11REV_IS(wlc_hw->corerev, 24)) {
- if (BRCMS_ISLCNPHY(wlc_hw->band)) {
- brcms_c_write_inits(wlc_hw,
- d11lcn0bsinitvals24);
- } else
- wiphy_err(wiphy, "%s: wl%d: unsupported phy in"
- " core rev %d\n", __func__,
- wlc_hw->unit, wlc_hw->corerev);
- } else {
- wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
- __func__, wlc_hw->unit, wlc_hw->corerev);
- }
- }
-}
-
-/* switch to new band but leave it inactive */
-static u32 brcms_c_setband_inact(struct brcms_c_info *wlc,
- uint bandunit)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- u32 macintmask;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
-
- /* disable interrupts */
- macintmask = brcms_intrsoff(wlc->wl);
-
- /* radio off */
- wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
-
- brcms_b_core_phy_clk(wlc_hw, OFF);
-
- brcms_c_setxband(wlc_hw, bandunit);
-
- return macintmask;
-}
-
-/* Process received frames */
-/*
- * Return true if more frames need to be processed. false otherwise.
- * Param 'bound' indicates max. # frames to process before break out.
- */
-static bool
-brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
-{
- struct sk_buff *p;
- struct sk_buff *head = NULL;
- struct sk_buff *tail = NULL;
- uint n = 0;
- uint bound_limit = bound ? wlc_hw->wlc->pub->tunables->rxbnd : -1;
- struct brcms_d11rxhdr *wlc_rxhdr = NULL;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
- /* gather received frames */
- while ((p = dma_rx(wlc_hw->di[fifo]))) {
-
- if (!tail)
- head = tail = p;
- else {
- tail->prev = p;
- tail = p;
- }
-
- /* !give others some time to run! */
- if (++n >= bound_limit)
- break;
- }
-
- /* post more rbufs */
- dma_rxfill(wlc_hw->di[fifo]);
-
- /* process each frame */
- while ((p = head) != NULL) {
- head = head->prev;
- p->prev = NULL;
-
- wlc_rxhdr = (struct brcms_d11rxhdr *) p->data;
-
- /* compute the RSSI from d11rxhdr and record it in wlc_rxd11hr */
- wlc_phy_rssi_compute(wlc_hw->band->pi, wlc_rxhdr);
-
- brcms_c_recv(wlc_hw->wlc, p);
- }
-
- return n >= bound_limit;
-}
-
-/* second-level interrupt processing
- * Return true if another dpc needs to be re-scheduled. false otherwise.
- * Param 'bounded' indicates if applicable loops should be bounded.
- */
-bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
-{
- u32 macintstatus;
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs = wlc_hw->regs;
- bool fatal = false;
- struct wiphy *wiphy = wlc->wiphy;
-
- if (DEVICEREMOVED(wlc)) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
- __func__);
- brcms_down(wlc->wl);
- return false;
- }
-
- /* grab and clear the saved software intstatus bits */
- macintstatus = wlc->macintstatus;
- wlc->macintstatus = 0;
-
- BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
- wlc_hw->unit, macintstatus);
-
- WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
-
- /* BCN template is available */
- /* ZZZ: Use AP_ACTIVE ? */
- if (AP_ENAB(wlc->pub) && (!APSTA_ENAB(wlc->pub))
- && (macintstatus & MI_BCNTPL)) {
- brcms_c_update_beacon(wlc);
- }
-
- /* tx status */
- if (macintstatus & MI_TFS) {
- if (brcms_b_txstatus(wlc->hw, bounded, &fatal))
- wlc->macintstatus |= MI_TFS;
- if (fatal) {
- wiphy_err(wiphy, "MI_TFS: fatal\n");
- goto fatal;
- }
- }
-
- if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
- brcms_c_tbtt(wlc);
-
- /* ATIM window end */
- if (macintstatus & MI_ATIMWINEND) {
- BCMMSG(wlc->wiphy, "end of ATIM window\n");
- OR_REG(&regs->maccommand, wlc->qvalid);
- wlc->qvalid = 0;
- }
-
- /* received data or control frame, MI_DMAINT is indication of RX_FIFO interrupt */
- if (macintstatus & MI_DMAINT)
- if (brcms_b_recv(wlc_hw, RX_FIFO, bounded))
- wlc->macintstatus |= MI_DMAINT;
-
- /* TX FIFO suspend/flush completion */
- if (macintstatus & MI_TXSTOP)
- brcms_b_tx_fifo_suspended(wlc_hw, TX_DATA_FIFO);
-
- /* noise sample collected */
- if (macintstatus & MI_BG_NOISE) {
- wlc_phy_noise_sample_intr(wlc_hw->band->pi);
- }
-
- if (macintstatus & MI_GP0) {
- wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d "
- "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
-
- printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
- __func__, wlc_hw->sih->chip,
- wlc_hw->sih->chiprev);
- /* big hammer */
- brcms_init(wlc->wl);
- }
-
- /* gptimer timeout */
- if (macintstatus & MI_TO) {
- W_REG(&regs->gptimer, 0);
- }
-
- if (macintstatus & MI_RFDISABLE) {
- BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the"
- " RF Disable Input\n", wlc_hw->unit);
- brcms_rfkill_set_hw_state(wlc->wl);
- }
-
- /* send any enq'd tx packets. Just makes sure to jump start tx */
- if (!pktq_empty(&wlc->pkt_queue->q))
- brcms_c_send_q(wlc);
-
- /* it isn't done and needs to be resched if macintstatus is non-zero */
- return wlc->macintstatus != 0;
-
- fatal:
- brcms_init(wlc->wl);
- return wlc->macintstatus != 0;
-}
-
-/* common low-level watchdog code */
-void brcms_b_watchdog(void *arg)
-{
- struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
- struct brcms_hardware *wlc_hw = wlc->hw;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- if (!wlc_hw->up)
- return;
-
- /* increment second count */
- wlc_hw->now++;
-
- /* Check for FIFO error interrupts */
- brcms_b_fifoerrors(wlc_hw);
-
- /* make sure RX dma has buffers */
- dma_rxfill(wlc->hw->di[RX_FIFO]);
-
- wlc_phy_watchdog(wlc_hw->band->pi);
-}
-
-void
-brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, chanspec_t chanspec,
- bool mute, struct txpwr_limits *txpwr)
-{
- uint bandunit;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec);
-
- wlc_hw->chanspec = chanspec;
-
- /* Switch bands if necessary */
- if (NBANDS_HW(wlc_hw) > 1) {
- bandunit = CHSPEC_BANDUNIT(chanspec);
- if (wlc_hw->band->bandunit != bandunit) {
- /* brcms_b_setband disables other bandunit,
- * use light band switch if not up yet
- */
- if (wlc_hw->up) {
- wlc_phy_chanspec_radio_set(wlc_hw->
- bandstate[bandunit]->
- pi, chanspec);
- brcms_b_setband(wlc_hw, bandunit, chanspec);
- } else {
- brcms_c_setxband(wlc_hw, bandunit);
- }
- }
- }
-
- wlc_phy_initcal_enable(wlc_hw->band->pi, !mute);
-
- if (!wlc_hw->up) {
- if (wlc_hw->clk)
- wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr,
- chanspec);
- wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
- } else {
- wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec);
- wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
-
- /* Update muting of the channel */
- brcms_b_mute(wlc_hw, mute, 0);
- }
-}
-
-int brcms_b_state_get(struct brcms_hardware *wlc_hw,
- struct brcms_b_state *state)
-{
- state->machwcap = wlc_hw->machwcap;
-
- return 0;
-}
-
-static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
-{
- uint i;
- char name[8];
- /* ucode host flag 2 needed for pio mode, independent of band and fifo */
- u16 pio_mhf2 = 0;
- struct brcms_hardware *wlc_hw = wlc->hw;
- uint unit = wlc_hw->unit;
- struct brcms_tunables *tune = wlc->pub->tunables;
- struct wiphy *wiphy = wlc->wiphy;
-
- /* name and offsets for dma_attach */
- snprintf(name, sizeof(name), "wl%d", unit);
-
- if (wlc_hw->di[0] == 0) { /* Init FIFOs */
- uint addrwidth;
- int dma_attach_err = 0;
- /* Find out the DMA addressing capability and let OS know
- * All the channels within one DMA core have 'common-minimum' same
- * capability
- */
- addrwidth =
- dma_addrwidth(wlc_hw->sih, DMAREG(wlc_hw, DMA_TX, 0));
-
- if (!wl_alloc_dma_resources(wlc_hw->wlc->wl, addrwidth)) {
- wiphy_err(wiphy, "wl%d: wlc_attach: alloc_dma_"
- "resources failed\n", unit);
- return false;
- }
-
- /*
- * FIFO 0
- * TX: TX_AC_BK_FIFO (TX AC Background data packets)
- * RX: RX_FIFO (RX data packets)
- */
- wlc_hw->di[0] = dma_attach(name, wlc_hw->sih,
- (wme ? DMAREG(wlc_hw, DMA_TX, 0) :
- NULL), DMAREG(wlc_hw, DMA_RX, 0),
- (wme ? tune->ntxd : 0), tune->nrxd,
- tune->rxbufsz, -1, tune->nrxbufpost,
- BRCMS_HWRXOFF, &brcm_msg_level);
- dma_attach_err |= (NULL == wlc_hw->di[0]);
-
- /*
- * FIFO 1
- * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets)
- * (legacy) TX_DATA_FIFO (TX data packets)
- * RX: UNUSED
- */
- wlc_hw->di[1] = dma_attach(name, wlc_hw->sih,
- DMAREG(wlc_hw, DMA_TX, 1), NULL,
- tune->ntxd, 0, 0, -1, 0, 0,
- &brcm_msg_level);
- dma_attach_err |= (NULL == wlc_hw->di[1]);
-
- /*
- * FIFO 2
- * TX: TX_AC_VI_FIFO (TX AC Video data packets)
- * RX: UNUSED
- */
- wlc_hw->di[2] = dma_attach(name, wlc_hw->sih,
- DMAREG(wlc_hw, DMA_TX, 2), NULL,
- tune->ntxd, 0, 0, -1, 0, 0,
- &brcm_msg_level);
- dma_attach_err |= (NULL == wlc_hw->di[2]);
- /*
- * FIFO 3
- * TX: TX_AC_VO_FIFO (TX AC Voice data packets)
- * (legacy) TX_CTL_FIFO (TX control & mgmt packets)
- */
- wlc_hw->di[3] = dma_attach(name, wlc_hw->sih,
- DMAREG(wlc_hw, DMA_TX, 3),
- NULL, tune->ntxd, 0, 0, -1,
- 0, 0, &brcm_msg_level);
- dma_attach_err |= (NULL == wlc_hw->di[3]);
-/* Cleaner to leave this as if with AP defined */
-
- if (dma_attach_err) {
- wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed"
- "\n", unit);
- return false;
- }
-
- /* get pointer to dma engine tx flow control variable */
- for (i = 0; i < NFIFO; i++)
- if (wlc_hw->di[i])
- wlc_hw->txavail[i] =
- (uint *) dma_getvar(wlc_hw->di[i],
- "&txavail");
- }
-
- /* initial ucode host flags */
- brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2);
-
- return true;
-}
-
-static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw)
-{
- uint j;
-
- for (j = 0; j < NFIFO; j++) {
- if (wlc_hw->di[j]) {
- dma_detach(wlc_hw->di[j]);
- wlc_hw->di[j] = NULL;
- }
- }
-}
-
-/* low level attach
- * run backplane attach, init nvram
- * run phy attach
- * initialize software state for each core and band
- * put the whole chip in reset(driver down state), no clock
- */
-int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, uint unit,
- bool piomode, void *regsva, uint bustype, void *btparam)
-{
- struct brcms_hardware *wlc_hw;
- d11regs_t *regs;
- char *macaddr = NULL;
- char *vars;
- uint err = 0;
- uint j;
- bool wme = false;
- struct shared_phy_params sha_params;
- struct wiphy *wiphy = wlc->wiphy;
-
- BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor,
- device);
-
- wme = true;
-
- wlc_hw = wlc->hw;
- wlc_hw->wlc = wlc;
- wlc_hw->unit = unit;
- wlc_hw->band = wlc_hw->bandstate[0];
- wlc_hw->_piomode = piomode;
-
- /* populate struct brcms_hardware with default values */
- brcms_b_info_init(wlc_hw);
-
- /*
- * Do the hardware portion of the attach.
- * Also initialize software state that depends on the particular hardware
- * we are running.
- */
- wlc_hw->sih = ai_attach(regsva, bustype, btparam,
- &wlc_hw->vars, &wlc_hw->vars_size);
- if (wlc_hw->sih == NULL) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n",
- unit);
- err = 11;
- goto fail;
- }
- vars = wlc_hw->vars;
-
- /*
- * Get vendid/devid nvram overwrites, which could be different
- * than those the BIOS recognizes for devices on PCMCIA_BUS,
- * SDIO_BUS, and SROMless devices on PCI_BUS.
- */
-#ifdef BCMBUSTYPE
- bustype = BCMBUSTYPE;
-#endif
- if (bustype != SI_BUS) {
- char *var;
-
- var = getvar(vars, "vendid");
- if (var) {
- vendor = (u16) simple_strtoul(var, NULL, 0);
- wiphy_err(wiphy, "Overriding vendor id = 0x%x\n",
- vendor);
- }
- var = getvar(vars, "devid");
- if (var) {
- u16 devid = (u16) simple_strtoul(var, NULL, 0);
- if (devid != 0xffff) {
- device = devid;
- wiphy_err(wiphy, "Overriding device id = 0x%x"
- "\n", device);
- }
- }
-
- /* verify again the device is supported */
- if (!brcms_c_chipmatch(vendor, device)) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported "
- "vendor/device (0x%x/0x%x)\n",
- unit, vendor, device);
- err = 12;
- goto fail;
- }
- }
-
- wlc_hw->vendorid = vendor;
- wlc_hw->deviceid = device;
-
- /* set bar0 window to point at D11 core */
- wlc_hw->regs = (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
- wlc_hw->corerev = ai_corerev(wlc_hw->sih);
-
- regs = wlc_hw->regs;
-
- wlc->regs = wlc_hw->regs;
-
- /* validate chip, chiprev and corerev */
- if (!brcms_c_isgoodchip(wlc_hw)) {
- err = 13;
- goto fail;
- }
-
- /* initialize power control registers */
- ai_clkctl_init(wlc_hw->sih);
-
- /* request fastclock and force fastclock for the rest of attach
- * bring the d11 core out of reset.
- * For PMU chips, the first wlc_clkctl_clk is no-op since core-clk is still false;
- * But it will be called again inside wlc_corereset, after d11 is out of reset.
- */
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
- brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
-
- if (!brcms_b_validate_chip_access(wlc_hw)) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access "
- "failed\n", unit);
- err = 14;
- goto fail;
- }
-
- /* get the board rev, used just below */
- j = getintvar(vars, "boardrev");
- /* promote srom boardrev of 0xFF to 1 */
- if (j == BOARDREV_PROMOTABLE)
- j = BOARDREV_PROMOTED;
- wlc_hw->boardrev = (u16) j;
- if (!brcms_c_validboardtype(wlc_hw)) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom "
- "board type (0x%x)" " or revision level (0x%x)\n",
- unit, wlc_hw->sih->boardtype, wlc_hw->boardrev);
- err = 15;
- goto fail;
- }
- wlc_hw->sromrev = (u8) getintvar(vars, "sromrev");
- wlc_hw->boardflags = (u32) getintvar(vars, "boardflags");
- wlc_hw->boardflags2 = (u32) getintvar(vars, "boardflags2");
-
- if (wlc_hw->boardflags & BFL_NOPLLDOWN)
- brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED);
-
- if ((wlc_hw->sih->bustype == PCI_BUS)
- && (ai_pci_war16165(wlc_hw->sih)))
- wlc->war16165 = true;
-
- /* check device id(srom, nvram etc.) to set bands */
- if (wlc_hw->deviceid == BCM43224_D11N_ID ||
- wlc_hw->deviceid == BCM43224_D11N_ID_VEN1) {
- /* Dualband boards */
- wlc_hw->_nbands = 2;
- } else
- wlc_hw->_nbands = 1;
-
- if ((wlc_hw->sih->chip == BCM43225_CHIP_ID))
- wlc_hw->_nbands = 1;
-
- /* BMAC_NOTE: remove init of pub values when brcms_c_attach()
- * unconditionally does the init of these values
- */
- wlc->vendorid = wlc_hw->vendorid;
- wlc->deviceid = wlc_hw->deviceid;
- wlc->pub->sih = wlc_hw->sih;
- wlc->pub->corerev = wlc_hw->corerev;
- wlc->pub->sromrev = wlc_hw->sromrev;
- wlc->pub->boardrev = wlc_hw->boardrev;
- wlc->pub->boardflags = wlc_hw->boardflags;
- wlc->pub->boardflags2 = wlc_hw->boardflags2;
- wlc->pub->_nbands = wlc_hw->_nbands;
-
- wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc);
-
- if (wlc_hw->physhim == NULL) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach "
- "failed\n", unit);
- err = 25;
- goto fail;
- }
-
- /* pass all the parameters to wlc_phy_shared_attach in one struct */
- sha_params.sih = wlc_hw->sih;
- sha_params.physhim = wlc_hw->physhim;
- sha_params.unit = unit;
- sha_params.corerev = wlc_hw->corerev;
- sha_params.vars = vars;
- sha_params.vid = wlc_hw->vendorid;
- sha_params.did = wlc_hw->deviceid;
- sha_params.chip = wlc_hw->sih->chip;
- sha_params.chiprev = wlc_hw->sih->chiprev;
- sha_params.chippkg = wlc_hw->sih->chippkg;
- sha_params.sromrev = wlc_hw->sromrev;
- sha_params.boardtype = wlc_hw->sih->boardtype;
- sha_params.boardrev = wlc_hw->boardrev;
- sha_params.boardvendor = wlc_hw->sih->boardvendor;
- sha_params.boardflags = wlc_hw->boardflags;
- sha_params.boardflags2 = wlc_hw->boardflags2;
- sha_params.bustype = wlc_hw->sih->bustype;
- sha_params.buscorerev = wlc_hw->sih->buscorerev;
-
- /* alloc and save pointer to shared phy state area */
- wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
- if (!wlc_hw->phy_sh) {
- err = 16;
- goto fail;
- }
-
- /* initialize software state for each core and band */
- for (j = 0; j < NBANDS_HW(wlc_hw); j++) {
- /*
- * band0 is always 2.4Ghz
- * band1, if present, is 5Ghz
- */
-
- /* So if this is a single band 11a card, use band 1 */
- if (IS_SINGLEBAND_5G(wlc_hw->deviceid))
- j = BAND_5G_INDEX;
-
- brcms_c_setxband(wlc_hw, j);
-
- wlc_hw->band->bandunit = j;
- wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
- wlc->band->bandunit = j;
- wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
- wlc->core->coreidx = ai_coreidx(wlc_hw->sih);
-
- wlc_hw->machwcap = R_REG(&regs->machwcap);
- wlc_hw->machwcap_backup = wlc_hw->machwcap;
-
- /* init tx fifo size */
- wlc_hw->xmtfifo_sz =
- xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
-
- /* Get a phy for this band */
- wlc_hw->band->pi = wlc_phy_attach(wlc_hw->phy_sh,
- (void *)regs, brcms_b_bandtype(wlc_hw), vars,
- wlc->wiphy);
- if (wlc_hw->band->pi == NULL) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_"
- "attach failed\n", unit);
- err = 17;
- goto fail;
- }
-
- wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap);
-
- wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype,
- &wlc_hw->band->phyrev,
- &wlc_hw->band->radioid,
- &wlc_hw->band->radiorev);
- wlc_hw->band->abgphy_encore =
- wlc_phy_get_encore(wlc_hw->band->pi);
- wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi);
- wlc_hw->band->core_flags =
- wlc_phy_get_coreflags(wlc_hw->band->pi);
-
- /* verify good phy_type & supported phy revision */
- if (BRCMS_ISNPHY(wlc_hw->band)) {
- if (NCONF_HAS(wlc_hw->band->phyrev))
- goto good_phy;
- else
- goto bad_phy;
- } else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
- if (LCNCONF_HAS(wlc_hw->band->phyrev))
- goto good_phy;
- else
- goto bad_phy;
- } else {
- bad_phy:
- wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported "
- "phy type/rev (%d/%d)\n", unit,
- wlc_hw->band->phytype, wlc_hw->band->phyrev);
- err = 18;
- goto fail;
- }
-
- good_phy:
- /* BMAC_NOTE: wlc->band->pi should not be set below and should be done in the
- * high level attach. However we can not make that change until all low level access
- * is changed to wlc_hw->band->pi. Instead do the wlc->band->pi init below, keeping
- * wlc_hw->band->pi as well for incremental update of low level fns, and cut over
- * low only init when all fns updated.
- */
- wlc->band->pi = wlc_hw->band->pi;
- wlc->band->phytype = wlc_hw->band->phytype;
- wlc->band->phyrev = wlc_hw->band->phyrev;
- wlc->band->radioid = wlc_hw->band->radioid;
- wlc->band->radiorev = wlc_hw->band->radiorev;
-
- /* default contention windows size limits */
- wlc_hw->band->CWmin = APHY_CWMIN;
- wlc_hw->band->CWmax = PHY_CWMAX;
-
- if (!brcms_b_attach_dmapio(wlc, j, wme)) {
- err = 19;
- goto fail;
- }
- }
-
- /* disable core to match driver "down" state */
- brcms_c_coredisable(wlc_hw);
-
- /* Match driver "down" state */
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_down(wlc_hw->sih);
-
- /* register sb interrupt callback functions */
- ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff,
- (void *)brcms_c_wlintrsrestore, NULL, wlc);
-
- /* turn off pll and xtal to match driver "down" state */
- brcms_b_xtal(wlc_hw, OFF);
-
- /* *********************************************************************
- * The hardware is in the DOWN state at this point. D11 core
- * or cores are in reset with clocks off, and the board PLLs
- * are off if possible.
- *
- * Beyond this point, wlc->sbclk == false and chip registers
- * should not be touched.
- *********************************************************************
- */
-
- /* init etheraddr state variables */
- macaddr = brcms_c_get_macaddr(wlc_hw);
- if (macaddr == NULL) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n",
- unit);
- err = 21;
- goto fail;
- }
- brcmu_ether_atoe(macaddr, wlc_hw->etheraddr);
- if (is_broadcast_ether_addr(wlc_hw->etheraddr) ||
- is_zero_ether_addr(wlc_hw->etheraddr)) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n",
- unit, macaddr);
- err = 22;
- goto fail;
- }
-
- BCMMSG(wlc->wiphy,
- "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
- wlc_hw->deviceid, wlc_hw->_nbands,
- wlc_hw->sih->boardtype, macaddr);
-
- return err;
-
- fail:
- wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit,
- err);
- return err;
-}
-
-/*
- * Initialize brcms_c_info default values ...
- * may get overrides later in this function
- * BMAC_NOTES, move low out and resolve the dangling ones
- */
-static void brcms_b_info_init(struct brcms_hardware *wlc_hw)
-{
- struct brcms_c_info *wlc = wlc_hw->wlc;
-
- /* set default sw macintmask value */
- wlc->defmacintmask = DEF_MACINTMASK;
-
- /* various 802.11g modes */
- wlc_hw->shortslot = false;
-
- wlc_hw->SFBL = RETRY_SHORT_FB;
- wlc_hw->LFBL = RETRY_LONG_FB;
-
- /* default mac retry limits */
- wlc_hw->SRL = RETRY_SHORT_DEF;
- wlc_hw->LRL = RETRY_LONG_DEF;
- wlc_hw->chanspec = CH20MHZ_CHSPEC(1);
-}
-
-/*
- * low level detach
- */
-int brcms_b_detach(struct brcms_c_info *wlc)
-{
- uint i;
- struct brcms_hw_band *band;
- struct brcms_hardware *wlc_hw = wlc->hw;
- int callbacks;
-
- callbacks = 0;
-
- if (wlc_hw->sih) {
- /* detach interrupt sync mechanism since interrupt is disabled and per-port
- * interrupt object may has been freed. this must be done before sb core switch
- */
- ai_deregister_intr_callback(wlc_hw->sih);
-
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_sleep(wlc_hw->sih);
- }
-
- brcms_b_detach_dmapio(wlc_hw);
-
- band = wlc_hw->band;
- for (i = 0; i < NBANDS_HW(wlc_hw); i++) {
- if (band->pi) {
- /* Detach this band's phy */
- wlc_phy_detach(band->pi);
- band->pi = NULL;
- }
- band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)];
- }
-
- /* Free shared phy state */
- kfree(wlc_hw->phy_sh);
-
- wlc_phy_shim_detach(wlc_hw->physhim);
-
- /* free vars */
- kfree(wlc_hw->vars);
- wlc_hw->vars = NULL;
-
- if (wlc_hw->sih) {
- ai_detach(wlc_hw->sih);
- wlc_hw->sih = NULL;
- }
-
- return callbacks;
-
-}
-
-void brcms_b_reset(struct brcms_hardware *wlc_hw)
-{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- /* reset the core */
- if (!DEVICEREMOVED(wlc_hw->wlc))
- brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
-
- /* purge the dma rings */
- brcms_c_flushqueues(wlc_hw->wlc);
-
- brcms_c_reset_bmac_done(wlc_hw->wlc);
-}
-
-void
-brcms_b_init(struct brcms_hardware *wlc_hw, chanspec_t chanspec,
- bool mute) {
- u32 macintmask;
- bool fastclk;
- struct brcms_c_info *wlc = wlc_hw->wlc;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- /* request FAST clock if not on */
- fastclk = wlc_hw->forcefastclk;
- if (!fastclk)
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- /* disable interrupts */
- macintmask = brcms_intrsoff(wlc->wl);
-
- /* set up the specified band and chanspec */
- brcms_c_setxband(wlc_hw, CHSPEC_BANDUNIT(chanspec));
- wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
-
- /* do one-time phy inits and calibration */
- wlc_phy_cal_init(wlc_hw->band->pi);
-
- /* core-specific initialization */
- brcms_b_coreinit(wlc);
-
- /* suspend the tx fifos and mute the phy for preism cac time */
- if (mute)
- brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM);
-
- /* band-specific inits */
- brcms_b_bsinit(wlc, chanspec);
-
- /* restore macintmask */
- brcms_intrsrestore(wlc->wl, macintmask);
-
- /* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac
- * is suspended and brcms_c_enable_mac() will clear this override bit.
- */
- mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
-
- /*
- * initialize mac_suspend_depth to 1 to match ucode initial suspended state
- */
- wlc_hw->mac_suspend_depth = 1;
-
- /* restore the clk */
- if (!fastclk)
- brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
-{
- uint coremask;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- /*
- * Enable pll and xtal, initialize the power control registers,
- * and force fastclock for the remainder of brcms_c_up().
- */
- brcms_b_xtal(wlc_hw, ON);
- ai_clkctl_init(wlc_hw->sih);
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- /*
- * Configure pci/pcmcia here instead of in brcms_c_attach()
- * to allow mfg hotswap: down, hotswap (chip power cycle), up.
- */
- coremask = (1 << wlc_hw->wlc->core->coreidx);
-
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_setup(wlc_hw->sih, coremask);
-
- /*
- * Need to read the hwradio status here to cover the case where the system
- * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
- */
- if (brcms_b_radio_read_hwdisabled(wlc_hw)) {
- /* put SB PCI in down state again */
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_down(wlc_hw->sih);
- brcms_b_xtal(wlc_hw, OFF);
- return -ENOMEDIUM;
- }
-
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_up(wlc_hw->sih);
-
- /* reset the d11 core */
- brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
-
- return 0;
-}
-
-int brcms_b_up_finish(struct brcms_hardware *wlc_hw)
-{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- wlc_hw->up = true;
- wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
-
- /* FULLY enable dynamic power control and d11 core interrupt */
- brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
- brcms_intrson(wlc_hw->wlc->wl);
- return 0;
-}
-
-int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw)
-{
- bool dev_gone;
- uint callbacks = 0;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- if (!wlc_hw->up)
- return callbacks;
-
- dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
- /* disable interrupts */
- if (dev_gone)
- wlc_hw->wlc->macintmask = 0;
- else {
- /* now disable interrupts */
- brcms_intrsoff(wlc_hw->wlc->wl);
-
- /* ensure we're running on the pll clock again */
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
- }
- /* down phy at the last of this stage */
- callbacks += wlc_phy_down(wlc_hw->band->pi);
-
- return callbacks;
-}
-
-int brcms_b_down_finish(struct brcms_hardware *wlc_hw)
-{
- uint callbacks = 0;
- bool dev_gone;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- if (!wlc_hw->up)
- return callbacks;
-
- wlc_hw->up = false;
- wlc_phy_hw_state_upd(wlc_hw->band->pi, false);
-
- dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
- if (dev_gone) {
- wlc_hw->sbclk = false;
- wlc_hw->clk = false;
- wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
-
- /* reclaim any posted packets */
- brcms_c_flushqueues(wlc_hw->wlc);
- } else {
-
- /* Reset and disable the core */
- if (ai_iscoreup(wlc_hw->sih)) {
- if (R_REG(&wlc_hw->regs->maccontrol) &
- MCTL_EN_MAC)
- brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
- callbacks += brcms_reset(wlc_hw->wlc->wl);
- brcms_c_coredisable(wlc_hw);
- }
-
- /* turn off primary xtal and pll */
- if (!wlc_hw->noreset) {
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_down(wlc_hw->sih);
- brcms_b_xtal(wlc_hw, OFF);
- }
- }
-
- return callbacks;
-}
-
-void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw)
-{
- /* delay before first read of ucode state */
- udelay(40);
-
- /* wait until ucode is no longer asleep */
- SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) ==
- DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
-}
-
-void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw, u8 *ea)
-{
- memcpy(ea, wlc_hw->etheraddr, ETH_ALEN);
-}
-
-static int brcms_b_bandtype(struct brcms_hardware *wlc_hw)
-{
- return wlc_hw->band->bandtype;
-}
-
-/* control chip clock to save power, enable dynamic clock or force fast clock */
-static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
-{
- if (PMUCTL_ENAB(wlc_hw->sih)) {
- /* new chips with PMU, CCS_FORCEHT will distribute the HT clock on backplane,
- * but mac core will still run on ALP(not HT) when it enters powersave mode,
- * which means the FCA bit may not be set.
- * should wakeup mac if driver wants it to run on HT.
- */
-
- if (wlc_hw->clk) {
- if (mode == CLK_FAST) {
- OR_REG(&wlc_hw->regs->clk_ctl_st,
- CCS_FORCEHT);
-
- udelay(64);
-
- SPINWAIT(((R_REG
- (&wlc_hw->regs->
- clk_ctl_st) & CCS_HTAVAIL) == 0),
- PMU_MAX_TRANSITION_DLY);
- WARN_ON(!(R_REG
- (&wlc_hw->regs->
- clk_ctl_st) & CCS_HTAVAIL));
- } else {
- if ((wlc_hw->sih->pmurev == 0) &&
- (R_REG
- (&wlc_hw->regs->
- clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ)))
- SPINWAIT(((R_REG
- (&wlc_hw->regs->
- clk_ctl_st) & CCS_HTAVAIL)
- == 0),
- PMU_MAX_TRANSITION_DLY);
- AND_REG(&wlc_hw->regs->clk_ctl_st,
- ~CCS_FORCEHT);
- }
- }
- wlc_hw->forcefastclk = (mode == CLK_FAST);
- } else {
-
- /* old chips w/o PMU, force HT through cc,
- * then use FCA to verify mac is running fast clock
- */
-
- wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode);
-
- /* check fast clock is available (if core is not in reset) */
- if (wlc_hw->forcefastclk && wlc_hw->clk)
- WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) &
- SISF_FCLKA));
-
- /* keep the ucode wake bit on if forcefastclk is on
- * since we do not want ucode to put us back to slow clock
- * when it dozes for PM mode.
- * Code below matches the wake override bit with current forcefastclk state
- * Only setting bit in wake_override instead of waking ucode immediately
- * since old code (wlc.c 1.4499) had this behavior. Older code set
- * wlc->forcefastclk but only had the wake happen if the wakup_ucode work
- * (protected by an up check) was executed just below.
- */
- if (wlc_hw->forcefastclk)
- mboolset(wlc_hw->wake_override,
- BRCMS_WAKE_OVERRIDE_FORCEFAST);
- else
- mboolclr(wlc_hw->wake_override,
- BRCMS_WAKE_OVERRIDE_FORCEFAST);
- }
-}
-
-/* set initial host flags value */
-static void
-brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
-
- memset(mhfs, 0, MHFMAX * sizeof(u16));
-
- mhfs[MHF2] |= mhf2_init;
-
- /* prohibit use of slowclock on multifunction boards */
- if (wlc_hw->boardflags & BFL_NOPLLDOWN)
- mhfs[MHF1] |= MHF1_FORCEFASTCLK;
-
- if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) {
- mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR;
- mhfs[MHF1] |= MHF1_IQSWAP_WAR;
- }
-}
-
-/* set or clear ucode host flag bits
- * it has an optimization for no-change write
- * it only writes through shared memory when the core has clock;
- * pre-CLK changes should use wlc_write_mhf to get around the optimization
- *
- *
- * bands values are: BRCM_BAND_AUTO <--- Current band only
- * BRCM_BAND_5G <--- 5G band only
- * BRCM_BAND_2G <--- 2G band only
- * BRCM_BAND_ALL <--- All bands
- */
-void
-brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val,
- int bands)
-{
- u16 save;
- u16 addr[MHFMAX] = {
- M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
- M_HOST_FLAGS5
- };
- struct brcms_hw_band *band;
-
- if ((val & ~mask) || idx >= MHFMAX)
- return; /* error condition */
-
- switch (bands) {
- /* Current band only or all bands,
- * then set the band to current band
- */
- case BRCM_BAND_AUTO:
- case BRCM_BAND_ALL:
- band = wlc_hw->band;
- break;
- case BRCM_BAND_5G:
- band = wlc_hw->bandstate[BAND_5G_INDEX];
- break;
- case BRCM_BAND_2G:
- band = wlc_hw->bandstate[BAND_2G_INDEX];
- break;
- default:
- band = NULL; /* error condition */
- }
-
- if (band) {
- save = band->mhfs[idx];
- band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
-
- /* optimization: only write through if changed, and
- * changed band is the current band
- */
- if (wlc_hw->clk && (band->mhfs[idx] != save)
- && (band == wlc_hw->band))
- brcms_b_write_shm(wlc_hw, addr[idx],
- (u16) band->mhfs[idx]);
- }
-
- if (bands == BRCM_BAND_ALL) {
- wlc_hw->bandstate[0]->mhfs[idx] =
- (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val;
- wlc_hw->bandstate[1]->mhfs[idx] =
- (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val;
- }
-}
-
-u16 brcms_b_mhf_get(struct brcms_hardware *wlc_hw, u8 idx, int bands)
-{
- struct brcms_hw_band *band;
-
- if (idx >= MHFMAX)
- return 0; /* error condition */
- switch (bands) {
- case BRCM_BAND_AUTO:
- band = wlc_hw->band;
- break;
- case BRCM_BAND_5G:
- band = wlc_hw->bandstate[BAND_5G_INDEX];
- break;
- case BRCM_BAND_2G:
- band = wlc_hw->bandstate[BAND_2G_INDEX];
- break;
- default:
- band = NULL; /* error condition */
- }
-
- if (!band)
- return 0;
-
- return band->mhfs[idx];
-}
-
-static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs)
-{
- u8 idx;
- u16 addr[] = {
- M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
- M_HOST_FLAGS5
- };
-
- for (idx = 0; idx < MHFMAX; idx++) {
- brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]);
- }
-}
-
-/* set the maccontrol register to desired reset state and
- * initialize the sw cache of the register
- */
-static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw)
-{
- /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
- wlc_hw->maccontrol = 0;
- wlc_hw->suspended_fifos = 0;
- wlc_hw->wake_override = 0;
- wlc_hw->mute_override = 0;
- brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
-}
-
-/* set or clear maccontrol bits */
-void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val)
-{
- u32 maccontrol;
- u32 new_maccontrol;
-
- if (val & ~mask)
- return; /* error condition */
- maccontrol = wlc_hw->maccontrol;
- new_maccontrol = (maccontrol & ~mask) | val;
-
- /* if the new maccontrol value is the same as the old, nothing to do */
- if (new_maccontrol == maccontrol)
- return;
-
- /* something changed, cache the new value */
- wlc_hw->maccontrol = new_maccontrol;
-
- /* write the new values with overrides applied */
- brcms_c_mctrl_write(wlc_hw);
-}
-
-/* write the software state of maccontrol and overrides to the maccontrol register */
-static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw)
-{
- u32 maccontrol = wlc_hw->maccontrol;
-
- /* OR in the wake bit if overridden */
- if (wlc_hw->wake_override)
- maccontrol |= MCTL_WAKE;
-
- /* set AP and INFRA bits for mute if needed */
- if (wlc_hw->mute_override) {
- maccontrol &= ~(MCTL_AP);
- maccontrol |= MCTL_INFRA;
- }
-
- W_REG(&wlc_hw->regs->maccontrol, maccontrol);
-}
-
-void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
- u32 override_bit)
-{
- if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) {
- mboolset(wlc_hw->wake_override, override_bit);
- return;
- }
-
- mboolset(wlc_hw->wake_override, override_bit);
-
- brcms_c_mctrl_write(wlc_hw);
- brcms_b_wait_for_wake(wlc_hw);
-
- return;
-}
-
-void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
- u32 override_bit)
-{
- mboolclr(wlc_hw->wake_override, override_bit);
-
- if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE))
- return;
-
- brcms_c_mctrl_write(wlc_hw);
-
- return;
-}
-
-/* When driver needs ucode to stop beaconing, it has to make sure that
- * MCTL_AP is clear and MCTL_INFRA is set
- * Mode MCTL_AP MCTL_INFRA
- * AP 1 1
- * STA 0 1 <--- This will ensure no beacons
- * IBSS 0 0
- */
-static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw)
-{
- wlc_hw->mute_override = 1;
-
- /* if maccontrol already has AP == 0 and INFRA == 1 without this
- * override, then there is no change to write
- */
- if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
- return;
-
- brcms_c_mctrl_write(wlc_hw);
-
- return;
-}
-
-/* Clear the override on AP and INFRA bits */
-static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw)
-{
- if (wlc_hw->mute_override == 0)
- return;
-
- wlc_hw->mute_override = 0;
-
- /* if maccontrol already has AP == 0 and INFRA == 1 without this
- * override, then there is no change to write
- */
- if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
- return;
-
- brcms_c_mctrl_write(wlc_hw);
-}
-
-/*
- * Write a MAC address to the given match reg offset in the RXE match engine.
- */
-void
-brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset,
- const u8 *addr)
-{
- d11regs_t *regs;
- u16 mac_l;
- u16 mac_m;
- u16 mac_h;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n",
- wlc_hw->unit);
-
- regs = wlc_hw->regs;
- mac_l = addr[0] | (addr[1] << 8);
- mac_m = addr[2] | (addr[3] << 8);
- mac_h = addr[4] | (addr[5] << 8);
-
- /* enter the MAC addr into the RXE match registers */
- W_REG(&regs->rcm_ctl, RCM_INC_DATA | match_reg_offset);
- W_REG(&regs->rcm_mat_data, mac_l);
- W_REG(&regs->rcm_mat_data, mac_m);
- W_REG(&regs->rcm_mat_data, mac_h);
-
-}
-
-void
-brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len,
- void *buf)
-{
- d11regs_t *regs;
- u32 word;
- bool be_bit;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- regs = wlc_hw->regs;
- W_REG(&regs->tplatewrptr, offset);
-
- /* if MCTL_BIGEND bit set in mac control register,
- * the chip swaps data in fifo, as well as data in
- * template ram
- */
- be_bit = (R_REG(&regs->maccontrol) & MCTL_BIGEND) != 0;
-
- while (len > 0) {
- memcpy(&word, buf, sizeof(u32));
-
- if (be_bit)
- word = cpu_to_be32(word);
- else
- word = cpu_to_le32(word);
-
- W_REG(&regs->tplatewrdata, word);
-
- buf = (u8 *) buf + sizeof(u32);
- len -= sizeof(u32);
- }
-}
-
-void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin)
-{
- wlc_hw->band->CWmin = newmin;
-
- W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN);
- (void)R_REG(&wlc_hw->regs->objaddr);
- W_REG(&wlc_hw->regs->objdata, newmin);
-}
-
-void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax)
-{
- wlc_hw->band->CWmax = newmax;
-
- W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX);
- (void)R_REG(&wlc_hw->regs->objaddr);
- W_REG(&wlc_hw->regs->objdata, newmax);
-}
-
-void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw)
-{
- bool fastclk;
-
- /* request FAST clock if not on */
- fastclk = wlc_hw->forcefastclk;
- if (!fastclk)
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
-
- brcms_b_phy_reset(wlc_hw);
- wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi));
-
- /* restore the clk */
- if (!fastclk)
- brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-static void
-brcms_c_write_hw_bcntemplate0(struct brcms_hardware *wlc_hw, void *bcn,
- int len)
-{
- d11regs_t *regs = wlc_hw->regs;
-
- brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, (len + 3) & ~3,
- bcn);
- /* write beacon length to SCR */
- brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
- /* mark beacon0 valid */
- OR_REG(&regs->maccommand, MCMD_BCN0VLD);
-}
-
-static void
-brcms_c_write_hw_bcntemplate1(struct brcms_hardware *wlc_hw, void *bcn,
- int len)
-{
- d11regs_t *regs = wlc_hw->regs;
-
- brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, (len + 3) & ~3,
- bcn);
- /* write beacon length to SCR */
- brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
- /* mark beacon1 valid */
- OR_REG(&regs->maccommand, MCMD_BCN1VLD);
-}
-
-/* mac is assumed to be suspended at this point */
-void
-brcms_b_write_hw_bcntemplates(struct brcms_hardware *wlc_hw, void *bcn,
- int len, bool both)
-{
- d11regs_t *regs = wlc_hw->regs;
-
- if (both) {
- brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len);
- brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len);
- } else {
- /* bcn 0 */
- if (!(R_REG(&regs->maccommand) & MCMD_BCN0VLD))
- brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len);
- /* bcn 1 */
- else if (!
- (R_REG(&regs->maccommand) & MCMD_BCN1VLD))
- brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len);
- }
-}
-
-static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw)
-{
- u16 v;
- struct brcms_c_info *wlc = wlc_hw->wlc;
- /* update SYNTHPU_DLY */
-
- if (BRCMS_ISLCNPHY(wlc->band)) {
- v = SYNTHPU_DLY_LPPHY_US;
- } else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) {
- v = SYNTHPU_DLY_NPHY_US;
- } else {
- v = SYNTHPU_DLY_BPHY_US;
- }
-
- brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v);
-}
-
-/* band-specific init */
-static void
-brcms_b_bsinit(struct brcms_c_info *wlc, chanspec_t chanspec)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
-
- BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
- wlc_hw->band->bandunit);
-
- brcms_c_ucode_bsinit(wlc_hw);
-
- wlc_phy_init(wlc_hw->band->pi, chanspec);
-
- brcms_c_ucode_txant_set(wlc_hw);
-
- /* cwmin is band-specific, update hardware with value for current band */
- brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
- brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
-
- brcms_b_update_slot_timing(wlc_hw,
- BAND_5G(wlc_hw->band->
- bandtype) ? true : wlc_hw->
- shortslot);
-
- /* write phytype and phyvers */
- brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype);
- brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev);
-
- /* initialize the txphyctl1 rate table since shmem is shared between bands */
- brcms_upd_ofdm_pctl1_table(wlc_hw);
-
- brcms_b_upd_synthpu(wlc_hw);
-}
-
-static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
-{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk);
-
- wlc_hw->phyclk = clk;
-
- if (OFF == clk) { /* clear gmode bit, put phy into reset */
-
- ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE),
- (SICF_PRST | SICF_FGC));
- udelay(1);
- ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST);
- udelay(1);
-
- } else { /* take phy out of reset */
-
- ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC);
- udelay(1);
- ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0);
- udelay(1);
-
- }
-}
-
-/* Perform a soft reset of the PHY PLL */
-void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw)
-{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- ai_corereg(wlc_hw->sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_addr), ~0, 0);
- udelay(1);
- ai_corereg(wlc_hw->sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
- udelay(1);
- ai_corereg(wlc_hw->sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data), 0x4, 4);
- udelay(1);
- ai_corereg(wlc_hw->sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
- udelay(1);
-}
-
-/* light way to turn on phy clock without reset for NPHY only
- * refer to brcms_b_core_phy_clk for full version
- */
-void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk)
-{
- /* support(necessary for NPHY and HYPHY) only */
- if (!BRCMS_ISNPHY(wlc_hw->band))
- return;
-
- if (ON == clk)
- ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC);
- else
- ai_core_cflags(wlc_hw->sih, SICF_FGC, 0);
-
-}
-
-void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk)
-{
- if (ON == clk)
- ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE);
- else
- ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0);
-}
-
-void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
-{
- struct brcms_phy_pub *pih = wlc_hw->band->pi;
- u32 phy_bw_clkbits;
- bool phy_in_reset = false;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- if (pih == NULL)
- return;
-
- phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi);
-
- /* Specific reset sequence required for NPHY rev 3 and 4 */
- if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
- NREV_LE(wlc_hw->band->phyrev, 4)) {
- /* Set the PHY bandwidth */
- ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits);
-
- udelay(1);
-
- /* Perform a soft reset of the PHY PLL */
- brcms_b_core_phypll_reset(wlc_hw);
-
- /* reset the PHY */
- ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE),
- (SICF_PRST | SICF_PCLKE));
- phy_in_reset = true;
- } else {
-
- ai_core_cflags(wlc_hw->sih,
- (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
- (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
- }
-
- udelay(2);
- brcms_b_core_phy_clk(wlc_hw, ON);
-
- if (pih)
- wlc_phy_anacore(pih, ON);
-}
-
-/* switch to and initialize new band */
-static void
-brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
- chanspec_t chanspec) {
- struct brcms_c_info *wlc = wlc_hw->wlc;
- u32 macintmask;
-
- /* Enable the d11 core before accessing it */
- if (!ai_iscoreup(wlc_hw->sih)) {
- ai_core_reset(wlc_hw->sih, 0, 0);
- brcms_c_mctrl_reset(wlc_hw);
- }
-
- macintmask = brcms_c_setband_inact(wlc, bandunit);
-
- if (!wlc_hw->up)
- return;
-
- brcms_b_core_phy_clk(wlc_hw, ON);
-
- /* band-specific initializations */
- brcms_b_bsinit(wlc, chanspec);
-
- /*
- * If there are any pending software interrupt bits,
- * then replace these with a harmless nonzero value
- * so brcms_c_dpc() will re-enable interrupts when done.
- */
- if (wlc->macintstatus)
- wlc->macintstatus = MI_DMAINT;
-
- /* restore macintmask */
- brcms_intrsrestore(wlc->wl, macintmask);
-
- /* ucode should still be suspended.. */
- WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
-}
-
-/* low-level band switch utility routine */
-void brcms_c_setxband(struct brcms_hardware *wlc_hw,
- uint bandunit)
-{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
- bandunit);
-
- wlc_hw->band = wlc_hw->bandstate[bandunit];
-
- /* BMAC_NOTE: until we eliminate need for wlc->band refs in low level code */
- wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
-
- /* set gmode core flag */
- if (wlc_hw->sbclk && !wlc_hw->noreset) {
- ai_core_cflags(wlc_hw->sih, SICF_GMODE,
- ((bandunit == 0) ? SICF_GMODE : 0));
- }
-}
-
-static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw)
-{
-
- /* reject unsupported corerev */
- if (!VALID_COREREV(wlc_hw->corerev)) {
- wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n",
- wlc_hw->corerev);
- return false;
- }
-
- return true;
-}
-
-/* Validate some board info parameters */
-static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw)
-{
- uint boardrev = wlc_hw->boardrev;
-
- /* 4 bits each for board type, major, minor, and tiny version */
- uint brt = (boardrev & 0xf000) >> 12;
- uint b0 = (boardrev & 0xf00) >> 8;
- uint b1 = (boardrev & 0xf0) >> 4;
- uint b2 = boardrev & 0xf;
-
- /* voards from other vendors are always considered valid */
- if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM)
- return true;
-
- /* do some boardrev sanity checks when boardvendor is Broadcom */
- if (boardrev == 0)
- return false;
-
- if (boardrev <= 0xff)
- return true;
-
- if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9)
- || (b2 > 9))
- return false;
-
- return true;
-}
-
-static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw)
-{
- const char *varname = "macaddr";
- char *macaddr;
-
- /* If macaddr exists, use it (Sromrev4, CIS, ...). */
- macaddr = getvar(wlc_hw->vars, varname);
- if (macaddr != NULL)
- return macaddr;
-
- if (NBANDS_HW(wlc_hw) > 1)
- varname = "et1macaddr";
- else
- varname = "il0macaddr";
-
- macaddr = getvar(wlc_hw->vars, varname);
- if (macaddr == NULL) {
- wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr "
- "getvar(%s) not found\n", wlc_hw->unit, varname);
- }
-
- return macaddr;
-}
-
-/*
- * Return true if radio is disabled, otherwise false.
- * hw radio disable signal is an external pin, users activate it asynchronously
- * this function could be called when driver is down and w/o clock
- * it operates on different registers depending on corerev and boardflag.
- */
-bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
-{
- bool v, clk, xtal;
- u32 resetbits = 0, flags = 0;
-
- xtal = wlc_hw->sbclk;
- if (!xtal)
- brcms_b_xtal(wlc_hw, ON);
-
- /* may need to take core out of reset first */
- clk = wlc_hw->clk;
- if (!clk) {
- /*
- * mac no longer enables phyclk automatically when driver
- * accesses phyreg throughput mac. This can be skipped since
- * only mac reg is accessed below
- */
- flags |= SICF_PCLKE;
-
- /* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
- if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
- (wlc_hw->sih->chip == BCM43225_CHIP_ID))
- wlc_hw->regs =
- (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID,
- 0);
- ai_core_reset(wlc_hw->sih, flags, resetbits);
- brcms_c_mctrl_reset(wlc_hw);
- }
-
- v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0);
-
- /* put core back into reset */
- if (!clk)
- ai_core_disable(wlc_hw->sih, 0);
-
- if (!xtal)
- brcms_b_xtal(wlc_hw, OFF);
-
- return v;
-}
-
-/* Initialize just the hardware when coming out of POR or S3/S5 system states */
-void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
-{
- if (wlc_hw->wlc->pub->hw_up)
- return;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- /*
- * Enable pll and xtal, initialize the power control registers,
- * and force fastclock for the remainder of brcms_c_up().
- */
- brcms_b_xtal(wlc_hw, ON);
- ai_clkctl_init(wlc_hw->sih);
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- if (wlc_hw->sih->bustype == PCI_BUS) {
- ai_pci_fixcfg(wlc_hw->sih);
-
- /* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
- if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
- (wlc_hw->sih->chip == BCM43225_CHIP_ID))
- wlc_hw->regs =
- (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID,
- 0);
- }
-
- /* Inform phy that a POR reset has occurred so it does a complete phy init */
- wlc_phy_por_inform(wlc_hw->band->pi);
-
- wlc_hw->ucode_loaded = false;
- wlc_hw->wlc->pub->hw_up = true;
-
- if ((wlc_hw->boardflags & BFL_FEM)
- && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
- if (!
- (wlc_hw->boardrev >= 0x1250
- && (wlc_hw->boardflags & BFL_FEM_BT)))
- ai_epa_4313war(wlc_hw->sih);
- }
-}
-
-static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo)
-{
- struct dma_pub *di = wlc_hw->di[fifo];
- return dma_rxreset(di);
-}
-
-/* d11 core reset
- * ensure fask clock during reset
- * reset dma
- * reset d11(out of reset)
- * reset phy(out of reset)
- * clear software macintstatus for fresh new start
- * one testing hack wlc_hw->noreset will bypass the d11/phy reset
- */
-void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
-{
- d11regs_t *regs;
- uint i;
- bool fastclk;
- u32 resetbits = 0;
-
- if (flags == BRCMS_USE_COREFLAGS)
- flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- regs = wlc_hw->regs;
-
- /* request FAST clock if not on */
- fastclk = wlc_hw->forcefastclk;
- if (!fastclk)
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- /* reset the dma engines except first time thru */
- if (ai_iscoreup(wlc_hw->sih)) {
- for (i = 0; i < NFIFO; i++)
- if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) {
- wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: "
- "dma_txreset[%d]: cannot stop dma\n",
- wlc_hw->unit, __func__, i);
- }
-
- if ((wlc_hw->di[RX_FIFO])
- && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) {
- wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset"
- "[%d]: cannot stop dma\n",
- wlc_hw->unit, __func__, RX_FIFO);
- }
- }
- /* if noreset, just stop the psm and return */
- if (wlc_hw->noreset) {
- wlc_hw->wlc->macintstatus = 0; /* skip wl_dpc after down */
- brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0);
- return;
- }
-
- /*
- * mac no longer enables phyclk automatically when driver accesses
- * phyreg throughput mac, AND phy_reset is skipped at early stage when
- * band->pi is invalid. need to enable PHY CLK
- */
- flags |= SICF_PCLKE;
-
- /* reset the core
- * In chips with PMU, the fastclk request goes through d11 core reg 0x1e0, which
- * is cleared by the core_reset. have to re-request it.
- * This adds some delay and we can optimize it by also requesting fastclk through
- * chipcommon during this period if necessary. But that has to work coordinate
- * with other driver like mips/arm since they may touch chipcommon as well.
- */
- wlc_hw->clk = false;
- ai_core_reset(wlc_hw->sih, flags, resetbits);
- wlc_hw->clk = true;
- if (wlc_hw->band && wlc_hw->band->pi)
- wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
-
- brcms_c_mctrl_reset(wlc_hw);
-
- if (PMUCTL_ENAB(wlc_hw->sih))
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- brcms_b_phy_reset(wlc_hw);
-
- /* turn on PHY_PLL */
- brcms_b_core_phypll_ctl(wlc_hw, true);
-
- /* clear sw intstatus */
- wlc_hw->wlc->macintstatus = 0;
-
- /* restore the clk setting */
- if (!fastclk)
- brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-/* txfifo sizes needs to be modified(increased) since the newer cores
- * have more memory.
- */
-static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw)
-{
- d11regs_t *regs = wlc_hw->regs;
- u16 fifo_nu;
- u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
- u16 txfifo_def, txfifo_def1;
- u16 txfifo_cmd;
-
- /* tx fifos start at TXFIFO_START_BLK from the Base address */
- txfifo_startblk = TXFIFO_START_BLK;
-
- /* sequence of operations: reset fifo, set fifo size, reset fifo */
- for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) {
-
- txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu];
- txfifo_def = (txfifo_startblk & 0xff) |
- (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT);
- txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) |
- ((((txfifo_endblk -
- 1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT);
- txfifo_cmd =
- TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
-
- W_REG(&regs->xmtfifocmd, txfifo_cmd);
- W_REG(&regs->xmtfifodef, txfifo_def);
- W_REG(&regs->xmtfifodef1, txfifo_def1);
-
- W_REG(&regs->xmtfifocmd, txfifo_cmd);
-
- txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
- }
- /*
- * need to propagate to shm location to be in sync since ucode/hw won't
- * do this
- */
- brcms_b_write_shm(wlc_hw, M_FIFOSIZE0,
- wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
- brcms_b_write_shm(wlc_hw, M_FIFOSIZE1,
- wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
- brcms_b_write_shm(wlc_hw, M_FIFOSIZE2,
- ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
- xmtfifo_sz[TX_AC_BK_FIFO]));
- brcms_b_write_shm(wlc_hw, M_FIFOSIZE3,
- ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
- xmtfifo_sz[TX_BCMC_FIFO]));
-}
-
-/* d11 core init
- * reset PSM
- * download ucode/PCM
- * let ucode run to suspended
- * download ucode inits
- * config other core registers
- * init dma
- */
-static void brcms_b_coreinit(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs;
- u32 sflags;
- uint bcnint_us;
- uint i = 0;
- bool fifosz_fixup = false;
- int err = 0;
- u16 buf[NFIFO];
- struct wiphy *wiphy = wlc->wiphy;
-
- regs = wlc_hw->regs;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- /* reset PSM */
- brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
-
- brcms_ucode_download(wlc_hw);
- /*
- * FIFOSZ fixup. driver wants to controls the fifo allocation.
- */
- fifosz_fixup = true;
-
- /* let the PSM run to the suspended state, set mode to BSS STA */
- W_REG(&regs->macintstatus, -1);
- brcms_b_mctrl(wlc_hw, ~0,
- (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
-
- /* wait for ucode to self-suspend after auto-init */
- SPINWAIT(((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0),
- 1000 * 1000);
- if ((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0)
- wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-"
- "suspend!\n", wlc_hw->unit);
-
- brcms_c_gpio_init(wlc);
-
- sflags = ai_core_sflags(wlc_hw->sih, 0, 0);
-
- if (D11REV_IS(wlc_hw->corerev, 23)) {
- if (BRCMS_ISNPHY(wlc_hw->band))
- brcms_c_write_inits(wlc_hw, d11n0initvals16);
- else
- wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
- " %d\n", __func__, wlc_hw->unit,
- wlc_hw->corerev);
- } else if (D11REV_IS(wlc_hw->corerev, 24)) {
- if (BRCMS_ISLCNPHY(wlc_hw->band)) {
- brcms_c_write_inits(wlc_hw, d11lcn0initvals24);
- } else {
- wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
- " %d\n", __func__, wlc_hw->unit,
- wlc_hw->corerev);
- }
- } else {
- wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
- __func__, wlc_hw->unit, wlc_hw->corerev);
- }
-
- /* For old ucode, txfifo sizes needs to be modified(increased) */
- if (fifosz_fixup == true) {
- brcms_b_corerev_fifofixup(wlc_hw);
- }
-
- /* check txfifo allocations match between ucode and driver */
- buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0);
- if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) {
- i = TX_AC_BE_FIFO;
- err = -1;
- }
- buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1);
- if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) {
- i = TX_AC_VI_FIFO;
- err = -1;
- }
- buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2);
- buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff;
- buf[TX_AC_BK_FIFO] &= 0xff;
- if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) {
- i = TX_AC_BK_FIFO;
- err = -1;
- }
- if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) {
- i = TX_AC_VO_FIFO;
- err = -1;
- }
- buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3);
- buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff;
- buf[TX_BCMC_FIFO] &= 0xff;
- if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) {
- i = TX_BCMC_FIFO;
- err = -1;
- }
- if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) {
- i = TX_ATIM_FIFO;
- err = -1;
- }
- if (err != 0) {
- wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d"
- " driver size %d index %d\n", buf[i],
- wlc_hw->xmtfifo_sz[i], i);
- }
-
- /* make sure we can still talk to the mac */
- WARN_ON(R_REG(&regs->maccontrol) == 0xffffffff);
-
- /* band-specific inits done by wlc_bsinit() */
-
- /* Set up frame burst size and antenna swap threshold init values */
- brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST);
- brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
-
- /* enable one rx interrupt per received frame */
- W_REG(&regs->intrcvlazy[0], (1 << IRL_FC_SHIFT));
-
- /* set the station mode (BSS STA) */
- brcms_b_mctrl(wlc_hw,
- (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP),
- (MCTL_INFRA | MCTL_DISCARD_PMQ));
-
- /* set up Beacon interval */
- bcnint_us = 0x8000 << 10;
- W_REG(&regs->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT));
- W_REG(&regs->tsf_cfpstart, bcnint_us);
- W_REG(&regs->macintstatus, MI_GP1);
-
- /* write interrupt mask */
- W_REG(&regs->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK);
-
- /* allow the MAC to control the PHY clock (dynamic on/off) */
- brcms_b_macphyclk_set(wlc_hw, ON);
-
- /* program dynamic clock control fast powerup delay register */
- wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih);
- W_REG(&regs->scc_fastpwrup_dly, wlc->fastpwrup_dly);
-
- /* tell the ucode the corerev */
- brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
-
- /* tell the ucode MAC capabilities */
- brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L,
- (u16) (wlc_hw->machwcap & 0xffff));
- brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H,
- (u16) ((wlc_hw->
- machwcap >> 16) & 0xffff));
-
- /* write retry limits to SCR, this done after PSM init */
- W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
- (void)R_REG(&regs->objaddr);
- W_REG(&regs->objdata, wlc_hw->SRL);
- W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
- (void)R_REG(&regs->objaddr);
- W_REG(&regs->objdata, wlc_hw->LRL);
-
- /* write rate fallback retry limits */
- brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
- brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
-
- AND_REG(&regs->ifs_ctl, 0x0FFF);
- W_REG(&regs->ifs_aifsn, EDCF_AIFSN_MIN);
-
- /* dma initializations */
- wlc->txpend16165war = 0;
-
- /* init the tx dma engines */
- for (i = 0; i < NFIFO; i++) {
- if (wlc_hw->di[i])
- dma_txinit(wlc_hw->di[i]);
- }
-
- /* init the rx dma engine(s) and post receive buffers */
- dma_rxinit(wlc_hw->di[RX_FIFO]);
- dma_rxfill(wlc_hw->di[RX_FIFO]);
-}
-
-/* This function is used for changing the tsf frac register
- * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz
- * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz
- * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz
- * HTPHY Formula is 2^26/freq(MHz) e.g.
- * For spuron2 - 126MHz -> 2^26/126 = 532610.0
- * - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082
- * For spuron: 123MHz -> 2^26/123 = 545600.5
- * - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341
- * For spur off: 120MHz -> 2^26/120 = 559240.5
- * - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
- */
-
-void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
-{
- d11regs_t *regs;
- regs = wlc_hw->regs;
-
- if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
- (wlc_hw->sih->chip == BCM43225_CHIP_ID)) {
- if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */
- W_REG(&regs->tsf_clk_frac_l, 0x2082);
- W_REG(&regs->tsf_clk_frac_h, 0x8);
- } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */
- W_REG(&regs->tsf_clk_frac_l, 0x5341);
- W_REG(&regs->tsf_clk_frac_h, 0x8);
- } else { /* 120Mhz */
- W_REG(&regs->tsf_clk_frac_l, 0x8889);
- W_REG(&regs->tsf_clk_frac_h, 0x8);
- }
- } else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
- if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */
- W_REG(&regs->tsf_clk_frac_l, 0x7CE0);
- W_REG(&regs->tsf_clk_frac_h, 0xC);
- } else { /* 80Mhz */
- W_REG(&regs->tsf_clk_frac_l, 0xCCCD);
- W_REG(&regs->tsf_clk_frac_h, 0xC);
- }
- }
-}
-
-/* Initialize GPIOs that are controlled by D11 core */
-static void brcms_c_gpio_init(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs;
- u32 gc, gm;
-
- regs = wlc_hw->regs;
-
- /* use GPIO select 0 to get all gpio signals from the gpio out reg */
- brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
-
- /*
- * Common GPIO setup:
- * G0 = LED 0 = WLAN Activity
- * G1 = LED 1 = WLAN 2.4 GHz Radio State
- * G2 = LED 2 = WLAN 5 GHz Radio State
- * G4 = radio disable input (HI enabled, LO disabled)
- */
-
- gc = gm = 0;
-
- /* Allocate GPIOs for mimo antenna diversity feature */
- if (wlc_hw->antsel_type == ANTSEL_2x3) {
- /* Enable antenna diversity, use 2x3 mode */
- brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
- MHF3_ANTSEL_EN, BRCM_BAND_ALL);
- brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
- MHF3_ANTSEL_MODE, BRCM_BAND_ALL);
-
- /* init superswitch control */
- wlc_phy_antsel_init(wlc_hw->band->pi, false);
-
- } else if (wlc_hw->antsel_type == ANTSEL_2x4) {
- gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13);
- /*
- * The board itself is powered by these GPIOs
- * (when not sending pattern) so set them high
- */
- OR_REG(&regs->psm_gpio_oe,
- (BOARD_GPIO_12 | BOARD_GPIO_13));
- OR_REG(&regs->psm_gpio_out,
- (BOARD_GPIO_12 | BOARD_GPIO_13));
-
- /* Enable antenna diversity, use 2x4 mode */
- brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
- MHF3_ANTSEL_EN, BRCM_BAND_ALL);
- brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0,
- BRCM_BAND_ALL);
-
- /* Configure the desired clock to be 4Mhz */
- brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV,
- ANTSEL_CLKDIV_4MHZ);
- }
-
- /* gpio 9 controls the PA. ucode is responsible for wiggling out and oe */
- if (wlc_hw->boardflags & BFL_PACTRL)
- gm |= gc |= BOARD_GPIO_PACTRL;
-
- /* apply to gpiocontrol register */
- ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY);
-}
-
-static void brcms_ucode_download(struct brcms_hardware *wlc_hw)
-{
- struct brcms_c_info *wlc;
- wlc = wlc_hw->wlc;
-
- if (wlc_hw->ucode_loaded)
- return;
-
- if (D11REV_IS(wlc_hw->corerev, 23)) {
- if (BRCMS_ISNPHY(wlc_hw->band)) {
- brcms_ucode_write(wlc_hw, bcm43xx_16_mimo,
- bcm43xx_16_mimosz);
- wlc_hw->ucode_loaded = true;
- } else
- wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
- "corerev %d\n",
- __func__, wlc_hw->unit, wlc_hw->corerev);
- } else if (D11REV_IS(wlc_hw->corerev, 24)) {
- if (BRCMS_ISLCNPHY(wlc_hw->band)) {
- brcms_ucode_write(wlc_hw, bcm43xx_24_lcn,
- bcm43xx_24_lcnsz);
- wlc_hw->ucode_loaded = true;
- } else {
- wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
- "corerev %d\n",
- __func__, wlc_hw->unit, wlc_hw->corerev);
- }
- }
-}
-
-static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[],
- const uint nbytes) {
- d11regs_t *regs = wlc_hw->regs;
- uint i;
- uint count;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- count = (nbytes / sizeof(u32));
-
- W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
- (void)R_REG(&regs->objaddr);
- for (i = 0; i < count; i++)
- W_REG(&regs->objdata, ucode[i]);
-}
-
-static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
- const struct d11init *inits)
-{
- int i;
- volatile u8 *base;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- base = (volatile u8 *)wlc_hw->regs;
-
- for (i = 0; inits[i].addr != 0xffff; i++) {
- if (inits[i].size == 2)
- W_REG((u16 *)(base + inits[i].addr),
- inits[i].value);
- else if (inits[i].size == 4)
- W_REG((u32 *)(base + inits[i].addr),
- inits[i].value);
- }
-}
-
-static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw)
-{
- u16 phyctl;
- u16 phytxant = wlc_hw->bmac_phytxant;
- u16 mask = PHY_TXC_ANT_MASK;
-
- /* set the Probe Response frame phy control word */
- phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS);
- phyctl = (phyctl & ~mask) | phytxant;
- brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl);
-
- /* set the Response (ACK/CTS) frame phy control word */
- phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD);
- phyctl = (phyctl & ~mask) | phytxant;
- brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl);
-}
-
-void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant)
-{
- /* update sw state */
- wlc_hw->bmac_phytxant = phytxant;
-
- /* push to ucode if up */
- if (!wlc_hw->up)
- return;
- brcms_c_ucode_txant_set(wlc_hw);
-
-}
-
-u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw)
-{
- return (u16) wlc_hw->wlc->stf->txant;
-}
-
-void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type)
-{
- wlc_hw->antsel_type = antsel_type;
-
- /* Update the antsel type for phy module to use */
- wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
-}
-
-void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
-{
- bool fatal = false;
- uint unit;
- uint intstatus, idx;
- d11regs_t *regs = wlc_hw->regs;
- struct wiphy *wiphy = wlc_hw->wlc->wiphy;
-
- unit = wlc_hw->unit;
-
- for (idx = 0; idx < NFIFO; idx++) {
- /* read intstatus register and ignore any non-error bits */
- intstatus =
- R_REG(&regs->intctrlregs[idx].intstatus) & I_ERRORS;
- if (!intstatus)
- continue;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n",
- unit, idx, intstatus);
-
- if (intstatus & I_RO) {
- wiphy_err(wiphy, "wl%d: fifo %d: receive fifo "
- "overflow\n", unit, idx);
- fatal = true;
- }
-
- if (intstatus & I_PC) {
- wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n",
- unit, idx);
- fatal = true;
- }
-
- if (intstatus & I_PD) {
- wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit,
- idx);
- fatal = true;
- }
-
- if (intstatus & I_DE) {
- wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol "
- "error\n", unit, idx);
- fatal = true;
- }
-
- if (intstatus & I_RU) {
- wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor "
- "underflow\n", idx, unit);
- }
-
- if (intstatus & I_XU) {
- wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo "
- "underflow\n", idx, unit);
- fatal = true;
- }
-
- if (fatal) {
- brcms_c_fatal_error(wlc_hw->wlc); /* big hammer */
- break;
- } else
- W_REG(&regs->intctrlregs[idx].intstatus,
- intstatus);
- }
-}
-
-void brcms_c_intrson(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- wlc->macintmask = wlc->defmacintmask;
- W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
-}
-
-/* callback for siutils.c, which has only wlc handler, no wl
- * they both check up, not only because there is no need to off/restore d11 interrupt
- * but also because per-port code may require sync with valid interrupt.
- */
-
-static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc)
-{
- if (!wlc->hw->up)
- return 0;
-
- return brcms_intrsoff(wlc->wl);
-}
-
-static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask)
-{
- if (!wlc->hw->up)
- return;
-
- brcms_intrsrestore(wlc->wl, macintmask);
-}
-
-u32 brcms_c_intrsoff(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- u32 macintmask;
-
- if (!wlc_hw->clk)
- return 0;
-
- macintmask = wlc->macintmask; /* isr can still happen */
-
- W_REG(&wlc_hw->regs->macintmask, 0);
- (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */
- udelay(1); /* ensure int line is no longer driven */
- wlc->macintmask = 0;
-
- /* return previous macintmask; resolve race between us and our isr */
- return wlc->macintstatus ? 0 : macintmask;
-}
-
-void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- if (!wlc_hw->clk)
- return;
-
- wlc->macintmask = macintmask;
- W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
-}
-
-static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, mbool flags)
-{
- u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
-
- if (on) {
- /* suspend tx fifos */
- brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
- brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
- brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO);
- brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
-
- /* zero the address match register so we do not send ACKs */
- brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
- null_ether_addr);
- } else {
- /* resume tx fifos */
- if (!wlc_hw->wlc->tx_suspended) {
- brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
- }
- brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO);
- brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO);
- brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
-
- /* Restore address */
- brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
- wlc_hw->etheraddr);
- }
-
- wlc_phy_mute_upd(wlc_hw->band->pi, on, flags);
-
- if (on)
- brcms_c_ucode_mute_override_set(wlc_hw);
- else
- brcms_c_ucode_mute_override_clear(wlc_hw);
-}
-
-int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
- uint *blocks)
-{
- if (fifo >= NFIFO)
- return -EINVAL;
-
- *blocks = wlc_hw->xmtfifo_sz[fifo];
-
- return 0;
-}
-
-/* brcms_b_tx_fifo_suspended:
- * Check the MAC's tx suspend status for a tx fifo.
- *
- * When the MAC acknowledges a tx suspend, it indicates that no more
- * packets will be transmitted out the radio. This is independent of
- * DMA channel suspension---the DMA may have finished suspending, or may still
- * be pulling data into a tx fifo, by the time the MAC acks the suspend
- * request.
- */
-static bool brcms_b_tx_fifo_suspended(struct brcms_hardware *wlc_hw,
- uint tx_fifo)
-{
- /* check that a suspend has been requested and is no longer pending */
-
- /*
- * for DMA mode, the suspend request is set in xmtcontrol of the DMA engine,
- * and the tx fifo suspend at the lower end of the MAC is acknowledged in the
- * chnstatus register.
- * The tx fifo suspend completion is independent of the DMA suspend completion and
- * may be acked before or after the DMA is suspended.
- */
- if (dma_txsuspended(wlc_hw->di[tx_fifo]) &&
- (R_REG(&wlc_hw->regs->chnstatus) &
- (1 << tx_fifo)) == 0)
- return true;
-
- return false;
-}
-
-static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
- uint tx_fifo)
-{
- u8 fifo = 1 << tx_fifo;
-
- /* Two clients of this code, 11h Quiet period and scanning. */
-
- /* only suspend if not already suspended */
- if ((wlc_hw->suspended_fifos & fifo) == fifo)
- return;
-
- /* force the core awake only if not already */
- if (wlc_hw->suspended_fifos == 0)
- brcms_c_ucode_wake_override_set(wlc_hw,
- BRCMS_WAKE_OVERRIDE_TXFIFO);
-
- wlc_hw->suspended_fifos |= fifo;
-
- if (wlc_hw->di[tx_fifo]) {
- /* Suspending AMPDU transmissions in the middle can cause underflow
- * which may result in mismatch between ucode and driver
- * so suspend the mac before suspending the FIFO
- */
- if (BRCMS_PHY_11N_CAP(wlc_hw->band))
- brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
-
- dma_txsuspend(wlc_hw->di[tx_fifo]);
-
- if (BRCMS_PHY_11N_CAP(wlc_hw->band))
- brcms_c_enable_mac(wlc_hw->wlc);
- }
-}
-
-static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
- uint tx_fifo)
-{
- /* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case
- * but need to be done here for PIO otherwise the watchdog will catch
- * the inconsistency and fire
- */
- /* Two clients of this code, 11h Quiet period and scanning. */
- if (wlc_hw->di[tx_fifo])
- dma_txresume(wlc_hw->di[tx_fifo]);
-
- /* allow core to sleep again */
- if (wlc_hw->suspended_fifos == 0)
- return;
- else {
- wlc_hw->suspended_fifos &= ~(1 << tx_fifo);
- if (wlc_hw->suspended_fifos == 0)
- brcms_c_ucode_wake_override_clear(wlc_hw,
- BRCMS_WAKE_OVERRIDE_TXFIFO);
- }
-}
-
-/*
- * Read and clear macintmask and macintstatus and intstatus registers.
- * This routine should be called with interrupts off
- * Return:
- * -1 if DEVICEREMOVED(wlc) evaluates to true;
- * 0 if the interrupt is not for us, or we are in some special cases;
- * device interrupt status bits otherwise.
- */
-static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs = wlc_hw->regs;
- u32 macintstatus;
-
- /* macintstatus includes a DMA interrupt summary bit */
- macintstatus = R_REG(&regs->macintstatus);
-
- BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit,
- macintstatus);
-
- /* detect cardbus removed, in power down(suspend) and in reset */
- if (DEVICEREMOVED(wlc))
- return -1;
-
- /* DEVICEREMOVED succeeds even when the core is still resetting,
- * handle that case here.
- */
- if (macintstatus == 0xffffffff)
- return 0;
-
- /* defer unsolicited interrupts */
- macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
-
- /* if not for us */
- if (macintstatus == 0)
- return 0;
-
- /* interrupts are already turned off for CFE build
- * Caution: For CFE Turning off the interrupts again has some undesired
- * consequences
- */
- /* turn off the interrupts */
- W_REG(&regs->macintmask, 0);
- (void)R_REG(&regs->macintmask); /* sync readback */
- wlc->macintmask = 0;
-
- /* clear device interrupts */
- W_REG(&regs->macintstatus, macintstatus);
-
- /* MI_DMAINT is indication of non-zero intstatus */
- if (macintstatus & MI_DMAINT) {
- /*
- * only fifo interrupt enabled is I_RI in
- * RX_FIFO. If MI_DMAINT is set, assume it
- * is set and clear the interrupt.
- */
- W_REG(&regs->intctrlregs[RX_FIFO].intstatus,
- DEF_RXINTMASK);
- }
-
- return macintstatus;
-}
-
-/* Update wlc->macintstatus and wlc->intstatus[]. */
-/* Return true if they are updated successfully. false otherwise */
-bool brcms_c_intrsupd(struct brcms_c_info *wlc)
-{
- u32 macintstatus;
-
- /* read and clear macintstatus and intstatus registers */
- macintstatus = wlc_intstatus(wlc, false);
-
- /* device is removed */
- if (macintstatus == 0xffffffff)
- return false;
-
- /* update interrupt status in software */
- wlc->macintstatus |= macintstatus;
-
- return true;
-}
-
-/*
- * First-level interrupt processing.
- * Return true if this was our interrupt, false otherwise.
- * *wantdpc will be set to true if further brcms_c_dpc() processing is required,
- * false otherwise.
- */
-bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- u32 macintstatus;
-
- *wantdpc = false;
-
- if (!wlc_hw->up || !wlc->macintmask)
- return false;
-
- /* read and clear macintstatus and intstatus registers */
- macintstatus = wlc_intstatus(wlc, true);
-
- if (macintstatus == 0xffffffff)
- wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code"
- " path\n");
-
- /* it is not for us */
- if (macintstatus == 0)
- return false;
-
- *wantdpc = true;
-
- /* save interrupt status bits */
- wlc->macintstatus = macintstatus;
-
- return true;
-
-}
-
-static bool
-brcms_b_dotxstatus(struct brcms_hardware *wlc_hw, struct tx_status *txs,
- u32 s2)
-{
- /* discard intermediate indications for ucode with one legitimate case:
- * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
- * tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
- * transmission count)
- */
- if (!(txs->status & TX_STATUS_AMPDU)
- && (txs->status & TX_STATUS_INTERMEDIATE)) {
- return false;
- }
-
- return brcms_c_dotxstatus(wlc_hw->wlc, txs, s2);
-}
-
-/* process tx completion events in BMAC
- * Return true if more tx status need to be processed. false otherwise.
- */
-static bool
-brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
-{
- bool morepending = false;
- struct brcms_c_info *wlc = wlc_hw->wlc;
- d11regs_t *regs;
- struct tx_status txstatus, *txs;
- u32 s1, s2;
- uint n = 0;
- /*
- * Param 'max_tx_num' indicates max. # tx status to process before
- * break out.
- */
- uint max_tx_num = bound ? wlc->pub->tunables->txsbnd : -1;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- txs = &txstatus;
- regs = wlc_hw->regs;
- while (!(*fatal)
- && (s1 = R_REG(&regs->frmtxstatus)) & TXS_V) {
-
- if (s1 == 0xffffffff) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n",
- wlc_hw->unit, __func__);
- return morepending;
- }
-
- s2 = R_REG(&regs->frmtxstatus2);
-
- txs->status = s1 & TXS_STATUS_MASK;
- txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
- txs->sequence = s2 & TXS_SEQ_MASK;
- txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT;
- txs->lasttxtime = 0;
-
- *fatal = brcms_b_dotxstatus(wlc_hw, txs, s2);
-
- /* !give others some time to run! */
- if (++n >= max_tx_num)
- break;
- }
-
- if (*fatal)
- return 0;
-
- if (n >= max_tx_num)
- morepending = true;
-
- if (!pktq_empty(&wlc->pkt_queue->q))
- brcms_c_send_q(wlc);
-
- return morepending;
-}
-
-void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs = wlc_hw->regs;
- u32 mc, mi;
- struct wiphy *wiphy = wlc->wiphy;
-
- BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
- wlc_hw->band->bandunit);
-
- /*
- * Track overlapping suspend requests
- */
- wlc_hw->mac_suspend_depth++;
- if (wlc_hw->mac_suspend_depth > 1)
- return;
-
- /* force the core awake */
- brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
-
- mc = R_REG(&regs->maccontrol);
-
- if (mc == 0xffffffff) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
- __func__);
- brcms_down(wlc->wl);
- return;
- }
- WARN_ON(mc & MCTL_PSM_JMP_0);
- WARN_ON(!(mc & MCTL_PSM_RUN));
- WARN_ON(!(mc & MCTL_EN_MAC));
-
- mi = R_REG(&regs->macintstatus);
- if (mi == 0xffffffff) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
- __func__);
- brcms_down(wlc->wl);
- return;
- }
- WARN_ON(mi & MI_MACSSPNDD);
-
- brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0);
-
- SPINWAIT(!(R_REG(&regs->macintstatus) & MI_MACSSPNDD),
- BRCMS_MAX_MAC_SUSPEND);
-
- if (!(R_REG(&regs->macintstatus) & MI_MACSSPNDD)) {
- wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
- " and MI_MACSSPNDD is still not on.\n",
- wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND);
- wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
- "psm_brc 0x%04x\n", wlc_hw->unit,
- R_REG(&regs->psmdebug),
- R_REG(&regs->phydebug),
- R_REG(&regs->psm_brc));
- }
-
- mc = R_REG(&regs->maccontrol);
- if (mc == 0xffffffff) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
- __func__);
- brcms_down(wlc->wl);
- return;
- }
- WARN_ON(mc & MCTL_PSM_JMP_0);
- WARN_ON(!(mc & MCTL_PSM_RUN));
- WARN_ON(mc & MCTL_EN_MAC);
-}
-
-void brcms_c_enable_mac(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs = wlc_hw->regs;
- u32 mc, mi;
-
- BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
- wlc->band->bandunit);
-
- /*
- * Track overlapping suspend requests
- */
- wlc_hw->mac_suspend_depth--;
- if (wlc_hw->mac_suspend_depth > 0)
- return;
-
- mc = R_REG(&regs->maccontrol);
- WARN_ON(mc & MCTL_PSM_JMP_0);
- WARN_ON(mc & MCTL_EN_MAC);
- WARN_ON(!(mc & MCTL_PSM_RUN));
-
- brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
- W_REG(&regs->macintstatus, MI_MACSSPNDD);
-
- mc = R_REG(&regs->maccontrol);
- WARN_ON(mc & MCTL_PSM_JMP_0);
- WARN_ON(!(mc & MCTL_EN_MAC));
- WARN_ON(!(mc & MCTL_PSM_RUN));
-
- mi = R_REG(&regs->macintstatus);
- WARN_ON(mi & MI_MACSSPNDD);
-
- brcms_c_ucode_wake_override_clear(wlc_hw,
- BRCMS_WAKE_OVERRIDE_MACSUSPEND);
-}
-
-static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw)
-{
- u8 rate;
- u8 rates[8] = {
- BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M,
- BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M
- };
- u16 entry_ptr;
- u16 pctl1;
- uint i;
-
- if (!BRCMS_PHY_11N_CAP(wlc_hw->band))
- return;
-
- /* walk the phy rate table and update the entries */
- for (i = 0; i < ARRAY_SIZE(rates); i++) {
- rate = rates[i];
-
- entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate);
-
- /* read the SHM Rate Table entry OFDM PCTL1 values */
- pctl1 =
- brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS);
-
- /* modify the value */
- pctl1 &= ~PHY_TXC1_MODE_MASK;
- pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT);
-
- /* Update the SHM Rate Table entry OFDM PCTL1 values */
- brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS,
- pctl1);
- }
-}
-
-static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw,
- u8 rate)
-{
- uint i;
- u8 plcp_rate = 0;
- struct plcp_signal_rate_lookup {
- u8 rate;
- u8 signal_rate;
- };
- /* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */
- const struct plcp_signal_rate_lookup rate_lookup[] = {
- {BRCM_RATE_6M, 0xB},
- {BRCM_RATE_9M, 0xF},
- {BRCM_RATE_12M, 0xA},
- {BRCM_RATE_18M, 0xE},
- {BRCM_RATE_24M, 0x9},
- {BRCM_RATE_36M, 0xD},
- {BRCM_RATE_48M, 0x8},
- {BRCM_RATE_54M, 0xC}
- };
-
- for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) {
- if (rate == rate_lookup[i].rate) {
- plcp_rate = rate_lookup[i].signal_rate;
- break;
- }
- }
-
- /* Find the SHM pointer to the rate table entry by looking in the
- * Direct-map Table
- */
- return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
-}
-
-void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode)
-{
- wlc_hw->hw_stf_ss_opmode = stf_mode;
-
- if (wlc_hw->clk)
- brcms_upd_ofdm_pctl1_table(wlc_hw);
-}
-
-void
-brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
- u32 *tsf_h_ptr)
-{
- d11regs_t *regs = wlc_hw->regs;
-
- /* read the tsf timer low, then high to get an atomic read */
- *tsf_l_ptr = R_REG(&regs->tsf_timerlow);
- *tsf_h_ptr = R_REG(&regs->tsf_timerhigh);
-
- return;
-}
-
-static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw)
-{
- d11regs_t *regs;
- u32 w, val;
- struct wiphy *wiphy = wlc_hw->wlc->wiphy;
-
- BCMMSG(wiphy, "wl%d\n", wlc_hw->unit);
-
- regs = wlc_hw->regs;
-
- /* Validate dchip register access */
-
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- w = R_REG(&regs->objdata);
-
- /* Can we write and read back a 32bit register? */
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- W_REG(&regs->objdata, (u32) 0xaa5555aa);
-
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- val = R_REG(&regs->objdata);
- if (val != (u32) 0xaa5555aa) {
- wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
- "expected 0xaa5555aa\n", wlc_hw->unit, val);
- return false;
- }
-
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- W_REG(&regs->objdata, (u32) 0x55aaaa55);
-
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- val = R_REG(&regs->objdata);
- if (val != (u32) 0x55aaaa55) {
- wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
- "expected 0x55aaaa55\n", wlc_hw->unit, val);
- return false;
- }
-
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- W_REG(&regs->objdata, w);
-
- /* clear CFPStart */
- W_REG(&regs->tsf_cfpstart, 0);
-
- w = R_REG(&regs->maccontrol);
- if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
- (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
- wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = "
- "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w,
- (MCTL_IHR_EN | MCTL_WAKE),
- (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE));
- return false;
- }
-
- return true;
-}
-
-#define PHYPLL_WAIT_US 100000
-
-void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
-{
- d11regs_t *regs;
- u32 tmp;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- tmp = 0;
- regs = wlc_hw->regs;
-
- if (on) {
- if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
- OR_REG(&regs->clk_ctl_st,
- (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL |
- CCS_ERSRC_REQ_PHYPLL));
- SPINWAIT((R_REG(&regs->clk_ctl_st) &
- (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT),
- PHYPLL_WAIT_US);
-
- tmp = R_REG(&regs->clk_ctl_st);
- if ((tmp & (CCS_ERSRC_AVAIL_HT)) !=
- (CCS_ERSRC_AVAIL_HT)) {
- wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY"
- " PLL failed\n", __func__);
- }
- } else {
- OR_REG(&regs->clk_ctl_st,
- (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL));
- SPINWAIT((R_REG(&regs->clk_ctl_st) &
- (CCS_ERSRC_AVAIL_D11PLL |
- CCS_ERSRC_AVAIL_PHYPLL)) !=
- (CCS_ERSRC_AVAIL_D11PLL |
- CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
-
- tmp = R_REG(&regs->clk_ctl_st);
- if ((tmp &
- (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
- !=
- (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) {
- wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on "
- "PHY PLL failed\n", __func__);
- }
- }
- } else {
- /* Since the PLL may be shared, other cores can still be requesting it;
- * so we'll deassert the request but not wait for status to comply.
- */
- AND_REG(&regs->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL);
- tmp = R_REG(&regs->clk_ctl_st);
- }
-}
-
-void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
-{
- bool dev_gone;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
- if (dev_gone)
- return;
-
- if (wlc_hw->noreset)
- return;
-
- /* radio off */
- wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
-
- /* turn off analog core */
- wlc_phy_anacore(wlc_hw->band->pi, OFF);
-
- /* turn off PHYPLL to save power */
- brcms_b_core_phypll_ctl(wlc_hw, false);
-
- /* No need to set wlc->pub->radio_active = OFF
- * because this function needs down capability and
- * radio_active is designed for BCMNODOWN.
- */
-
- /* remove gpio controls */
- if (wlc_hw->ucode_dbgsel)
- ai_gpiocontrol(wlc_hw->sih, ~0, 0, GPIO_DRV_PRIORITY);
-
- wlc_hw->clk = false;
- ai_core_disable(wlc_hw->sih, 0);
- wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
-}
-
-/* power both the pll and external oscillator on/off */
-static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want)
-{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want);
-
- /* dont power down if plldown is false or we must poll hw radio disable */
- if (!want && wlc_hw->pllreq)
- return;
-
- if (wlc_hw->sih)
- ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want);
-
- wlc_hw->sbclk = want;
- if (!wlc_hw->sbclk) {
- wlc_hw->clk = false;
- if (wlc_hw->band && wlc_hw->band->pi)
- wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
- }
-}
-
-static void brcms_c_flushqueues(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- uint i;
-
- wlc->txpend16165war = 0;
-
- /* free any posted tx packets */
- for (i = 0; i < NFIFO; i++)
- if (wlc_hw->di[i]) {
- dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL);
- TXPKTPENDCLR(wlc, i);
- BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i);
- }
-
- /* free any posted rx packets */
- dma_rxreclaim(wlc_hw->di[RX_FIFO]);
-}
-
-u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset)
-{
- return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL);
-}
-
-void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v)
-{
- brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL);
-}
-
-static u16
-brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel)
-{
- d11regs_t *regs = wlc_hw->regs;
- volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
- volatile u16 *objdata_hi = objdata_lo + 1;
- u16 v;
-
- W_REG(&regs->objaddr, sel | (offset >> 2));
- (void)R_REG(&regs->objaddr);
- if (offset & 2) {
- v = R_REG(objdata_hi);
- } else {
- v = R_REG(objdata_lo);
- }
-
- return v;
-}
-
-static void
-brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v,
- u32 sel)
-{
- d11regs_t *regs = wlc_hw->regs;
- volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
- volatile u16 *objdata_hi = objdata_lo + 1;
-
- W_REG(&regs->objaddr, sel | (offset >> 2));
- (void)R_REG(&regs->objaddr);
- if (offset & 2) {
- W_REG(objdata_hi, v);
- } else {
- W_REG(objdata_lo, v);
- }
-}
-
-/* Copy a buffer to shared memory of specified type .
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- * 'sel' selects the type of memory
- */
-void
-brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset,
- const void *buf, int len, u32 sel)
-{
- u16 v;
- const u8 *p = (const u8 *)buf;
- int i;
-
- if (len <= 0 || (offset & 1) || (len & 1))
- return;
-
- for (i = 0; i < len; i += 2) {
- v = p[i] | (p[i + 1] << 8);
- brcms_b_write_objmem(wlc_hw, offset + i, v, sel);
- }
-}
-
-/* Copy a piece of shared memory of specified type to a buffer .
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- * 'sel' selects the type of memory
- */
-void
-brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf,
- int len, u32 sel)
-{
- u16 v;
- u8 *p = (u8 *) buf;
- int i;
-
- if (len <= 0 || (offset & 1) || (len & 1))
- return;
-
- for (i = 0; i < len; i += 2) {
- v = brcms_b_read_objmem(wlc_hw, offset + i, sel);
- p[i] = v & 0xFF;
- p[i + 1] = (v >> 8) & 0xFF;
- }
-}
-
-void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf,
- uint *len)
-{
- BCMMSG(wlc_hw->wlc->wiphy, "nvram vars totlen=%d\n",
- wlc_hw->vars_size);
-
- *buf = wlc_hw->vars;
- *len = wlc_hw->vars_size;
-}
-
-void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, u16 SRL, u16 LRL)
-{
- wlc_hw->SRL = SRL;
- wlc_hw->LRL = LRL;
-
- /* write retry limit to SCR, shouldn't need to suspend */
- if (wlc_hw->up) {
- W_REG(&wlc_hw->regs->objaddr,
- OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
- (void)R_REG(&wlc_hw->regs->objaddr);
- W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL);
- W_REG(&wlc_hw->regs->objaddr,
- OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
- (void)R_REG(&wlc_hw->regs->objaddr);
- W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL);
- }
-}
-
-void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, mbool req_bit)
-{
- if (set) {
- if (mboolisset(wlc_hw->pllreq, req_bit))
- return;
-
- mboolset(wlc_hw->pllreq, req_bit);
-
- if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
- if (!wlc_hw->sbclk) {
- brcms_b_xtal(wlc_hw, ON);
- }
- }
- } else {
- if (!mboolisset(wlc_hw->pllreq, req_bit))
- return;
-
- mboolclr(wlc_hw->pllreq, req_bit);
-
- if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
- if (wlc_hw->sbclk) {
- brcms_b_xtal(wlc_hw, OFF);
- }
- }
- }
-
- return;
-}
-
-u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
-{
- u16 table_ptr;
- u8 phy_rate, index;
-
- /* get the phy specific rate encoding for the PLCP SIGNAL field */
- if (IS_OFDM(rate))
- table_ptr = M_RT_DIRMAP_A;
- else
- table_ptr = M_RT_DIRMAP_B;
-
- /* for a given rate, the LS-nibble of the PLCP SIGNAL field is
- * the index into the rate table.
- */
- phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
- index = phy_rate & 0xf;
-
- /* Find the SHM pointer to the rate table entry by looking in the
- * Direct-map Table
- */
- return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2));
-}
-
-void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
-{
- wlc_hw->antsel_avail = antsel_avail;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/bmac.h b/drivers/staging/brcm80211/brcmsmac/bmac.h
deleted file mode 100644
index 3c9ad4f3bd22..000000000000
--- a/drivers/staging/brcm80211/brcmsmac/bmac.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * 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_BOTTOM_MAC_H_
-#define _BRCM_BOTTOM_MAC_H_
-
-#include <brcmu_wifi.h>
-#include "types.h"
-
-/* dup state between BMAC(struct brcms_hardware) and HIGH(struct brcms_c_info)
- driver */
-struct brcms_b_state {
- u32 machwcap; /* mac hw capibility */
- u32 preamble_ovr; /* preamble override */
-};
-
-enum {
- IOV_BMAC_DIAG,
- IOV_BMAC_SBGPIOTIMERVAL,
- IOV_BMAC_SBGPIOOUT,
- IOV_BMAC_CCGPIOCTRL, /* CC GPIOCTRL REG */
- IOV_BMAC_CCGPIOOUT, /* CC GPIOOUT REG */
- IOV_BMAC_CCGPIOOUTEN, /* CC GPIOOUTEN REG */
- IOV_BMAC_CCGPIOIN, /* CC GPIOIN REG */
- IOV_BMAC_WPSGPIO, /* WPS push button GPIO pin */
- IOV_BMAC_OTPDUMP,
- IOV_BMAC_OTPSTAT,
- IOV_BMAC_PCIEASPM, /* obfuscation clkreq/aspm control */
- IOV_BMAC_PCIEADVCORRMASK, /* advanced correctable error mask */
- IOV_BMAC_PCIECLKREQ, /* PCIE 1.1 clockreq enab support */
- IOV_BMAC_PCIELCREG, /* PCIE LCREG */
- IOV_BMAC_SBGPIOTIMERMASK,
- IOV_BMAC_RFDISABLEDLY,
- IOV_BMAC_PCIEREG, /* PCIE REG */
- IOV_BMAC_PCICFGREG, /* PCI Config register */
- IOV_BMAC_PCIESERDESREG, /* PCIE SERDES REG (dev, 0}offset) */
- IOV_BMAC_PCIEGPIOOUT, /* PCIEOUT REG */
- IOV_BMAC_PCIEGPIOOUTEN, /* PCIEOUTEN REG */
- IOV_BMAC_PCIECLKREQENCTRL, /* clkreqenctrl REG (PCIE REV > 6.0 */
- IOV_BMAC_DMALPBK,
- IOV_BMAC_CCREG,
- IOV_BMAC_COREREG,
- IOV_BMAC_SDCIS,
- IOV_BMAC_SDIO_DRIVE,
- IOV_BMAC_OTPW,
- IOV_BMAC_NVOTPW,
- IOV_BMAC_SROM,
- IOV_BMAC_SRCRC,
- IOV_BMAC_CIS_SOURCE,
- IOV_BMAC_CISVAR,
- IOV_BMAC_OTPLOCK,
- IOV_BMAC_OTP_CHIPID,
- IOV_BMAC_CUSTOMVAR1,
- IOV_BMAC_BOARDFLAGS,
- IOV_BMAC_BOARDFLAGS2,
- IOV_BMAC_WPSLED,
- IOV_BMAC_NVRAM_SOURCE,
- IOV_BMAC_OTP_RAW_READ,
- IOV_BMAC_LAST
-};
-
-extern int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
- uint unit, bool piomode, void *regsva, uint bustype,
- void *btparam);
-extern int brcms_b_detach(struct brcms_c_info *wlc);
-extern void brcms_b_watchdog(void *arg);
-
-/* up/down, reset, clk */
-extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw,
- uint offset, const void *buf, int len,
- u32 sel);
-extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset,
- void *buf, int len, u32 sel);
-#define brcms_b_copyfrom_shm(wlc_hw, offset, buf, len) \
- brcms_b_copyfrom_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
-#define brcms_b_copyto_shm(wlc_hw, offset, buf, len) \
- brcms_b_copyto_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
-
-extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw);
-extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on);
-extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk);
-extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk);
-extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw);
-extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags);
-extern void brcms_b_reset(struct brcms_hardware *wlc_hw);
-extern void brcms_b_init(struct brcms_hardware *wlc_hw, chanspec_t chanspec,
- bool mute);
-extern int brcms_b_up_prep(struct brcms_hardware *wlc_hw);
-extern int brcms_b_up_finish(struct brcms_hardware *wlc_hw);
-extern int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw);
-extern int brcms_b_down_finish(struct brcms_hardware *wlc_hw);
-extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode);
-
-/* chanspec, ucode interface */
-extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw,
- chanspec_t chanspec,
- bool mute, struct txpwr_limits *txpwr);
-
-extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
- uint *blocks);
-extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask,
- u16 val, int bands);
-extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val);
-extern u16 brcms_b_mhf_get(struct brcms_hardware *wlc_hw, u8 idx, int bands);
-extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant);
-extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw);
-extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw,
- u8 antsel_type);
-extern int brcms_b_state_get(struct brcms_hardware *wlc_hw,
- struct brcms_b_state *state);
-extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset,
- u16 v);
-extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset);
-extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw,
- int offset, int len, void *buf);
-extern void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf,
- uint *len);
-
-extern void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw,
- u8 *ea);
-
-extern bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw);
-extern void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw,
- bool shortslot);
-extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw,
- u8 stf_mode);
-
-extern void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw);
-
-extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
- u32 override_bit);
-extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
- u32 override_bit);
-
-extern void brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw,
- int match_reg_offset,
- const u8 *addr);
-extern void brcms_b_write_hw_bcntemplates(struct brcms_hardware *wlc_hw,
- void *bcn, int len, bool both);
-
-extern void brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
- u32 *tsf_h_ptr);
-extern void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin);
-extern void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax);
-
-extern void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, u16 SRL,
- u16 LRL);
-
-extern void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw);
-
-
-/* API for BMAC driver (e.g. wlc_phy.c etc) */
-
-extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw);
-extern void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set,
- mbool req_bit);
-extern void brcms_b_hw_up(struct brcms_hardware *wlc_hw);
-extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate);
-extern void brcms_b_antsel_set(struct brcms_hardware *wlc_hw,
- u32 antsel_avail);
-
-#endif /* _BRCM_BOTTOM_MAC_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/alloc.h b/drivers/staging/brcm80211/brcmsmac/brcms_trace_events.c
index f465d3043030..52fc9eeb5fa5 100644
--- a/drivers/staging/brcm80211/brcmsmac/alloc.h
+++ b/drivers/staging/brcm80211/brcmsmac/brcms_trace_events.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Broadcom Corporation
+ * 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
@@ -14,6 +14,10 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-extern struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err,
- uint devid);
-extern void brcms_c_detach_mfree(struct brcms_c_info *wlc);
+#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
diff --git a/drivers/staging/brcm80211/brcmsmac/brcms_trace_events.h b/drivers/staging/brcm80211/brcmsmac/brcms_trace_events.h
new file mode 100644
index 000000000000..27dd73eef56d
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/brcms_trace_events.h
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac
+
+#if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ)
+
+#define __TRACE_BRCMSMAC_H
+
+#include <linux/tracepoint.h>
+#include "mac80211_if.h"
+
+#ifndef CONFIG_BRCMDBG
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+#endif
+
+/*
+ * 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
+ )
+);
+
+#endif /* __TRACE_BRCMSMAC_H */
+
+#ifdef CONFIG_BRCMDBG
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE brcms_trace_events
+
+#include <trace/define_trace.h>
+
+#endif /* CONFIG_BRCMDBG */
diff --git a/drivers/staging/brcm80211/brcmsmac/channel.c b/drivers/staging/brcm80211/brcmsmac/channel.c
index f59693e1d8a2..89ad1b7dab8f 100644
--- a/drivers/staging/brcm80211/brcmsmac/channel.c
+++ b/drivers/staging/brcm80211/brcmsmac/channel.c
@@ -20,24 +20,138 @@
#include <defs.h>
#include "pub.h"
#include "phy/phy_hal.h"
-#include "bmac.h"
#include "main.h"
#include "stf.h"
#include "channel.h"
-#define VALID_CHANNEL20_DB(wlc, val) brcms_c_valid_channel20_db((wlc)->cmi, val)
-#define VALID_CHANNEL20_IN_BAND(wlc, bandunit, val) \
- brcms_c_valid_channel20_in_band((wlc)->cmi, bandunit, val)
-#define VALID_CHANNEL20(wlc, val) brcms_c_valid_channel20((wlc)->cmi, val)
+/* QDB() macro takes a dB value and converts to a quarter dB value */
+#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
+
+#define LOCALE_CHAN_01_11 (1<<0)
+#define LOCALE_CHAN_12_13 (1<<1)
+#define LOCALE_CHAN_14 (1<<2)
+#define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */
+#define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */
+#define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */
+#define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */
+#define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */
+#define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */
+#define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */
+#define LOCALE_SET_5G_MID3 (1<<10) /* 128 */
+#define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */
+#define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */
+#define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */
+#define LOCALE_CHAN_52_140_ALL (1<<14)
+#define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */
+
+#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | \
+ LOCALE_SET_5G_LOW2 | \
+ LOCALE_SET_5G_LOW3)
+#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
+#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
+#define LOCALE_CHAN_100_140 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \
+ LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
+#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
+#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4
+
+#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | \
+ LOCALE_CHAN_12_13 | \
+ LOCALE_CHAN_14)
+
+#define LOCALE_RADAR_SET_NONE 0
+#define LOCALE_RADAR_SET_1 1
+
+#define LOCALE_RESTRICTED_NONE 0
+#define LOCALE_RESTRICTED_SET_2G_SHORT 1
+#define LOCALE_RESTRICTED_CHAN_165 2
+#define LOCALE_CHAN_ALL_5G 3
+#define LOCALE_RESTRICTED_JAPAN_LEGACY 4
+#define LOCALE_RESTRICTED_11D_2G 5
+#define LOCALE_RESTRICTED_11D_5G 6
+#define LOCALE_RESTRICTED_LOW_HI 7
+#define LOCALE_RESTRICTED_12_13_14 8
+
+#define LOCALE_2G_IDX_i 0
+#define LOCALE_5G_IDX_11 0
+#define LOCALE_MIMO_IDX_bn 0
+#define LOCALE_MIMO_IDX_11n 0
+
+/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
+#define BRCMS_MAXPWR_TBL_SIZE 6
+/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
+#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14
+
+/* power level in group of 2.4GHz band channels:
+ * maxpwr[0] - CCK channels [1]
+ * maxpwr[1] - CCK channels [2-10]
+ * maxpwr[2] - CCK channels [11-14]
+ * maxpwr[3] - OFDM channels [1]
+ * maxpwr[4] - OFDM channels [2-10]
+ * maxpwr[5] - OFDM channels [11-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 LC_2G(id) LOCALE_2G_IDX_ ## id
+
+#define LC_5G(id) LOCALE_5G_IDX_ ## id
+
+#define LOCALES(band2, band5, mimo2, mimo5) \
+ {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
+
+/* macro to get 2.4 GHz channel group index for tx power */
+#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2))
+#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5))
+
+/* 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 ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU)
struct brcms_cm_band {
- u8 locale_flags; /* struct locale_info flags */
- chanvec_t valid_channels; /* List of valid channels in the country */
- const chanvec_t *restricted_channels; /* List of restricted use channels */
- const chanvec_t *radar_channels; /* List of radar sensitive channels */
+ /* struct locale_info flags */
+ u8 locale_flags;
+ /* List of valid channels in the country */
+ struct brcms_chanvec valid_channels;
+ /* List of restricted use channels */
+ const struct brcms_chanvec *restricted_channels;
+ /* List of radar sensitive channels */
+ const struct brcms_chanvec *radar_channels;
u8 PAD[8];
};
+ /* 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];
+ u8 flags;
+};
+
+/* Country names and abbreviations with locale defined from ISO 3166 */
+struct country_info {
+ const u8 locale_2G; /* 2.4G band locale */
+ const u8 locale_5G; /* 5G band locale */
+ const u8 locale_mimo_2G; /* 2.4G mimo info */
+ const u8 locale_mimo_5G; /* 5G mimo info */
+};
+
struct brcms_cm_info {
struct brcms_pub *pub;
struct brcms_c_info *wlc;
@@ -50,63 +164,23 @@ struct brcms_cm_info {
/* per-band state (one per phy/radio) */
struct brcms_cm_band bandstate[MAXBANDS];
/* quiet channels currently for radar sensitivity or 11h support */
- chanvec_t quiet_channels; /* channels on which we cannot transmit */
+ /* channels on which we cannot transmit */
+ struct brcms_chanvec quiet_channels;
};
-static int brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
- const struct country_info *country);
-static void brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, uint regrev,
- const struct country_info *country);
-static int brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm,
- const char *ccode);
-static int brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, int regrev);
-static int brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm,
- const char *ccode,
- char *mapped_ccode, uint *mapped_regrev);
-
-static const struct country_info *
-brcms_c_country_lookup_direct(const char *ccode, uint regrev);
-
-static const struct country_info *
-brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm,
- const char *ccode, char *mapped_ccode,
- uint *mapped_regrev);
-
-static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm);
-static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm);
-static bool brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm,
- chanspec_t chspec);
-static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val);
-static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit, uint val);
-static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val);
-
-static const struct country_info *
-brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode);
-
-static void brcms_c_locale_get_channels(const struct locale_info *locale,
- chanvec_t *valid_channels);
-static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx);
-static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx);
-static bool brcms_c_japan(struct brcms_c_info *wlc);
-static bool brcms_c_japan_ccode(const char *ccode);
-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);
-static void brcms_c_locale_add_channels(chanvec_t *target,
- const chanvec_t *channels);
-static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx);
-static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx);
-
-/* QDB() macro takes a dB value and converts to a quarter dB value */
-#ifdef QDB
-#undef QDB
-#endif
-#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
+/* locale channel and power info. */
+struct locale_info {
+ u32 valid_channels;
+ /* List of radar sensitive channels */
+ u8 radar_channels;
+ /* List of channels used only if APs are detected */
+ u8 restricted_channels;
+ /* Max tx pwr in qdBm for each sub-band */
+ s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE];
+ /* Country IE advertised max tx pwr in dBm per sub-band */
+ s8 pub_maxpwr[BAND_5G_PWR_LVLS];
+ u8 flags;
+};
/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */
@@ -115,7 +189,7 @@ static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx);
*/
/* No channels */
-static const chanvec_t chanvec_none = {
+static const struct brcms_chanvec chanvec_none = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -123,7 +197,7 @@ static const chanvec_t chanvec_none = {
};
/* All 2.4 GHz HW channels */
-const chanvec_t chanvec_all_2G = {
+static const struct brcms_chanvec chanvec_all_2G = {
{0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -131,7 +205,7 @@ const chanvec_t chanvec_all_2G = {
};
/* All 5 GHz HW channels */
-const chanvec_t chanvec_all_5G = {
+static const struct brcms_chanvec chanvec_all_5G = {
{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11,
0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11,
@@ -142,13 +216,11 @@ const chanvec_t chanvec_all_5G = {
* Radar channel sets
*/
-/* No radar */
-#define radar_set_none chanvec_none
-
-static const chanvec_t radar_set1 = { /* Channels 52 - 64, 100 - 140 */
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */
- 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */
- 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */
+/* Channels 52 - 64, 100 - 140 */
+static const struct brcms_chanvec radar_set1 = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */
+ 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */
0x00, 0x00, 0x00, 0x00}
};
@@ -156,10 +228,8 @@ static const chanvec_t radar_set1 = { /* Channels 52 - 64, 100 - 140 */
* Restricted channel sets
*/
-#define restricted_set_none chanvec_none
-
/* Channels 34, 38, 42, 46 */
-static const chanvec_t restricted_set_japan_legacy = {
+static const struct brcms_chanvec restricted_set_japan_legacy = {
{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -167,7 +237,7 @@ static const chanvec_t restricted_set_japan_legacy = {
};
/* Channels 12, 13 */
-static const chanvec_t restricted_set_2g_short = {
+static const struct brcms_chanvec restricted_set_2g_short = {
{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -175,7 +245,7 @@ static const chanvec_t restricted_set_2g_short = {
};
/* Channel 165 */
-static const chanvec_t restricted_chan_165 = {
+static const struct brcms_chanvec restricted_chan_165 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
@@ -183,7 +253,7 @@ static const chanvec_t restricted_chan_165 = {
};
/* Channels 36 - 48 & 149 - 165 */
-static const chanvec_t restricted_low_hi = {
+static const struct brcms_chanvec restricted_low_hi = {
{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00,
@@ -191,61 +261,21 @@ static const chanvec_t restricted_low_hi = {
};
/* Channels 12 - 14 */
-static const chanvec_t restricted_set_12_13_14 = {
+static const struct brcms_chanvec restricted_set_12_13_14 = {
{0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-#define LOCALE_CHAN_01_11 (1<<0)
-#define LOCALE_CHAN_12_13 (1<<1)
-#define LOCALE_CHAN_14 (1<<2)
-#define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */
-#define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */
-#define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */
-#define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */
-#define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */
-#define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */
-#define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */
-#define LOCALE_SET_5G_MID3 (1<<10) /* 128 */
-#define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */
-#define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */
-#define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */
-#define LOCALE_CHAN_52_140_ALL (1<<14)
-#define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */
-
-#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
-#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
-#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
-#define LOCALE_CHAN_100_140 \
- (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
-#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
-#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4
-
-#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13 | LOCALE_CHAN_14)
-
-#define LOCALE_RADAR_SET_NONE 0
-#define LOCALE_RADAR_SET_1 1
-
-#define LOCALE_RESTRICTED_NONE 0
-#define LOCALE_RESTRICTED_SET_2G_SHORT 1
-#define LOCALE_RESTRICTED_CHAN_165 2
-#define LOCALE_CHAN_ALL_5G 3
-#define LOCALE_RESTRICTED_JAPAN_LEGACY 4
-#define LOCALE_RESTRICTED_11D_2G 5
-#define LOCALE_RESTRICTED_11D_5G 6
-#define LOCALE_RESTRICTED_LOW_HI 7
-#define LOCALE_RESTRICTED_12_13_14 8
-
/* global memory to provide working buffer for expanded locale */
-static const chanvec_t *g_table_radar_set[] = {
+static const struct brcms_chanvec *g_table_radar_set[] = {
&chanvec_none,
&radar_set1
};
-static const chanvec_t *g_table_restricted_chan[] = {
+static const struct brcms_chanvec *g_table_restricted_chan[] = {
&chanvec_none, /* restricted_set_none */
&restricted_set_2g_short,
&restricted_chan_165,
@@ -257,119 +287,119 @@ static const chanvec_t *g_table_restricted_chan[] = {
&restricted_set_12_13_14
};
-static const chanvec_t locale_2g_01_11 = {
+static const struct brcms_chanvec locale_2g_01_11 = {
{0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_2g_12_13 = {
+static const struct brcms_chanvec locale_2g_12_13 = {
{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_2g_14 = {
+static const struct brcms_chanvec locale_2g_14 = {
{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_LOW_JP1 = {
+static const struct brcms_chanvec locale_5g_LOW_JP1 = {
{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_LOW_JP2 = {
+static const struct brcms_chanvec locale_5g_LOW_JP2 = {
{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_LOW1 = {
+static const struct brcms_chanvec locale_5g_LOW1 = {
{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_LOW2 = {
+static const struct brcms_chanvec locale_5g_LOW2 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_LOW3 = {
+static const struct brcms_chanvec locale_5g_LOW3 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_MID1 = {
+static const struct brcms_chanvec locale_5g_MID1 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_MID2 = {
+static const struct brcms_chanvec locale_5g_MID2 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_MID3 = {
+static const struct brcms_chanvec locale_5g_MID3 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_HIGH1 = {
+static const struct brcms_chanvec locale_5g_HIGH1 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_HIGH2 = {
+static const struct brcms_chanvec locale_5g_HIGH2 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_HIGH3 = {
+static const struct brcms_chanvec locale_5g_HIGH3 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_52_140_ALL = {
+static const struct brcms_chanvec locale_5g_52_140_ALL = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_HIGH4 = {
+static const struct brcms_chanvec locale_5g_HIGH4 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
0x11, 0x11, 0x11, 0x11}
};
-static const chanvec_t *g_table_locale_base[] = {
+static const struct brcms_chanvec *g_table_locale_base[] = {
&locale_2g_01_11,
&locale_2g_12_13,
&locale_2g_14,
@@ -388,27 +418,25 @@ static const chanvec_t *g_table_locale_base[] = {
&locale_5g_HIGH4
};
-static void brcms_c_locale_add_channels(chanvec_t *target,
- const chanvec_t *channels)
+static void brcms_c_locale_add_channels(struct brcms_chanvec *target,
+ const struct brcms_chanvec *channels)
{
u8 i;
- for (i = 0; i < sizeof(chanvec_t); i++) {
+ for (i = 0; i < sizeof(struct brcms_chanvec); i++)
target->vec[i] |= channels->vec[i];
- }
}
static void brcms_c_locale_get_channels(const struct locale_info *locale,
- chanvec_t *channels)
+ struct brcms_chanvec *channels)
{
u8 i;
- memset(channels, 0, sizeof(chanvec_t));
+ memset(channels, 0, sizeof(struct brcms_chanvec));
for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) {
- if (locale->valid_channels & (1 << i)) {
+ if (locale->valid_channels & (1 << i))
brcms_c_locale_add_channels(channels,
g_table_locale_base[i]);
- }
}
}
@@ -438,12 +466,10 @@ static const struct locale_info locale_11 = {
BRCMS_EIRP | BRCMS_DFS_EU
};
-#define LOCALE_2G_IDX_i 0
static const struct locale_info *g_locale_2g_table[] = {
&locale_i
};
-#define LOCALE_5G_IDX_11 0
static const struct locale_info *g_locale_5g_table[] = {
&locale_11
};
@@ -461,9 +487,6 @@ static const struct locale_mimo_info locale_bn = {
0
};
-/* locale mimo 2g indexes */
-#define LOCALE_MIMO_IDX_bn 0
-
static const struct locale_mimo_info *g_mimo_2g_table[] = {
&locale_bn
};
@@ -477,28 +500,10 @@ static const struct locale_mimo_info locale_11n = {
0
};
-#define LOCALE_MIMO_IDX_11n 0
static const struct locale_mimo_info *g_mimo_5g_table[] = {
&locale_11n
};
-#ifdef LC
-#undef LC
-#endif
-#define LC(id) LOCALE_MIMO_IDX_ ## id
-
-#ifdef LC_2G
-#undef LC_2G
-#endif
-#define LC_2G(id) LOCALE_2G_IDX_ ## id
-
-#ifdef LC_5G
-#undef LC_5G
-#endif
-#define LC_5G(id) LOCALE_5G_IDX_ ## id
-
-#define LOCALES(band2, band5, mimo2, mimo5) {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
-
static const struct {
char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */
struct country_info country;
@@ -586,201 +591,68 @@ struct chan20_info chan20_info[] = {
static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx)
{
- if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) {
+ if (locale_idx >= ARRAY_SIZE(g_locale_2g_table))
return NULL; /* error condition */
- }
+
return g_locale_2g_table[locale_idx];
}
static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx)
{
- if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) {
+ if (locale_idx >= ARRAY_SIZE(g_locale_5g_table))
return NULL; /* error condition */
- }
+
return g_locale_5g_table[locale_idx];
}
static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
{
- if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) {
+ 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];
-}
-
-struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
-{
- struct brcms_cm_info *wlc_cm;
- char country_abbrev[BRCM_CNTRY_BUF_SZ];
- const struct country_info *country;
- struct brcms_pub *pub = wlc->pub;
- char *ccode;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
- wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
- if (wlc_cm == NULL) {
- wiphy_err(wlc->wiphy, "wl%d: %s: out of memory", pub->unit,
- __func__);
+ if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table))
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 */
- ccode = getvar(wlc->pub->vars, "ccode");
- if (ccode) {
- strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
- }
-
- /* internal country information which must match regulatory constraints in firmware */
- memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
- strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
- country = brcms_c_country_lookup(wlc, country_abbrev);
-
- /* save default country for exiting 11d regulatory mode */
- strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
-
- /* initialize autocountry_default to driver default */
- strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
-
- brcms_c_set_countrycode(wlc_cm, country_abbrev);
-
- return wlc_cm;
-}
-
-void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
-{
- kfree(wlc_cm);
-}
-u8
-brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit)
-{
- return wlc_cm->bandstate[bandunit].locale_flags;
-}
-
-/* set the driver's current country and regulatory information using a country code
- * as the source. Lookup built in country information found with the country code.
- */
-static int
-brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode)
-{
- char country_abbrev[BRCM_CNTRY_BUF_SZ];
- strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ);
- return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1);
+ return g_mimo_5g_table[locale_idx];
}
static int
-brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, int regrev)
+brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode,
+ char *mapped_ccode, uint *mapped_regrev)
{
- const struct country_info *country;
- char mapped_ccode[BRCM_CNTRY_BUF_SZ];
- uint mapped_regrev;
-
- /* if regrev is -1, lookup the mapped country code,
- * otherwise use the ccode and regrev directly
- */
- if (regrev == -1) {
- /* map the country code to a built-in country code, regrev, and country_info */
- country =
- brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode,
- &mapped_regrev);
- } else {
- /* find the matching built-in country definition */
- country = brcms_c_country_lookup_direct(ccode, regrev);
- strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
- mapped_regrev = regrev;
- }
-
- if (country == NULL)
- return -EINVAL;
-
- /* set the driver state for the country */
- brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
- mapped_regrev, country);
-
- return 0;
+ return false;
}
-/* 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.
+/* Lookup a country info structure from a null terminated country
+ * abbreviation and regrev directly with no translation.
*/
-static void
-brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, uint regrev,
- const struct country_info *country)
+static const struct country_info *
+brcms_c_country_lookup_direct(const char *ccode, uint regrev)
{
- const struct locale_mimo_info *li_mimo;
- const struct locale_info *locale;
- struct brcms_c_info *wlc = wlc_cm->wlc;
- char prev_country_abbrev[BRCM_CNTRY_BUF_SZ];
-
- /* save current country state */
- wlc_cm->country = country;
-
- memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
- strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
- BRCM_CNTRY_BUF_SZ - 1);
+ uint size, i;
- strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
- strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
- wlc_cm->regrev = regrev;
+ /* Should just return 0 for single locale driver. */
+ /* Keep it this way in case we add more locales. (for now anyway) */
- /* disable/restore nmode based on country regulations */
- li_mimo = brcms_c_get_mimo_2g(country->locale_mimo_2G);
- if (li_mimo && (li_mimo->flags & BRCMS_NO_MIMO)) {
- brcms_c_set_nmode(wlc, OFF);
- wlc->stf->no_cddstbc = true;
- } else {
- wlc->stf->no_cddstbc = false;
- if (N_ENAB(wlc->pub) != wlc->protection->nmode_user)
- brcms_c_set_nmode(wlc, wlc->protection->nmode_user);
- }
+ /*
+ * all other country def arrays are for regrev == 0, so if
+ * regrev is non-zero, fail
+ */
+ if (regrev > 0)
+ return NULL;
- brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
- brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
- /* set or restore gmode as required by regulatory */
- locale = brcms_c_get_locale_2g(country->locale_2G);
- if (locale && (locale->flags & BRCMS_NO_OFDM)) {
- brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
- } else {
- brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
+ /* find matched table entry from country code */
+ size = ARRAY_SIZE(cntry_locales);
+ for (i = 0; i < size; i++) {
+ if (strcmp(ccode, cntry_locales[i].abbrev) == 0)
+ return &cntry_locales[i].country;
}
-
- brcms_c_channels_init(wlc_cm, country);
-
- return;
-}
-
-/* Lookup a country info structure from a null terminated country code
- * The lookup is case sensitive.
- */
-static const struct country_info *
-brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode)
-{
- const struct country_info *country;
- char mapped_ccode[BRCM_CNTRY_BUF_SZ];
- uint mapped_regrev;
-
- /* map the country code to a built-in country code, regrev, and country_info struct */
- country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode,
- &mapped_regrev);
-
- return country;
+ return NULL;
}
static const struct country_info *
@@ -831,174 +703,67 @@ brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode,
return country;
}
-static int
-brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode,
- char *mapped_ccode, uint *mapped_regrev)
-{
- return false;
-}
-
-/* Lookup a country info structure from a null terminated country
- * abbreviation and regrev directly with no translation.
+/* Lookup a country info structure from a null terminated country code
+ * The lookup is case sensitive.
*/
static const struct country_info *
-brcms_c_country_lookup_direct(const char *ccode, uint regrev)
-{
- uint size, i;
-
- /* Should just return 0 for single locale driver. */
- /* Keep it this way in case we add more locales. (for now anyway) */
-
- /* all other country def arrays are for regrev == 0, so if regrev is non-zero, fail */
- if (regrev > 0)
- return NULL;
-
- /* find matched table entry from country code */
- size = ARRAY_SIZE(cntry_locales);
- for (i = 0; i < size; i++) {
- if (strcmp(ccode, cntry_locales[i].abbrev) == 0) {
- return &cntry_locales[i].country;
- }
- }
- return NULL;
-}
-
-static int
-brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
- const struct country_info *country)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- uint i, j;
- struct brcms_band *band;
- const struct locale_info *li;
- chanvec_t sup_chan;
- const struct locale_mimo_info *li_mimo;
-
- band = wlc->band;
- for (i = 0; i < NBANDS(wlc);
- i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
-
- li = BAND_5G(band->bandtype) ?
- brcms_c_get_locale_5g(country->locale_5G) :
- brcms_c_get_locale_2g(country->locale_2G);
- wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
- li_mimo = BAND_5G(band->bandtype) ?
- brcms_c_get_mimo_5g(country->locale_mimo_5G) :
- brcms_c_get_mimo_2g(country->locale_mimo_2G);
-
- /* merge the mimo non-mimo locale flags */
- wlc_cm->bandstate[band->bandunit].locale_flags |=
- li_mimo->flags;
-
- wlc_cm->bandstate[band->bandunit].restricted_channels =
- g_table_restricted_chan[li->restricted_channels];
- wlc_cm->bandstate[band->bandunit].radar_channels =
- g_table_radar_set[li->radar_channels];
-
- /* set the channel availability,
- * masking out the channels that may not be supported on this phy
- */
- wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
- &sup_chan);
- brcms_c_locale_get_channels(li,
- &wlc_cm->bandstate[band->bandunit].
- valid_channels);
- for (j = 0; j < sizeof(chanvec_t); j++)
- wlc_cm->bandstate[band->bandunit].valid_channels.
- vec[j] &= sup_chan.vec[j];
- }
-
- brcms_c_quiet_channels_reset(wlc_cm);
- brcms_c_channels_commit(wlc_cm);
-
- return 0;
-}
-
-/* Update the radio state (enable/disable) and tx power targets
- * based on a new set of channel/regulatory information
- */
-static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
+brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode)
{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- uint chan;
- struct txpwr_limits txpwr;
-
- /* search for the existence of any valid channel */
- for (chan = 0; chan < MAXCHANNEL; chan++) {
- if (VALID_CHANNEL20_DB(wlc, chan)) {
- break;
- }
- }
- if (chan == MAXCHANNEL)
- chan = INVCHANNEL;
-
- /* based on the channel search above, set or clear WL_RADIO_COUNTRY_DISABLE */
- if (chan == INVCHANNEL) {
- /* country/locale with no valid channels, set the radio disable bit */
- mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
- wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
- "nbands %d bandlocked %d\n", wlc->pub->unit,
- __func__, wlc_cm->country_abbrev, NBANDS(wlc),
- wlc->bandlocked);
- } else
- if (mboolisset(wlc->pub->radio_disabled,
- WL_RADIO_COUNTRY_DISABLE)) {
- /* country/locale with valid channel, clear the radio disable bit */
- mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
- }
+ const struct country_info *country;
+ char mapped_ccode[BRCM_CNTRY_BUF_SZ];
+ uint mapped_regrev;
- /* Now that the country abbreviation is set, if the radio supports 2G, then
- * set channel 14 restrictions based on the new locale.
+ /*
+ * map the country code to a built-in country code, regrev, and
+ * country_info struct
*/
- if (NBANDS(wlc) > 1 || BAND_2G(wlc->band->bandtype)) {
- wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
- brcms_c_japan(wlc) ? true :
- false);
- }
+ country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode,
+ &mapped_regrev);
- if (wlc->pub->up && chan != INVCHANNEL) {
- brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
- brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm,
- &txpwr, BRCMS_TXPWR_MAX);
- wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
- }
+ return country;
}
-/* reset the quiet channels vector to the union of the restricted and radar channel sets */
+/*
+ * reset the quiet channels vector to the union
+ * of the restricted and radar channel sets
+ */
static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
uint i, j;
struct brcms_band *band;
- const chanvec_t *chanvec;
+ const struct brcms_chanvec *chanvec;
- memset(&wlc_cm->quiet_channels, 0, sizeof(chanvec_t));
+ memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec));
band = wlc->band;
- for (i = 0; i < NBANDS(wlc);
+ for (i = 0; i < wlc->pub->_nbands;
i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
/* initialize quiet channels for restricted channels */
chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels;
- for (j = 0; j < sizeof(chanvec_t); j++)
+ for (j = 0; j < sizeof(struct brcms_chanvec); j++)
wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j];
}
}
-static bool
-brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, chanspec_t chspec)
+/* Is the channel valid for the current locale and current band? */
+static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val)
+{
+ struct brcms_c_info *wlc = wlc_cm->wlc;
+
+ return ((val < MAXCHANNEL) &&
+ isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
+ val));
+}
+
+/* Is the channel valid for the current locale and specified band? */
+static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
+ uint bandunit, uint val)
{
- return N_ENAB(wlc_cm->wlc->pub) && CHSPEC_IS40(chspec) ?
- (isset
- (wlc_cm->quiet_channels.vec,
- LOWER_20_SB(CHSPEC_CHANNEL(chspec)))
- || isset(wlc_cm->quiet_channels.vec,
- UPPER_20_SB(CHSPEC_CHANNEL(chspec)))) : isset(wlc_cm->
- quiet_channels.
- vec,
- CHSPEC_CHANNEL
- (chspec));
+ return ((val < MAXCHANNEL)
+ && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
}
/* Is the channel valid for the current locale? (but don't consider channels not
@@ -1008,27 +773,23 @@ static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
- return VALID_CHANNEL20(wlc, val) ||
+ return brcms_c_valid_channel20(wlc->cmi, val) ||
(!wlc->bandlocked
- && VALID_CHANNEL20_IN_BAND(wlc, OTHERBANDUNIT(wlc), val));
+ && brcms_c_valid_channel20_in_band(wlc->cmi,
+ OTHERBANDUNIT(wlc), val));
}
-/* Is the channel valid for the current locale and specified band? */
-static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit, uint val)
+/* JP, J1 - J10 are Japan ccodes */
+static bool brcms_c_japan_ccode(const char *ccode)
{
- return ((val < MAXCHANNEL)
- && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
+ return (ccode[0] == 'J' &&
+ (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
}
-/* Is the channel valid for the current locale and current band? */
-static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val)
+/* Returns true if currently set country is Japan or variant */
+static bool brcms_c_japan(struct brcms_c_info *wlc)
{
- struct brcms_c_info *wlc = wlc_cm->wlc;
-
- return ((val < MAXCHANNEL) &&
- isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
- val));
+ return brcms_c_japan_ccode(wlc->cmi->country_abbrev);
}
static void
@@ -1039,50 +800,42 @@ brcms_c_channel_min_txpower_limits_with_local_constraint(
int j;
/* CCK Rates */
- for (j = 0; j < WL_TX_POWER_CCK_NUM; j++) {
+ 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++) {
+ 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++) {
+ 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++) {
+ 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++) {
+ 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++) {
+ 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++) {
+ 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++) {
+ 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++)
@@ -1090,22 +843,19 @@ brcms_c_channel_min_txpower_limits_with_local_constraint(
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++) {
+ 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++) {
+ 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++) {
+ 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++)
@@ -1117,8 +867,276 @@ brcms_c_channel_min_txpower_limits_with_local_constraint(
}
+/* Update the radio state (enable/disable) and tx power targets
+ * based on a new set of channel/regulatory information
+ */
+static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
+{
+ struct brcms_c_info *wlc = wlc_cm->wlc;
+ uint chan;
+ struct txpwr_limits txpwr;
+
+ /* search for the existence of any valid channel */
+ for (chan = 0; chan < MAXCHANNEL; chan++) {
+ if (brcms_c_valid_channel20_db(wlc->cmi, chan))
+ break;
+ }
+ if (chan == MAXCHANNEL)
+ chan = INVCHANNEL;
+
+ /*
+ * based on the channel search above, set or
+ * clear WL_RADIO_COUNTRY_DISABLE.
+ */
+ if (chan == INVCHANNEL) {
+ /*
+ * country/locale with no valid channels, set
+ * the radio disable bit
+ */
+ mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+ wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
+ "nbands %d bandlocked %d\n", wlc->pub->unit,
+ __func__, wlc_cm->country_abbrev, wlc->pub->_nbands,
+ wlc->bandlocked);
+ } else if (mboolisset(wlc->pub->radio_disabled,
+ WL_RADIO_COUNTRY_DISABLE)) {
+ /*
+ * country/locale with valid channel, clear
+ * the radio disable bit
+ */
+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+ }
+
+ /*
+ * Now that the country abbreviation is set, if the radio supports 2G,
+ * then set channel 14 restrictions based on the new locale.
+ */
+ if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
+ wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
+ brcms_c_japan(wlc) ? true :
+ false);
+
+ if (wlc->pub->up && chan != INVCHANNEL) {
+ brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
+ brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm,
+ &txpwr, BRCMS_TXPWR_MAX);
+ wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
+ }
+}
+
+static int
+brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
+ const struct country_info *country)
+{
+ struct brcms_c_info *wlc = wlc_cm->wlc;
+ uint i, j;
+ struct brcms_band *band;
+ const struct locale_info *li;
+ struct brcms_chanvec sup_chan;
+ const struct locale_mimo_info *li_mimo;
+
+ band = wlc->band;
+ for (i = 0; i < wlc->pub->_nbands;
+ i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
+
+ li = (band->bandtype == BRCM_BAND_5G) ?
+ brcms_c_get_locale_5g(country->locale_5G) :
+ brcms_c_get_locale_2g(country->locale_2G);
+ wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
+ 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);
+
+ /* merge the mimo non-mimo locale flags */
+ wlc_cm->bandstate[band->bandunit].locale_flags |=
+ li_mimo->flags;
+
+ wlc_cm->bandstate[band->bandunit].restricted_channels =
+ g_table_restricted_chan[li->restricted_channels];
+ wlc_cm->bandstate[band->bandunit].radar_channels =
+ g_table_radar_set[li->radar_channels];
+
+ /*
+ * set the channel availability, masking out the channels
+ * that may not be supported on this phy.
+ */
+ wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
+ &sup_chan);
+ brcms_c_locale_get_channels(li,
+ &wlc_cm->bandstate[band->bandunit].
+ valid_channels);
+ for (j = 0; j < sizeof(struct brcms_chanvec); j++)
+ wlc_cm->bandstate[band->bandunit].valid_channels.
+ vec[j] &= sup_chan.vec[j];
+ }
+
+ brcms_c_quiet_channels_reset(wlc_cm);
+ brcms_c_channels_commit(wlc_cm);
+
+ return 0;
+}
+
+/*
+ * 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_common(struct brcms_cm_info *wlc_cm,
+ const char *country_abbrev,
+ const char *ccode, uint regrev,
+ const struct country_info *country)
+{
+ const struct locale_info *locale;
+ struct brcms_c_info *wlc = wlc_cm->wlc;
+ char prev_country_abbrev[BRCM_CNTRY_BUF_SZ];
+
+ /* save current country state */
+ wlc_cm->country = country;
+
+ memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
+ strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
+ BRCM_CNTRY_BUF_SZ - 1);
+
+ strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
+ strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
+ wlc_cm->regrev = regrev;
+
+ 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]);
+ /* set or restore gmode as required by regulatory */
+ locale = brcms_c_get_locale_2g(country->locale_2G);
+ if (locale && (locale->flags & BRCMS_NO_OFDM))
+ brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
+ else
+ brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
+
+ brcms_c_channels_init(wlc_cm, country);
+
+ return;
+}
+
+static int
+brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
+ const char *country_abbrev,
+ const char *ccode, int regrev)
+{
+ const struct country_info *country;
+ char mapped_ccode[BRCM_CNTRY_BUF_SZ];
+ uint mapped_regrev;
+
+ /* if regrev is -1, lookup the mapped country code,
+ * otherwise use the ccode and regrev directly
+ */
+ if (regrev == -1) {
+ /*
+ * map the country code to a built-in country
+ * code, regrev, and country_info
+ */
+ country =
+ brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode,
+ &mapped_regrev);
+ } else {
+ /* find the matching built-in country definition */
+ country = brcms_c_country_lookup_direct(ccode, regrev);
+ strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
+ mapped_regrev = regrev;
+ }
+
+ if (country == NULL)
+ return -EINVAL;
+
+ /* set the driver state for the country */
+ brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
+ mapped_regrev, country);
+
+ return 0;
+}
+
+/*
+ * set the driver's current country and regulatory information using
+ * a country code as the source. Lookup built in country information
+ * found with the country code.
+ */
+static int
+brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode)
+{
+ char country_abbrev[BRCM_CNTRY_BUF_SZ];
+ strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ);
+ return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1);
+}
+
+struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
+{
+ struct brcms_cm_info *wlc_cm;
+ char country_abbrev[BRCM_CNTRY_BUF_SZ];
+ const struct country_info *country;
+ struct brcms_pub *pub = wlc->pub;
+ char *ccode;
+
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+ 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 */
+ ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE);
+ if (ccode)
+ strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
+
+ /*
+ * internal country information which must match
+ * regulatory constraints in firmware
+ */
+ memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
+ strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
+ country = brcms_c_country_lookup(wlc, country_abbrev);
+
+ /* save default country for exiting 11d regulatory mode */
+ strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
+
+ /* initialize autocountry_default to driver default */
+ strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
+
+ brcms_c_set_countrycode(wlc_cm, country_abbrev);
+
+ return wlc_cm;
+}
+
+void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
+{
+ kfree(wlc_cm);
+}
+
+u8
+brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
+ uint bandunit)
+{
+ return wlc_cm->bandstate[bandunit].locale_flags;
+}
+
+static bool
+brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec)
+{
+ return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) &&
+ CHSPEC_IS40(chspec) ?
+ (isset(wlc_cm->quiet_channels.vec,
+ lower_20_sb(CHSPEC_CHANNEL(chspec))) ||
+ isset(wlc_cm->quiet_channels.vec,
+ upper_20_sb(CHSPEC_CHANNEL(chspec)))) :
+ isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec));
+}
+
void
-brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
+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;
@@ -1126,8 +1144,9 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
- brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm, &txpwr,
- local_constraint_qdbm);
+ brcms_c_channel_min_txpower_limits_with_local_constraint(
+ wlc_cm, &txpwr, local_constraint_qdbm
+ );
brcms_b_set_chanspec(wlc->hw, chanspec,
(brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0),
@@ -1142,112 +1161,100 @@ static void wlc_phy_txpower_limits_dump(struct txpwr_limits *txpwr)
char fraction[4][4] = { " ", ".25", ".5 ", ".75" };
sprintf(buf, "CCK ");
- for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->cck[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->cck[i] % BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz OFDM SISO ");
- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm[i] % BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz OFDM CDD ");
- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm_cdd[i] % BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz OFDM SISO ");
- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm_40_siso[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm_40_siso[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz OFDM CDD ");
- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm_40_cdd[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS0-7 SISO ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_siso[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_siso[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS0-7 CDD ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_cdd[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS0-7 STBC ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_stbc[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_stbc[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS8-15 SDM ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_mimo[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_mimo[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS0-7 SISO ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_siso[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_siso[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS0-7 CDD ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_cdd[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS0-7 STBC ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_stbc[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_stbc[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS8-15 SDM ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_mimo[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_mimo[i] %
@@ -1262,7 +1269,7 @@ static void wlc_phy_txpower_limits_dump(struct txpwr_limits *txpwr)
#endif /* POWER_DBG */
void
-brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
+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;
@@ -1273,8 +1280,8 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
const struct country_info *country;
struct brcms_band *band;
const struct locale_info *li;
- int conducted_max;
- int conducted_ofdm_max;
+ int conducted_max = BRCMS_TXPWR_MAX;
+ int conducted_ofdm_max = BRCMS_TXPWR_MAX;
const struct locale_mimo_info *li_mimo;
int maxpwr20, maxpwr40;
int maxpwr_idx;
@@ -1291,12 +1298,12 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
}
chan = CHSPEC_CHANNEL(chanspec);
- band = wlc->bandstate[CHSPEC_BANDUNIT(chanspec)];
- li = BAND_5G(band->bandtype) ?
+ band = wlc->bandstate[chspec_bandunit(chanspec)];
+ li = (band->bandtype == BRCM_BAND_5G) ?
brcms_c_get_locale_5g(country->locale_5G) :
brcms_c_get_locale_2g(country->locale_2G);
- li_mimo = BAND_5G(band->bandtype) ?
+ 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);
@@ -1314,7 +1321,7 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
}
/* CCK txpwr limits for 2.4G band */
- if (BAND_2G(band->bandtype)) {
+ if (band->bandtype == BRCM_BAND_2G) {
maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)];
maxpwr = maxpwr - delta;
@@ -1326,29 +1333,29 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
}
/* OFDM txpwr limits for 2.4G or 5G bands */
- if (BAND_2G(band->bandtype)) {
+ if (band->bandtype == BRCM_BAND_2G)
maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)];
-
- } else {
+ else
maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)];
- }
maxpwr = maxpwr - delta;
maxpwr = max(maxpwr, 0);
maxpwr = min(maxpwr, conducted_ofdm_max);
/* Keep OFDM lmit below CCK limit */
- if (BAND_2G(band->bandtype))
+ if (band->bandtype == BRCM_BAND_2G)
maxpwr = min_t(int, maxpwr, txpwr->cck[0]);
for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
txpwr->ofdm[i] = (u8) maxpwr;
for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
- /* 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.
+ /*
+ * 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;
@@ -1366,7 +1373,7 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
delta = band->antgain - QDB(6); /* Excess over 6 dB */
}
- if (BAND_2G(band->bandtype))
+ if (band->bandtype == BRCM_BAND_2G)
maxpwr_idx = (chan - 1);
else
maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
@@ -1382,8 +1389,9 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
/* 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.
+ /*
+ * 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;
@@ -1395,15 +1403,17 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
}
- /* These locales have SISO expressed in the table and override CDD later */
+ /*
+ * 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) {
+ if (chan >= 3 && chan <= 11)
maxpwr40 = QDB(16);
- }
}
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
@@ -1437,10 +1447,10 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
}
}
- /* Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO value if it wasn't
- * provided explicitly.
+ /*
+ * 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];
@@ -1456,8 +1466,9 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
}
}
- /* Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding STBC values if they weren't
- * provided explicitly.
+ /*
+ * 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)
@@ -1473,73 +1484,94 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
return;
}
-/* Returns true if currently set country is Japan or variant */
-static bool brcms_c_japan(struct brcms_c_info *wlc)
+/*
+ * 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)
{
- return brcms_c_japan_ccode(wlc->cmi->country_abbrev);
-}
+ /* 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;
+ }
-/* 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')));
+ 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
+ * 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, chanspec_t chspec,
+brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
bool dualband)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
u8 channel = CHSPEC_CHANNEL(chspec);
/* check the chanspec */
- if (brcmu_chspec_malformed(chspec)) {
+ if (brcms_c_chspec_malformed(chspec)) {
wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
wlc->pub->unit, chspec);
return false;
}
if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
- CHSPEC_BANDUNIT(chspec))
+ chspec_bandunit(chspec))
return false;
/* Check a 20Mhz channel */
if (CHSPEC_IS20(chspec)) {
if (dualband)
- return VALID_CHANNEL20_DB(wlc_cm->wlc, channel);
+ return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi,
+ channel);
else
- return VALID_CHANNEL20(wlc_cm->wlc, channel);
+ return brcms_c_valid_channel20(wlc_cm->wlc->cmi,
+ channel);
}
#ifdef SUPPORT_40MHZ
- /* We know we are now checking a 40MHZ channel, so we should only be here
- * for NPHYS
+ /*
+ * We know we are now checking a 40MHZ channel, so we should
+ * only be here for NPHYS
*/
if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) {
u8 upper_sideband = 0, idx;
u8 num_ch20_entries =
sizeof(chan20_info) / sizeof(struct chan20_info);
- if (!VALID_40CHANSPEC_IN_BAND(wlc, CHSPEC_BANDUNIT(chspec)))
+ if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec)))
return false;
if (dualband) {
- if (!VALID_CHANNEL20_DB(wlc, LOWER_20_SB(channel)) ||
- !VALID_CHANNEL20_DB(wlc, UPPER_20_SB(channel)))
+ if (!brcms_c_valid_channel20_db(wlc->cmi,
+ lower_20_sb(channel)) ||
+ !brcms_c_valid_channel20_db(wlc->cmi,
+ upper_20_sb(channel)))
return false;
} else {
- if (!VALID_CHANNEL20(wlc, LOWER_20_SB(channel)) ||
- !VALID_CHANNEL20(wlc, UPPER_20_SB(channel)))
+ if (!brcms_c_valid_channel20(wlc->cmi,
+ lower_20_sb(channel)) ||
+ !brcms_c_valid_channel20(wlc->cmi,
+ upper_20_sb(channel)))
return false;
}
/* find the lower sideband info in the sideband array */
for (idx = 0; idx < num_ch20_entries; idx++) {
- if (chan20_info[idx].sb == LOWER_20_SB(channel))
+ if (chan20_info[idx].sb == lower_20_sb(channel))
upper_sideband = chan20_info[idx].adj_sbs;
}
/* check that the lower sideband allows an upper sideband */
@@ -1553,7 +1585,7 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, chanspec_t chspec,
return false;
}
-bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, chanspec_t chspec)
+bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
{
return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true);
}
diff --git a/drivers/staging/brcm80211/brcmsmac/channel.h b/drivers/staging/brcm80211/brcmsmac/channel.h
index d22f2f5f592d..808cb4fbfbe7 100644
--- a/drivers/staging/brcm80211/brcmsmac/channel.h
+++ b/drivers/staging/brcm80211/brcmsmac/channel.h
@@ -20,59 +20,6 @@
/* conversion for phy txpwr calculations that use .25 dB units */
#define BRCMS_TXPWR_DB_FACTOR 4
-
-/* 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 */
-
-/* power level in group of 2.4GHz band channels:
- * maxpwr[0] - CCK channels [1]
- * maxpwr[1] - CCK channels [2-10]
- * maxpwr[2] - CCK channels [11-14]
- * maxpwr[3] - OFDM channels [1]
- * maxpwr[4] - OFDM channels [2-10]
- * maxpwr[5] - OFDM channels [11-14]
- */
-
-/* macro to get 2.4 GHz channel group index for tx power */
-#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2)) /* cck index */
-#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5)) /* ofdm index */
-
-/* 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))))
-
-/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
-#define BRCMS_MAXPWR_TBL_SIZE 6
-/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
-#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14
-
-#define NBANDS(wlc) ((wlc)->pub->_nbands)
-#define NBANDS_PUB(pub) ((pub)->_nbands)
-#define NBANDS_HW(hw) ((hw)->_nbands)
-
-#define IS_SINGLEBAND_5G(device) 0
-
-/* locale channel and power info. */
-struct locale_info {
- u32 valid_channels;
- /* List of radar sensitive channels */
- u8 radar_channels;
- /* List of channels used only if APs are detected */
- u8 restricted_channels;
- /* Max tx pwr in qdBm for each sub-band */
- s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE];
- s8 pub_maxpwr[BAND_5G_PWR_LVLS]; /* Country IE advertised max tx pwr in dBm
- * per sub-band
- */
- u8 flags;
-};
-
/* bits for locale_info flags */
#define BRCMS_PEAK_CONDUCTED 0x00 /* Peak for locals */
#define BRCMS_EIRP 0x01 /* Flag for EIRP */
@@ -82,34 +29,8 @@ struct locale_info {
#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 */
-
-#define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU)
-
-/* 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];
- u8 flags;
-};
-extern const chanvec_t chanvec_all_2G;
-extern const chanvec_t chanvec_all_5G;
-
-/*
- * Country names and abbreviations with locale defined from ISO 3166
- */
-struct country_info {
- const u8 locale_2G; /* 2.4G band locale */
- const u8 locale_5G; /* 5G band locale */
- const u8 locale_mimo_2G; /* 2.4G mimo info */
- const u8 locale_mimo_5G; /* 5G mimo info */
-};
+#define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */
extern struct brcms_cm_info *
brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
@@ -120,13 +41,13 @@ extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
uint bandunit);
extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm,
- chanspec_t chspec);
+ u16 chspec);
extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm,
- chanspec_t chanspec,
+ u16 chanspec,
struct txpwr_limits *txpwr);
extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm,
- chanspec_t chanspec,
+ u16 chanspec,
u8 local_constraint_qdbm);
#endif /* _WLC_CHANNEL_H */
diff --git a/drivers/staging/brcm80211/brcmsmac/d11.h b/drivers/staging/brcm80211/brcmsmac/d11.h
index e7ff0e6f28e0..ed51616abc85 100644
--- a/drivers/staging/brcm80211/brcmsmac/d11.h
+++ b/drivers/staging/brcm80211/brcmsmac/d11.h
@@ -23,17 +23,15 @@
#include "pub.h"
#include "dma.h"
-#define BCN_TMPL_LEN 512 /* length of the BCN template area */
-
/* RX FIFO numbers */
#define RX_FIFO 0 /* data and ctl frames */
#define RX_TXSTATUS_FIFO 3 /* RX fifo for tx status packages */
-/* TX FIFO numbers using WME Access Classes */
-#define TX_AC_BK_FIFO 0 /* Access Category Background TX FIFO */
-#define TX_AC_BE_FIFO 1 /* Access Category Best-Effort TX FIFO */
-#define TX_AC_VI_FIFO 2 /* Access Class Video TX FIFO */
-#define TX_AC_VO_FIFO 3 /* Access Class Voice TX FIFO */
+/* TX FIFO numbers using WME Access Category */
+#define TX_AC_BK_FIFO 0 /* Background TX FIFO */
+#define TX_AC_BE_FIFO 1 /* Best-Effort TX FIFO */
+#define TX_AC_VI_FIFO 2 /* Video TX FIFO */
+#define TX_AC_VO_FIFO 3 /* Voice TX FIFO */
#define TX_BCMC_FIFO 4 /* Broadcast/Multicast TX FIFO */
#define TX_ATIM_FIFO 5 /* TX fifo for ATIM window info */
@@ -47,11 +45,7 @@
#define TX_DATA_FIFO TX_AC_BE_FIFO
#define TX_CTL_FIFO TX_AC_VO_FIFO
-#ifndef WL_RSSI_ANT_MAX
#define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */
-#elif WL_RSSI_ANT_MAX != 4
-#error "WL_RSSI_ANT_MAX does not match"
-#endif
struct intctrlregs {
u32 intstatus;
@@ -73,8 +67,8 @@ struct pio2regs {
/* a pair of pio channels(tx and rx) */
struct pio2regp {
- pio2regs_t tx;
- pio2regs_t rx;
+ struct pio2regs tx;
+ struct pio2regs rx;
};
/* 4byte-wide pio register set per channel(xmt or rcv) */
@@ -85,8 +79,8 @@ struct pio4regs {
/* a pair of pio channels(tx and rx) */
struct pio4regp {
- pio4regs_t tx;
- pio4regs_t rx;
+ struct pio4regs tx;
+ struct pio4regs rx;
};
/* read: 32-bit register that can be read as 32-bit or as 2 16-bit
@@ -101,10 +95,10 @@ union pmqreg {
};
struct fifo64 {
- dma64regs_t dmaxmt; /* dma tx */
- pio4regs_t piotx; /* pio tx */
- dma64regs_t dmarcv; /* dma rx */
- pio4regs_t piorx; /* pio rx */
+ struct dma64regs dmaxmt; /* dma tx */
+ struct pio4regs piotx; /* pio tx */
+ struct dma64regs dmarcv; /* dma rx */
+ struct pio4regs piorx; /* pio rx */
};
/*
@@ -120,7 +114,7 @@ struct d11regs {
u32 usectimer; /* 0x1c *//* for corerev >= 26 */
/* Interrupt Control *//* 0x20 */
- intctrlregs_t intctrlregs[8];
+ struct intctrlregs intctrlregs[8];
u32 PAD[40]; /* 0x60 - 0xFC */
@@ -139,7 +133,7 @@ struct d11regs {
u32 PAD[2]; /* 0x138 - 0x13C */
/* PMQ registers */
- pmqreg_t pmqreg; /* 0x140 */
+ union pmqreg pmqreg; /* 0x140 */
u32 pmqpatl; /* 0x144 */
u32 pmqpath; /* 0x148 */
u32 PAD; /* 0x14C */
@@ -179,10 +173,10 @@ struct d11regs {
u32 PAD[5]; /* 0x1ec - 0x1fc */
/* 0x200-0x37F dma/pio registers */
- fifo64_t fifo64regs[6];
+ struct fifo64 fifo64regs[6];
/* FIFO diagnostic port access */
- dma32diag_t dmafifo; /* 0x380 - 0x38C */
+ struct dma32diag dmafifo; /* 0x380 - 0x38C */
u32 aggfifocnt; /* 0x390 */
u32 aggfifodata; /* 0x394 */
@@ -457,7 +451,7 @@ struct d11regs {
#define IRL_FC_MASK 0xff000000 /* frame count */
#define IRL_FC_SHIFT 24 /* frame count */
-/* maccontrol register */
+/*== maccontrol register ==*/
#define MCTL_GMODE (1U << 31)
#define MCTL_DISCARD_PMQ (1 << 30)
#define MCTL_WAKE (1 << 26)
@@ -481,75 +475,119 @@ struct d11regs {
#define MCTL_PSM_RUN (1 << 1)
#define MCTL_EN_MAC (1 << 0)
-/* maccommand register */
+/*== maccommand register ==*/
#define MCMD_BCN0VLD (1 << 0)
#define MCMD_BCN1VLD (1 << 1)
#define MCMD_DIRFRMQVAL (1 << 2)
#define MCMD_CCA (1 << 3)
#define MCMD_BG_NOISE (1 << 4)
#define MCMD_SKIP_SHMINIT (1 << 5) /* only used for simulation */
-#define MCMD_SAMPLECOLL MCMD_SKIP_SHMINIT /* reuse for sample collect */
-
-/* macintstatus/macintmask */
-#define MI_MACSSPNDD (1 << 0) /* MAC has gracefully suspended */
-#define MI_BCNTPL (1 << 1) /* beacon template available */
-#define MI_TBTT (1 << 2) /* TBTT indication */
-#define MI_BCNSUCCESS (1 << 3) /* beacon successfully tx'd */
-#define MI_BCNCANCLD (1 << 4) /* beacon canceled (IBSS) */
-#define MI_ATIMWINEND (1 << 5) /* end of ATIM-window (IBSS) */
-#define MI_PMQ (1 << 6) /* PMQ entries available */
-#define MI_NSPECGEN_0 (1 << 7) /* non-specific gen-stat bits that are set by PSM */
-#define MI_NSPECGEN_1 (1 << 8) /* non-specific gen-stat bits that are set by PSM */
-#define MI_MACTXERR (1 << 9) /* MAC level Tx error */
-#define MI_NSPECGEN_3 (1 << 10) /* non-specific gen-stat bits that are set by PSM */
-#define MI_PHYTXERR (1 << 11) /* PHY Tx error */
-#define MI_PME (1 << 12) /* Power Management Event */
-#define MI_GP0 (1 << 13) /* General-purpose timer0 */
-#define MI_GP1 (1 << 14) /* General-purpose timer1 */
-#define MI_DMAINT (1 << 15) /* (ORed) DMA-interrupts */
-#define MI_TXSTOP (1 << 16) /* MAC has completed a TX FIFO Suspend/Flush */
-#define MI_CCA (1 << 17) /* MAC has completed a CCA measurement */
-#define MI_BG_NOISE (1 << 18) /* MAC has collected background noise samples */
-#define MI_DTIM_TBTT (1 << 19) /* MBSS DTIM TBTT indication */
-#define MI_PRQ (1 << 20) /* Probe response queue needs attention */
-#define MI_PWRUP (1 << 21) /* Radio/PHY has been powered back up. */
+#define MCMD_SAMPLECOLL MCMD_SKIP_SHMINIT /* reuse for sample collect */
+
+/*== macintstatus/macintmask ==*/
+/* gracefully suspended */
+#define MI_MACSSPNDD (1 << 0)
+/* beacon template available */
+#define MI_BCNTPL (1 << 1)
+/* TBTT indication */
+#define MI_TBTT (1 << 2)
+/* beacon successfully tx'd */
+#define MI_BCNSUCCESS (1 << 3)
+/* beacon canceled (IBSS) */
+#define MI_BCNCANCLD (1 << 4)
+/* end of ATIM-window (IBSS) */
+#define MI_ATIMWINEND (1 << 5)
+/* PMQ entries available */
+#define MI_PMQ (1 << 6)
+/* non-specific gen-stat bits that are set by PSM */
+#define MI_NSPECGEN_0 (1 << 7)
+/* non-specific gen-stat bits that are set by PSM */
+#define MI_NSPECGEN_1 (1 << 8)
+/* MAC level Tx error */
+#define MI_MACTXERR (1 << 9)
+/* non-specific gen-stat bits that are set by PSM */
+#define MI_NSPECGEN_3 (1 << 10)
+/* PHY Tx error */
+#define MI_PHYTXERR (1 << 11)
+/* Power Management Event */
+#define MI_PME (1 << 12)
+/* General-purpose timer0 */
+#define MI_GP0 (1 << 13)
+/* General-purpose timer1 */
+#define MI_GP1 (1 << 14)
+/* (ORed) DMA-interrupts */
+#define MI_DMAINT (1 << 15)
+/* MAC has completed a TX FIFO Suspend/Flush */
+#define MI_TXSTOP (1 << 16)
+/* MAC has completed a CCA measurement */
+#define MI_CCA (1 << 17)
+/* MAC has collected background noise samples */
+#define MI_BG_NOISE (1 << 18)
+/* MBSS DTIM TBTT indication */
+#define MI_DTIM_TBTT (1 << 19)
+/* Probe response queue needs attention */
+#define MI_PRQ (1 << 20)
+/* Radio/PHY has been powered back up. */
+#define MI_PWRUP (1 << 21)
#define MI_RESERVED3 (1 << 22)
#define MI_RESERVED2 (1 << 23)
#define MI_RESERVED1 (1 << 25)
/* MAC detected change on RF Disable input*/
#define MI_RFDISABLE (1 << 28)
-#define MI_TFS (1 << 29) /* MAC has completed a TX */
-#define MI_PHYCHANGED (1 << 30) /* A phy status change wrt G mode */
-#define MI_TO (1U << 31) /* general purpose timeout */
+/* MAC has completed a TX */
+#define MI_TFS (1 << 29)
+/* A phy status change wrt G mode */
+#define MI_PHYCHANGED (1 << 30)
+/* general purpose timeout */
+#define MI_TO (1U << 31)
/* Mac capabilities registers */
-/* machwcap */
+/*== machwcap ==*/
#define MCAP_TKIPMIC 0x80000000 /* TKIP MIC hardware present */
-/* pmqhost data */
-#define PMQH_DATA_MASK 0xffff0000 /* data entry of head pmq entry */
-#define PMQH_BSSCFG 0x00100000 /* PM entry for BSS config */
-#define PMQH_PMOFF 0x00010000 /* PM Mode OFF: power save off */
-#define PMQH_PMON 0x00020000 /* PM Mode ON: power save on */
-#define PMQH_DASAT 0x00040000 /* Dis-associated or De-authenticated */
-#define PMQH_ATIMFAIL 0x00080000 /* ATIM not acknowledged */
-#define PMQH_DEL_ENTRY 0x00000001 /* delete head entry */
-#define PMQH_DEL_MULT 0x00000002 /* delete head entry to cur read pointer -1 */
-#define PMQH_OFLO 0x00000004 /* pmq overflow indication */
-#define PMQH_NOT_EMPTY 0x00000008 /* entries are present in pmq */
-
-/* phydebug */
-#define PDBG_CRS (1 << 0) /* phy is asserting carrier sense */
-#define PDBG_TXA (1 << 1) /* phy is taking xmit byte from mac this cycle */
-#define PDBG_TXF (1 << 2) /* mac is instructing the phy to transmit a frame */
-#define PDBG_TXE (1 << 3) /* phy is signalling a transmit Error to the mac */
-#define PDBG_RXF (1 << 4) /* phy detected the end of a valid frame preamble */
-#define PDBG_RXS (1 << 5) /* phy detected the end of a valid PLCP header */
-#define PDBG_RXFRG (1 << 6) /* rx start not asserted */
-#define PDBG_RXV (1 << 7) /* mac is taking receive byte from phy this cycle */
-#define PDBG_RFD (1 << 16) /* RF portion of the radio is disabled */
-
-/* objaddr register */
+/*== pmqhost data ==*/
+/* data entry of head pmq entry */
+#define PMQH_DATA_MASK 0xffff0000
+/* PM entry for BSS config */
+#define PMQH_BSSCFG 0x00100000
+/* PM Mode OFF: power save off */
+#define PMQH_PMOFF 0x00010000
+/* PM Mode ON: power save on */
+#define PMQH_PMON 0x00020000
+/* Dis-associated or De-authenticated */
+#define PMQH_DASAT 0x00040000
+/* ATIM not acknowledged */
+#define PMQH_ATIMFAIL 0x00080000
+/* delete head entry */
+#define PMQH_DEL_ENTRY 0x00000001
+/* delete head entry to cur read pointer -1 */
+#define PMQH_DEL_MULT 0x00000002
+/* pmq overflow indication */
+#define PMQH_OFLO 0x00000004
+/* entries are present in pmq */
+#define PMQH_NOT_EMPTY 0x00000008
+
+/*== phydebug ==*/
+/* phy is asserting carrier sense */
+#define PDBG_CRS (1 << 0)
+/* phy is taking xmit byte from mac this cycle */
+#define PDBG_TXA (1 << 1)
+/* mac is instructing the phy to transmit a frame */
+#define PDBG_TXF (1 << 2)
+/* phy is signalling a transmit Error to the mac */
+#define PDBG_TXE (1 << 3)
+/* phy detected the end of a valid frame preamble */
+#define PDBG_RXF (1 << 4)
+/* phy detected the end of a valid PLCP header */
+#define PDBG_RXS (1 << 5)
+/* rx start not asserted */
+#define PDBG_RXFRG (1 << 6)
+/* mac is taking receive byte from phy this cycle */
+#define PDBG_RXV (1 << 7)
+/* RF portion of the radio is disabled */
+#define PDBG_RFD (1 << 16)
+
+/*== objaddr register ==*/
#define OBJADDR_SEL_MASK 0x000F0000
#define OBJADDR_UCM_SEL 0x00000000
#define OBJADDR_SHM_SEL 0x00010000
@@ -564,20 +602,20 @@ struct d11regs {
#define WEP_PCMADDR 0x07d4
#define WEP_PCMDATA 0x07d6
-/* frmtxstatus */
+/*== frmtxstatus ==*/
#define TXS_V (1 << 0) /* valid bit */
#define TXS_STATUS_MASK 0xffff
#define TXS_FID_MASK 0xffff0000
#define TXS_FID_SHIFT 16
-/* frmtxstatus2 */
+/*== frmtxstatus2 ==*/
#define TXS_SEQ_MASK 0xffff
#define TXS_PTX_MASK 0xff0000
#define TXS_PTX_SHIFT 16
#define TXS_MU_MASK 0x01000000
#define TXS_MU_SHIFT 24
-/* clk_ctl_st */
+/*== clk_ctl_st ==*/
#define CCS_ERSRC_REQ_D11PLL 0x00000100 /* d11 core pll request */
#define CCS_ERSRC_REQ_PHYPLL 0x00000200 /* PHY pll request */
#define CCS_ERSRC_AVAIL_D11PLL 0x01000000 /* d11 core pll available */
@@ -602,22 +640,27 @@ struct d11regs {
#define TXFIFO_SIZE_UNIT 256 /* one unit corresponds to 256 bytes */
#define MBSS16_TEMPLMEM_MINBLKS 65 /* one unit corresponds to 256 bytes */
-/* phy versions, PhyVersion:Revision field */
-#define PV_AV_MASK 0xf000 /* analog block version */
-#define PV_AV_SHIFT 12 /* analog block version bitfield offset */
-#define PV_PT_MASK 0x0f00 /* phy type */
-#define PV_PT_SHIFT 8 /* phy type bitfield offset */
-#define PV_PV_MASK 0x000f /* phy version */
+/*== phy versions (PhyVersion:Revision field) ==*/
+/* analog block version */
+#define PV_AV_MASK 0xf000
+/* analog block version bitfield offset */
+#define PV_AV_SHIFT 12
+/* phy type */
+#define PV_PT_MASK 0x0f00
+/* phy type bitfield offset */
+#define PV_PT_SHIFT 8
+/* phy version */
+#define PV_PV_MASK 0x000f
#define PHY_TYPE(v) ((v & PV_PT_MASK) >> PV_PT_SHIFT)
-/* phy types, PhyVersion:PhyType field */
+/*== phy types (PhyVersion:PhyType field) ==*/
#define PHY_TYPE_N 4 /* N-Phy value */
#define PHY_TYPE_SSN 6 /* SSLPN-Phy value */
#define PHY_TYPE_LCN 8 /* LCN-Phy value */
#define PHY_TYPE_LCNXN 9 /* LCNXN-Phy value */
#define PHY_TYPE_NULL 0xf /* Invalid Phy value */
-/* analog types, PhyVersion:AnalogType field */
+/*== analog types (PhyVersion:AnalogType field) ==*/
#define ANA_11N_013 5
/* 802.11a PLCP header def */
@@ -693,45 +736,46 @@ struct cck_phy_hdr {
#define BRCMS_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU)
#define BRCMS_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU)
-/* The dot11a PLCP header is 5 bytes. To simplify the software (so that we
- * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header has
- * padding added in the ucode.
+/*
+ * The dot11a PLCP header is 5 bytes. To simplify the software (so that we
+ * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header
+ * has padding added in the ucode.
*/
#define D11_PHY_HDR_LEN 6
/* TX DMA buffer header */
struct d11txh {
- u16 MacTxControlLow; /* 0x0 */
- u16 MacTxControlHigh; /* 0x1 */
- u16 MacFrameControl; /* 0x2 */
- u16 TxFesTimeNormal; /* 0x3 */
- u16 PhyTxControlWord; /* 0x4 */
- u16 PhyTxControlWord_1; /* 0x5 */
- u16 PhyTxControlWord_1_Fbr; /* 0x6 */
- u16 PhyTxControlWord_1_Rts; /* 0x7 */
- u16 PhyTxControlWord_1_FbrRts; /* 0x8 */
- u16 MainRates; /* 0x9 */
- u16 XtraFrameTypes; /* 0xa */
+ __le16 MacTxControlLow; /* 0x0 */
+ __le16 MacTxControlHigh; /* 0x1 */
+ __le16 MacFrameControl; /* 0x2 */
+ __le16 TxFesTimeNormal; /* 0x3 */
+ __le16 PhyTxControlWord; /* 0x4 */
+ __le16 PhyTxControlWord_1; /* 0x5 */
+ __le16 PhyTxControlWord_1_Fbr; /* 0x6 */
+ __le16 PhyTxControlWord_1_Rts; /* 0x7 */
+ __le16 PhyTxControlWord_1_FbrRts; /* 0x8 */
+ __le16 MainRates; /* 0x9 */
+ __le16 XtraFrameTypes; /* 0xa */
u8 IV[16]; /* 0x0b - 0x12 */
u8 TxFrameRA[6]; /* 0x13 - 0x15 */
- u16 TxFesTimeFallback; /* 0x16 */
+ __le16 TxFesTimeFallback; /* 0x16 */
u8 RTSPLCPFallback[6]; /* 0x17 - 0x19 */
- u16 RTSDurFallback; /* 0x1a */
+ __le16 RTSDurFallback; /* 0x1a */
u8 FragPLCPFallback[6]; /* 0x1b - 1d */
- u16 FragDurFallback; /* 0x1e */
- u16 MModeLen; /* 0x1f */
- u16 MModeFbrLen; /* 0x20 */
- u16 TstampLow; /* 0x21 */
- u16 TstampHigh; /* 0x22 */
- u16 ABI_MimoAntSel; /* 0x23 */
- u16 PreloadSize; /* 0x24 */
- u16 AmpduSeqCtl; /* 0x25 */
- u16 TxFrameID; /* 0x26 */
- u16 TxStatus; /* 0x27 */
- u16 MaxNMpdus; /* 0x28 */
- u16 MaxABytes_MRT; /* 0x29 */
- u16 MaxABytes_FBR; /* 0x2a */
- u16 MinMBytes; /* 0x2b */
+ __le16 FragDurFallback; /* 0x1e */
+ __le16 MModeLen; /* 0x1f */
+ __le16 MModeFbrLen; /* 0x20 */
+ __le16 TstampLow; /* 0x21 */
+ __le16 TstampHigh; /* 0x22 */
+ __le16 ABI_MimoAntSel; /* 0x23 */
+ __le16 PreloadSize; /* 0x24 */
+ __le16 AmpduSeqCtl; /* 0x25 */
+ __le16 TxFrameID; /* 0x26 */
+ __le16 TxStatus; /* 0x27 */
+ __le16 MaxNMpdus; /* 0x28 */
+ __le16 MaxABytes_MRT; /* 0x29 */
+ __le16 MaxABytes_FBR; /* 0x2a */
+ __le16 MinMBytes; /* 0x2b */
u8 RTSPhyHeader[D11_PHY_HDR_LEN]; /* 0x2c - 0x2e */
struct ieee80211_rts rts_frame; /* 0x2f - 0x36 */
u16 PAD; /* 0x37 */
@@ -745,14 +789,17 @@ struct d11txh {
#define FT_HT 2
#define FT_N 3
-/* Position of MPDU inside A-MPDU; indicated with bits 10:9 of MacTxControlLow */
+/*
+ * Position of MPDU inside A-MPDU; indicated with bits 10:9
+ * of MacTxControlLow
+ */
#define TXC_AMPDU_SHIFT 9 /* shift for ampdu settings */
#define TXC_AMPDU_NONE 0 /* Regular MPDU, not an A-MPDU */
#define TXC_AMPDU_FIRST 1 /* first MPDU of an A-MPDU */
#define TXC_AMPDU_MIDDLE 2 /* intermediate MPDU of an A-MPDU */
#define TXC_AMPDU_LAST 3 /* last (or single) MPDU of an A-MPDU */
-/* MacTxControlLow */
+/*== MacTxControlLow ==*/
#define TXC_AMIC 0x8000
#define TXC_SENDCTS 0x0800
#define TXC_AMPDU_MASK 0x0600
@@ -766,18 +813,25 @@ struct d11txh {
#define TXC_LONGFRAME 0x0002
#define TXC_IMMEDACK 0x0001
-/* MacTxControlHigh */
-#define TXC_PREAMBLE_RTS_FB_SHORT 0x8000 /* RTS fallback preamble type 1 = SHORT 0 = LONG */
-#define TXC_PREAMBLE_RTS_MAIN_SHORT 0x4000 /* RTS main rate preamble type 1 = SHORT 0 = LONG */
-#define TXC_PREAMBLE_DATA_FB_SHORT 0x2000 /* Main fallback rate preamble type
- * 1 = SHORT for OFDM/GF for MIMO
- * 0 = LONG for CCK/MM for MIMO
- */
+/*== MacTxControlHigh ==*/
+/* RTS fallback preamble type 1 = SHORT 0 = LONG */
+#define TXC_PREAMBLE_RTS_FB_SHORT 0x8000
+/* RTS main rate preamble type 1 = SHORT 0 = LONG */
+#define TXC_PREAMBLE_RTS_MAIN_SHORT 0x4000
+/*
+ * Main fallback rate preamble type
+ * 1 = SHORT for OFDM/GF for MIMO
+ * 0 = LONG for CCK/MM for MIMO
+ */
+#define TXC_PREAMBLE_DATA_FB_SHORT 0x2000
+
/* TXC_PREAMBLE_DATA_MAIN is in PhyTxControl bit 5 */
-#define TXC_AMPDU_FBR 0x1000 /* use fallback rate for this AMPDU */
+/* use fallback rate for this AMPDU */
+#define TXC_AMPDU_FBR 0x1000
#define TXC_SECKEY_MASK 0x0FF0
#define TXC_SECKEY_SHIFT 4
-#define TXC_ALT_TXPWR 0x0008 /* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */
+/* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */
+#define TXC_ALT_TXPWR 0x0008
#define TXC_SECTYPE_MASK 0x0007
#define TXC_SECTYPE_SHIFT 0
@@ -817,7 +871,7 @@ struct d11txh {
#define PHY_TXC1_MODE_SDM 3
/* PhyTxControl for HTphy that are different from Mimophy */
-#define PHY_TXC_HTANT_MASK 0x3fC0 /* bit 6, 7, 8, 9, 10, 11, 12, 13 */
+#define PHY_TXC_HTANT_MASK 0x3fC0 /* bits 6-13 */
/* XtraFrameTypes */
#define XFTS_RTS_FT_SHIFT 2
@@ -862,23 +916,23 @@ struct tx_status {
#define TX_STATUS_RTS_RTX_MASK 0x0F00
#define TX_STATUS_RTS_RTX_SHIFT 8
#define TX_STATUS_MASK 0x00FE
-#define TX_STATUS_PMINDCTD (1 << 7) /* PM mode indicated to AP */
-#define TX_STATUS_INTERMEDIATE (1 << 6) /* intermediate or 1st ampdu pkg */
-#define TX_STATUS_AMPDU (1 << 5) /* AMPDU status */
-#define TX_STATUS_SUPR_MASK 0x1C /* suppress status bits (4:2) */
+#define TX_STATUS_PMINDCTD (1 << 7) /* PM mode indicated to AP */
+#define TX_STATUS_INTERMEDIATE (1 << 6) /* intermediate or 1st ampdu pkg */
+#define TX_STATUS_AMPDU (1 << 5) /* AMPDU status */
+#define TX_STATUS_SUPR_MASK 0x1C /* suppress status bits (4:2) */
#define TX_STATUS_SUPR_SHIFT 2
-#define TX_STATUS_ACK_RCV (1 << 1) /* ACK received */
-#define TX_STATUS_VALID (1 << 0) /* Tx status valid */
+#define TX_STATUS_ACK_RCV (1 << 1) /* ACK received */
+#define TX_STATUS_VALID (1 << 0) /* Tx status valid */
#define TX_STATUS_NO_ACK 0
/* suppress status reason codes */
-#define TX_STATUS_SUPR_PMQ (1 << 2) /* PMQ entry */
-#define TX_STATUS_SUPR_FLUSH (2 << 2) /* flush request */
-#define TX_STATUS_SUPR_FRAG (3 << 2) /* previous frag failure */
-#define TX_STATUS_SUPR_TBTT (3 << 2) /* SHARED: Probe response supr for TBTT */
-#define TX_STATUS_SUPR_BADCH (4 << 2) /* channel mismatch */
-#define TX_STATUS_SUPR_EXPTIME (5 << 2) /* lifetime expiry */
-#define TX_STATUS_SUPR_UF (6 << 2) /* underflow */
+#define TX_STATUS_SUPR_PMQ (1 << 2) /* PMQ entry */
+#define TX_STATUS_SUPR_FLUSH (2 << 2) /* flush request */
+#define TX_STATUS_SUPR_FRAG (3 << 2) /* previous frag failure */
+#define TX_STATUS_SUPR_TBTT (3 << 2) /* SHARED: Probe resp supr for TBTT */
+#define TX_STATUS_SUPR_BADCH (4 << 2) /* channel mismatch */
+#define TX_STATUS_SUPR_EXPTIME (5 << 2) /* lifetime expiry */
+#define TX_STATUS_SUPR_UF (6 << 2) /* underflow */
/* Unexpected tx status for rate update */
#define TX_STATUS_UNEXP(status) \
@@ -939,8 +993,8 @@ struct tx_status {
#define ADDR_BMP_RA (1 << 0) /* Receiver Address (RA) */
#define ADDR_BMP_TA (1 << 1) /* Transmitter Address (TA) */
#define ADDR_BMP_BSSID (1 << 2) /* BSSID */
-#define ADDR_BMP_AP (1 << 3) /* Infra-BSS Access Point (AP) */
-#define ADDR_BMP_STA (1 << 4) /* Infra-BSS Station (STA) */
+#define ADDR_BMP_AP (1 << 3) /* Infra-BSS Access Point */
+#define ADDR_BMP_STA (1 << 4) /* Infra-BSS Station */
#define ADDR_BMP_RESERVED1 (1 << 5)
#define ADDR_BMP_RESERVED2 (1 << 6)
#define ADDR_BMP_RESERVED3 (1 << 7)
@@ -1012,9 +1066,10 @@ struct tx_status {
#define T_BCN0_TPL_BASE (0x34 * 2)
#define T_PRS_TPL_BASE (0x134 * 2)
#define T_BCN1_TPL_BASE (0x234 * 2)
-#define T_TX_FIFO_TXRAM_BASE (T_ACTS_TPL_BASE + (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT))
+#define T_TX_FIFO_TXRAM_BASE (T_ACTS_TPL_BASE + \
+ (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT))
-#define T_BA_TPL_BASE T_QNULL_TPL_BASE /* template area for BA */
+#define T_BA_TPL_BASE T_QNULL_TPL_BASE /* template area for BA */
#define T_RAM_ACCESS_SZ 4 /* template ram is 4 byte access only */
@@ -1207,14 +1262,18 @@ struct tx_status {
#define WATCHDOG_8TU_MAX 10
/* Manufacturing Test Variables */
-#define M_PKTENG_CTRL (0x6c * 2) /* PER test mode */
-#define M_PKTENG_IFS (0x6d * 2) /* IFS for TX mode */
-#define M_PKTENG_FRMCNT_LO (0x6e * 2) /* Lower word of tx frmcnt/rx lostcnt */
-#define M_PKTENG_FRMCNT_HI (0x6f * 2) /* Upper word of tx frmcnt/rx lostcnt */
+/* PER test mode */
+#define M_PKTENG_CTRL (0x6c * 2)
+/* IFS for TX mode */
+#define M_PKTENG_IFS (0x6d * 2)
+/* Lower word of tx frmcnt/rx lostcnt */
+#define M_PKTENG_FRMCNT_LO (0x6e * 2)
+/* Upper word of tx frmcnt/rx lostcnt */
+#define M_PKTENG_FRMCNT_HI (0x6f * 2)
/* Index variation in vbat ripple */
-#define M_LCN_PWR_IDX_MAX (0x67 * 2) /* highest index read by ucode */
-#define M_LCN_PWR_IDX_MIN (0x66 * 2) /* lowest index read by ucode */
+#define M_LCN_PWR_IDX_MAX (0x67 * 2) /* highest index read by ucode */
+#define M_LCN_PWR_IDX_MIN (0x66 * 2) /* lowest index read by ucode */
/* M_PKTENG_CTRL bit definitions */
#define M_PKTENG_MODE_TX 0x0001
@@ -1223,11 +1282,14 @@ struct tx_status {
#define M_PKTENG_MODE_RX 0x0002
#define M_PKTENG_MODE_RX_WITH_ACK 0x0402
#define M_PKTENG_MODE_MASK 0x0003
-#define M_PKTENG_FRMCNT_VLD 0x0100 /* TX frames indicated in the frmcnt reg */
+/* TX frames indicated in the frmcnt reg */
+#define M_PKTENG_FRMCNT_VLD 0x0100
/* Sample Collect parameters (bitmap and type) */
-#define M_SMPL_COL_BMP (0x37d * 2) /* Trigger bitmap for sample collect */
-#define M_SMPL_COL_CTL (0x3b2 * 2) /* Sample collect type */
+/* Trigger bitmap for sample collect */
+#define M_SMPL_COL_BMP (0x37d * 2)
+/* Sample collect type */
+#define M_SMPL_COL_CTL (0x3b2 * 2)
#define ANTSEL_CLKDIV_4MHZ 6
#define MIMO_ANTSEL_BUSY 0x4000 /* bit 14 (busy) */
@@ -1259,27 +1321,36 @@ struct shm_acparams {
#define MHF5 4 /* Hostflag 5 index */
/* Flags in M_HOST_FLAGS */
-#define MHF1_ANTDIV 0x0001 /* Enable ucode antenna diversity help */
-#define MHF1_EDCF 0x0100 /* Enable EDCF access control */
+/* Enable ucode antenna diversity help */
+#define MHF1_ANTDIV 0x0001
+/* Enable EDCF access control */
+#define MHF1_EDCF 0x0100
#define MHF1_IQSWAP_WAR 0x0200
-#define MHF1_FORCEFASTCLK 0x0400 /* Disable Slow clock request, for corerev < 11 */
+/* Disable Slow clock request, for corerev < 11 */
+#define MHF1_FORCEFASTCLK 0x0400
/* Flags in M_HOST_FLAGS2 */
-#define MHF2_PCISLOWCLKWAR 0x0008 /* PR16165WAR : Enable ucode PCI slow clock WAR */
-#define MHF2_TXBCMC_NOW 0x0040 /* Flush BCMC FIFO immediately */
-#define MHF2_HWPWRCTL 0x0080 /* Enable ucode/hw power control */
+
+/* Flush BCMC FIFO immediately */
+#define MHF2_TXBCMC_NOW 0x0040
+/* Enable ucode/hw power control */
+#define MHF2_HWPWRCTL 0x0080
#define MHF2_NPHY40MHZ_WAR 0x0800
/* Flags in M_HOST_FLAGS3 */
-#define MHF3_ANTSEL_EN 0x0001 /* enabled mimo antenna selection */
-#define MHF3_ANTSEL_MODE 0x0002 /* antenna selection mode: 0: 2x3, 1: 2x4 */
+/* enabled mimo antenna selection */
+#define MHF3_ANTSEL_EN 0x0001
+/* antenna selection mode: 0: 2x3, 1: 2x4 */
+#define MHF3_ANTSEL_MODE 0x0002
#define MHF3_RESERVED1 0x0004
#define MHF3_RESERVED2 0x0008
#define MHF3_NPHY_MLADV_WAR 0x0010
/* Flags in M_HOST_FLAGS4 */
-#define MHF4_BPHY_TXCORE0 0x0080 /* force bphy Tx on core 0 (board level WAR) */
-#define MHF4_EXTPA_ENABLE 0x4000 /* for 4313A0 FEM boards */
+/* force bphy Tx on core 0 (board level WAR) */
+#define MHF4_BPHY_TXCORE0 0x0080
+/* for 4313A0 FEM boards */
+#define MHF4_EXTPA_ENABLE 0x4000
/* Flags in M_HOST_FLAGS5 */
#define MHF5_4313_GPIOCTRL 0x0001
@@ -1292,52 +1363,80 @@ struct shm_acparams {
#define M_PHY_NOISE (0x037 * 2)
#define PHY_NOISE_MASK 0x00ff
-/* Receive Frame Data Header for 802.11b DCF-only frames */
-struct d11rxhdr {
- u16 RxFrameSize; /* Actual byte length of the frame data received */
+/*
+ * Receive Frame Data Header for 802.11b DCF-only frames
+ *
+ * RxFrameSize: Actual byte length of the frame data received
+ * PAD: padding (not used)
+ * PhyRxStatus_0: PhyRxStatus 15:0
+ * PhyRxStatus_1: PhyRxStatus 31:16
+ * PhyRxStatus_2: PhyRxStatus 47:32
+ * PhyRxStatus_3: PhyRxStatus 63:48
+ * PhyRxStatus_4: PhyRxStatus 79:64
+ * PhyRxStatus_5: PhyRxStatus 95:80
+ * RxStatus1: MAC Rx Status
+ * RxStatus2: extended MAC Rx status
+ * RxTSFTime: RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY
+ * RxChan: gain code, channel radio code, and phy type
+ */
+struct d11rxhdr_le {
+ __le16 RxFrameSize;
u16 PAD;
- u16 PhyRxStatus_0; /* PhyRxStatus 15:0 */
- u16 PhyRxStatus_1; /* PhyRxStatus 31:16 */
- u16 PhyRxStatus_2; /* PhyRxStatus 47:32 */
- u16 PhyRxStatus_3; /* PhyRxStatus 63:48 */
- u16 PhyRxStatus_4; /* PhyRxStatus 79:64 */
- u16 PhyRxStatus_5; /* PhyRxStatus 95:80 */
- u16 RxStatus1; /* MAC Rx Status */
- u16 RxStatus2; /* extended MAC Rx status */
- u16 RxTSFTime; /* RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY */
- u16 RxChan; /* gain code, channel radio code, and phy type */
+ __le16 PhyRxStatus_0;
+ __le16 PhyRxStatus_1;
+ __le16 PhyRxStatus_2;
+ __le16 PhyRxStatus_3;
+ __le16 PhyRxStatus_4;
+ __le16 PhyRxStatus_5;
+ __le16 RxStatus1;
+ __le16 RxStatus2;
+ __le16 RxTSFTime;
+ __le16 RxChan;
} __packed;
-#define RXHDR_LEN 24 /* sizeof struct d11rxhdr */
-#define FRAMELEN(h) ((h)->RxFrameSize)
-
-struct brcms_d11rxhdr {
- struct d11rxhdr rxhdr;
- u32 tsf_l; /* TSF_L reading */
- s8 rssi; /* computed instanteneous rssi in BMAC */
- s8 rxpwr0; /* obsoleted, place holder for legacy ROM code. use rxpwr[] */
- s8 rxpwr1; /* obsoleted, place holder for legacy ROM code. use rxpwr[] */
- s8 do_rssi_ma; /* do per-pkt sampling for per-antenna ma in HIGH */
- s8 rxpwr[WL_RSSI_ANT_MAX]; /* rssi for supported antennas */
+struct d11rxhdr {
+ u16 RxFrameSize;
+ u16 PAD;
+ u16 PhyRxStatus_0;
+ u16 PhyRxStatus_1;
+ u16 PhyRxStatus_2;
+ u16 PhyRxStatus_3;
+ u16 PhyRxStatus_4;
+ u16 PhyRxStatus_5;
+ u16 RxStatus1;
+ u16 RxStatus2;
+ u16 RxTSFTime;
+ u16 RxChan;
} __packed;
/* PhyRxStatus_0: */
-#define PRXS0_FT_MASK 0x0003 /* NPHY only: CCK, OFDM, preN, N */
-#define PRXS0_CLIP_MASK 0x000C /* NPHY only: clip count adjustment steps by AGC */
+/* NPHY only: CCK, OFDM, preN, N */
+#define PRXS0_FT_MASK 0x0003
+/* NPHY only: clip count adjustment steps by AGC */
+#define PRXS0_CLIP_MASK 0x000C
#define PRXS0_CLIP_SHIFT 2
-#define PRXS0_UNSRATE 0x0010 /* PHY received a frame with unsupported rate */
-#define PRXS0_RXANT_UPSUBBAND 0x0020 /* GPHY: rx ant, NPHY: upper sideband */
-#define PRXS0_LCRS 0x0040 /* CCK frame only: lost crs during cck frame reception */
-#define PRXS0_SHORTH 0x0080 /* Short Preamble */
-#define PRXS0_PLCPFV 0x0100 /* PLCP violation */
-#define PRXS0_PLCPHCF 0x0200 /* PLCP header integrity check failed */
-#define PRXS0_GAIN_CTL 0x4000 /* legacy PHY gain control */
-#define PRXS0_ANTSEL_MASK 0xF000 /* NPHY: Antennas used for received frame, bitmask */
+/* PHY received a frame with unsupported rate */
+#define PRXS0_UNSRATE 0x0010
+/* GPHY: rx ant, NPHY: upper sideband */
+#define PRXS0_RXANT_UPSUBBAND 0x0020
+/* CCK frame only: lost crs during cck frame reception */
+#define PRXS0_LCRS 0x0040
+/* Short Preamble */
+#define PRXS0_SHORTH 0x0080
+/* PLCP violation */
+#define PRXS0_PLCPFV 0x0100
+/* PLCP header integrity check failed */
+#define PRXS0_PLCPHCF 0x0200
+/* legacy PHY gain control */
+#define PRXS0_GAIN_CTL 0x4000
+/* NPHY: Antennas used for received frame, bitmask */
+#define PRXS0_ANTSEL_MASK 0xF000
#define PRXS0_ANTSEL_SHIFT 0x12
/* subfield PRXS0_FT_MASK */
#define PRXS0_CCK 0x0000
-#define PRXS0_OFDM 0x0001 /* valid only for G phy, use rxh->RxChan for A phy */
+/* valid only for G phy, use rxh->RxChan for A phy */
+#define PRXS0_OFDM 0x0001
#define PRXS0_PREN 0x0002
#define PRXS0_STDN 0x0003
@@ -1364,35 +1463,51 @@ struct brcms_d11rxhdr {
#define PRXS0_UNUSED 0xF000 /* unused and not defined; set to 0 */
/* htphy PhyRxStatus_1: */
-#define PRXS1_HTPHY_CORE_MASK 0x000F /* core enables for {3..0}, 0=disabled, 1=enabled */
-#define PRXS1_HTPHY_ANTCFG_MASK 0x00F0 /* antenna configation */
-#define PRXS1_HTPHY_MMPLCPLenL_MASK 0xFF00 /* Mixmode PLCP Length low byte mask */
+/* core enables for {3..0}, 0=disabled, 1=enabled */
+#define PRXS1_HTPHY_CORE_MASK 0x000F
+/* antenna configation */
+#define PRXS1_HTPHY_ANTCFG_MASK 0x00F0
+/* Mixmode PLCP Length low byte mask */
+#define PRXS1_HTPHY_MMPLCPLenL_MASK 0xFF00
/* htphy PhyRxStatus_2: */
-#define PRXS2_HTPHY_MMPLCPLenH_MASK 0x000F /* Mixmode PLCP Length high byte maskw */
-#define PRXS2_HTPHY_MMPLCH_RATE_MASK 0x00F0 /* Mixmode PLCP rate mask */
-#define PRXS2_HTPHY_RXPWR_ANT0 0xFF00 /* Rx power on core 0 */
+/* Mixmode PLCP Length high byte maskw */
+#define PRXS2_HTPHY_MMPLCPLenH_MASK 0x000F
+/* Mixmode PLCP rate mask */
+#define PRXS2_HTPHY_MMPLCH_RATE_MASK 0x00F0
+/* Rx power on core 0 */
+#define PRXS2_HTPHY_RXPWR_ANT0 0xFF00
/* htphy PhyRxStatus_3: */
-#define PRXS3_HTPHY_RXPWR_ANT1 0x00FF /* Rx power on core 1 */
-#define PRXS3_HTPHY_RXPWR_ANT2 0xFF00 /* Rx power on core 2 */
+/* Rx power on core 1 */
+#define PRXS3_HTPHY_RXPWR_ANT1 0x00FF
+/* Rx power on core 2 */
+#define PRXS3_HTPHY_RXPWR_ANT2 0xFF00
/* htphy PhyRxStatus_4: */
-#define PRXS4_HTPHY_RXPWR_ANT3 0x00FF /* Rx power on core 3 */
-#define PRXS4_HTPHY_CFO 0xFF00 /* Coarse frequency offset */
+/* Rx power on core 3 */
+#define PRXS4_HTPHY_RXPWR_ANT3 0x00FF
+/* Coarse frequency offset */
+#define PRXS4_HTPHY_CFO 0xFF00
/* htphy PhyRxStatus_5: */
-#define PRXS5_HTPHY_FFO 0x00FF /* Fine frequency offset */
-#define PRXS5_HTPHY_AR 0xFF00 /* Advance Retard */
+/* Fine frequency offset */
+#define PRXS5_HTPHY_FFO 0x00FF
+/* Advance Retard */
+#define PRXS5_HTPHY_AR 0xFF00
-#define HTPHY_MMPLCPLen(rxs) ((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \
+#define HTPHY_MMPLCPLen(rxs) \
+ ((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \
(((rxs)->PhyRxStatus_2 & PRXS2_HTPHY_MMPLCPLenH_MASK) << 8))
/* Get Rx power on core 0 */
-#define HTPHY_RXPWR_ANT0(rxs) ((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8)
+#define HTPHY_RXPWR_ANT0(rxs) \
+ ((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8)
/* Get Rx power on core 1 */
-#define HTPHY_RXPWR_ANT1(rxs) (((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1)
+#define HTPHY_RXPWR_ANT1(rxs) \
+ (((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1)
/* Get Rx power on core 2 */
-#define HTPHY_RXPWR_ANT2(rxs) ((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8)
+#define HTPHY_RXPWR_ANT2(rxs) \
+ ((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8)
/* ucode RxStatus1: */
#define RXS_BCNSENT 0x8000
@@ -1400,7 +1515,8 @@ struct brcms_d11rxhdr {
#define RXS_SECKINDX_SHIFT 5
#define RXS_DECERR (1 << 4)
#define RXS_DECATMPT (1 << 3)
-#define RXS_PBPRES (1 << 2) /* PAD bytes to make IP data 4 bytes aligned */
+/* PAD bytes to make IP data 4 bytes aligned */
+#define RXS_PBPRES (1 << 2)
#define RXS_RESPFRAMETX (1 << 1)
#define RXS_FCSERR (1 << 0)
@@ -1433,16 +1549,17 @@ struct brcms_d11rxhdr {
#define M_PSM_SOFT_REGS 0x0
#define M_BOM_REV_MAJOR (M_PSM_SOFT_REGS + 0x0)
#define M_BOM_REV_MINOR (M_PSM_SOFT_REGS + 0x2)
-#define M_UCODE_DBGST (M_PSM_SOFT_REGS + 0x40) /* ucode debug status code */
-#define M_UCODE_MACSTAT (M_PSM_SOFT_REGS + 0xE0) /* macstat counters */
+#define M_UCODE_DBGST (M_PSM_SOFT_REGS + 0x40) /* ucode debug status code */
+#define M_UCODE_MACSTAT (M_PSM_SOFT_REGS + 0xE0) /* macstat counters */
-#define M_AGING_THRSH (0x3e * 2) /* max time waiting for medium before tx */
-#define M_MBURST_SIZE (0x40 * 2) /* max frames in a frameburst */
-#define M_MBURST_TXOP (0x41 * 2) /* max frameburst TXOP in unit of us */
-#define M_SYNTHPU_DLY (0x4a * 2) /* pre-wakeup for synthpu, default: 500 */
+#define M_AGING_THRSH (0x3e * 2) /* max time waiting for medium before tx */
+#define M_MBURST_SIZE (0x40 * 2) /* max frames in a frameburst */
+#define M_MBURST_TXOP (0x41 * 2) /* max frameburst TXOP in unit of us */
+#define M_SYNTHPU_DLY (0x4a * 2) /* pre-wakeup for synthpu, default: 500 */
#define M_PRETBTT (0x4b * 2)
-#define M_ALT_TXPWR_IDX (M_PSM_SOFT_REGS + (0x3b * 2)) /* offset to the target txpwr */
+/* offset to the target txpwr */
+#define M_ALT_TXPWR_IDX (M_PSM_SOFT_REGS + (0x3b * 2))
#define M_PHY_TX_FLT_PTR (M_PSM_SOFT_REGS + (0x3d * 2))
#define M_CTS_DURATION (M_PSM_SOFT_REGS + (0x5c * 2))
#define M_LP_RCCAL_OVR (M_PSM_SOFT_REGS + (0x6b * 2))
@@ -1451,11 +1568,16 @@ struct brcms_d11rxhdr {
#define M_RXSTATS_BLK_PTR (M_PSM_SOFT_REGS + (0x65 * 2))
/* ucode debug status codes */
-#define DBGST_INACTIVE 0 /* not valid really */
-#define DBGST_INIT 1 /* after zeroing SHM, before suspending at init */
-#define DBGST_ACTIVE 2 /* "normal" state */
-#define DBGST_SUSPENDED 3 /* suspended */
-#define DBGST_ASLEEP 4 /* asleep (PS mode) */
+/* not valid really */
+#define DBGST_INACTIVE 0
+/* after zeroing SHM, before suspending at init */
+#define DBGST_INIT 1
+/* "normal" state */
+#define DBGST_ACTIVE 2
+/* suspended */
+#define DBGST_SUSPENDED 3
+/* asleep (PS mode) */
+#define DBGST_ASLEEP 4
/* Scratch Reg defs */
enum _ePsmScratchPadRegDefinitions {
@@ -1463,66 +1585,66 @@ enum _ePsmScratchPadRegDefinitions {
S_RSV1,
S_RSV2,
- /* scratch registers for Dot11-contants */
- S_DOT11_CWMIN, /* CW-minimum 0x03 */
- S_DOT11_CWMAX, /* CW-maximum 0x04 */
- S_DOT11_CWCUR, /* CW-current 0x05 */
- S_DOT11_SRC_LMT, /* short retry count limit 0x06 */
- S_DOT11_LRC_LMT, /* long retry count limit 0x07 */
- S_DOT11_DTIMCOUNT, /* DTIM-count 0x08 */
-
- /* Tx-side scratch registers */
- S_SEQ_NUM, /* hardware sequence number reg 0x09 */
- S_SEQ_NUM_FRAG, /* seq-num for frags (Set at the start os MSDU 0x0A */
- S_FRMRETX_CNT, /* frame retx count 0x0B */
- S_SSRC, /* Station short retry count 0x0C */
- S_SLRC, /* Station long retry count 0x0D */
- S_EXP_RSP, /* Expected response frame 0x0E */
- S_OLD_BREM, /* Remaining backoff ctr 0x0F */
- S_OLD_CWWIN, /* saved-off CW-cur 0x10 */
- S_TXECTL, /* TXE-Ctl word constructed in scr-pad 0x11 */
- S_CTXTST, /* frm type-subtype as read from Tx-descr 0x12 */
-
- /* Rx-side scratch registers */
- S_RXTST, /* Type and subtype in Rxframe 0x13 */
+ /* offset 0x03: scratch registers for Dot11-contants */
+ S_DOT11_CWMIN, /* CW-minimum */
+ S_DOT11_CWMAX, /* CW-maximum */
+ S_DOT11_CWCUR, /* CW-current */
+ S_DOT11_SRC_LMT, /* short retry count limit */
+ S_DOT11_LRC_LMT, /* long retry count limit */
+ S_DOT11_DTIMCOUNT, /* DTIM-count */
+
+ /* offset 0x09: Tx-side scratch registers */
+ S_SEQ_NUM, /* hardware sequence number reg */
+ S_SEQ_NUM_FRAG, /* seq num for frags (at the start of MSDU) */
+ S_FRMRETX_CNT, /* frame retx count */
+ S_SSRC, /* Station short retry count */
+ S_SLRC, /* Station long retry count */
+ S_EXP_RSP, /* Expected response frame */
+ S_OLD_BREM, /* Remaining backoff ctr */
+ S_OLD_CWWIN, /* saved-off CW-cur */
+ S_TXECTL, /* TXE-Ctl word constructed in scr-pad */
+ S_CTXTST, /* frm type-subtype as read from Tx-descr */
+
+ /* offset 0x13: Rx-side scratch registers */
+ S_RXTST, /* Type and subtype in Rxframe */
/* Global state register */
- S_STREG, /* state storage actual bit maps below 0x14 */
-
- S_TXPWR_SUM, /* Tx power control: accumulator 0x15 */
- S_TXPWR_ITER, /* Tx power control: iteration 0x16 */
- S_RX_FRMTYPE, /* Rate and PHY type for frames 0x17 */
- S_THIS_AGG, /* Size of this AGG (A-MSDU) 0x18 */
-
- S_KEYINDX, /* 0x19 */
- S_RXFRMLEN, /* Receive MPDU length in bytes 0x1A */
-
- /* Receive TSF time stored in SCR */
- S_RXTSFTMRVAL_WD3, /* TSF value at the start of rx 0x1B */
- S_RXTSFTMRVAL_WD2, /* TSF value at the start of rx 0x1C */
- S_RXTSFTMRVAL_WD1, /* TSF value at the start of rx 0x1D */
- S_RXTSFTMRVAL_WD0, /* TSF value at the start of rx 0x1E */
- S_RXSSN, /* Received start seq number for A-MPDU BA 0x1F */
- S_RXQOSFLD, /* Rx-QoS field (if present) 0x20 */
-
- /* Scratch pad regs used in microcode as temp storage */
- S_TMP0, /* stmp0 0x21 */
- S_TMP1, /* stmp1 0x22 */
- S_TMP2, /* stmp2 0x23 */
- S_TMP3, /* stmp3 0x24 */
- S_TMP4, /* stmp4 0x25 */
- S_TMP5, /* stmp5 0x26 */
- S_PRQPENALTY_CTR, /* Probe response queue penalty counter 0x27 */
- S_ANTCNT, /* unsuccessful attempts on current ant. 0x28 */
- S_SYMBOL, /* flag for possible symbol ctl frames 0x29 */
- S_RXTP, /* rx frame type 0x2A */
- S_STREG2, /* extra state storage 0x2B */
- S_STREG3, /* even more extra state storage 0x2C */
- S_STREG4, /* ... 0x2D */
- S_STREG5, /* remember to initialize it to zero 0x2E */
+ S_STREG, /* state storage actual bit maps below */
+
+ S_TXPWR_SUM, /* Tx power control: accumulator */
+ S_TXPWR_ITER, /* Tx power control: iteration */
+ S_RX_FRMTYPE, /* Rate and PHY type for frames */
+ S_THIS_AGG, /* Size of this AGG (A-MSDU) */
+
+ S_KEYINDX,
+ S_RXFRMLEN, /* Receive MPDU length in bytes */
+
+ /* offset 0x1B: Receive TSF time stored in SCR */
+ S_RXTSFTMRVAL_WD3, /* TSF value at the start of rx */
+ S_RXTSFTMRVAL_WD2, /* TSF value at the start of rx */
+ S_RXTSFTMRVAL_WD1, /* TSF value at the start of rx */
+ S_RXTSFTMRVAL_WD0, /* TSF value at the start of rx */
+ S_RXSSN, /* Received start seq number for A-MPDU BA */
+ S_RXQOSFLD, /* Rx-QoS field (if present) */
+
+ /* offset 0x21: Scratch pad regs used in microcode as temp storage */
+ S_TMP0, /* stmp0 */
+ S_TMP1, /* stmp1 */
+ S_TMP2, /* stmp2 */
+ S_TMP3, /* stmp3 */
+ S_TMP4, /* stmp4 */
+ S_TMP5, /* stmp5 */
+ S_PRQPENALTY_CTR, /* Probe response queue penalty counter */
+ S_ANTCNT, /* unsuccessful attempts on current ant. */
+ S_SYMBOL, /* flag for possible symbol ctl frames */
+ S_RXTP, /* rx frame type */
+ S_STREG2, /* extra state storage */
+ S_STREG3, /* even more extra state storage */
+ S_STREG4, /* ... */
+ S_STREG5, /* remember to initialize it to zero */
S_ADJPWR_IDX,
- S_CUR_PTR, /* Temp pointer for A-MPDU re-Tx SHM table 0x32 */
+ S_CUR_PTR, /* Temp pointer for A-MPDU re-Tx SHM table */
S_REVID4, /* 0x33 */
S_INDX, /* 0x34 */
S_ADDR0, /* 0x35 */
@@ -1532,9 +1654,9 @@ enum _ePsmScratchPadRegDefinitions {
S_ADDR4, /* 0x39 */
S_ADDR5, /* 0x3A */
S_TMP6, /* 0x3B */
- S_KEYINDX_BU, /* Backup for Key index 0x3C */
- S_MFGTEST_TMP0, /* Temp register used for RX test calculations 0x3D */
- S_RXESN, /* Received end sequence number for A-MPDU BA 0x3E */
+ S_KEYINDX_BU, /* Backup for Key index */
+ S_MFGTEST_TMP0, /* Temp regs used for RX test calculations */
+ S_RXESN, /* Received end sequence number for A-MPDU BA */
S_STREG6, /* 0x3F */
};
@@ -1628,7 +1750,8 @@ struct macstat {
#define SISF_FCLKA 0x0004 /* FastClkAvailable */
#define SISF_DB_PHY 0x0008 /* Dualband phy */
-/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg, radio and LPPHY regs are separated === */
+/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg === */
+/* radio and LPPHY regs are separated */
#define BPHY_REG_OFT_BASE 0x0
/* offsets for indirect access to bphy registers */
diff --git a/drivers/staging/brcm80211/brcmsmac/dma.c b/drivers/staging/brcm80211/brcmsmac/dma.c
index ea17671efb63..b56a30297c26 100644
--- a/drivers/staging/brcm80211/brcmsmac/dma.c
+++ b/drivers/staging/brcm80211/brcmsmac/dma.c
@@ -18,17 +18,14 @@
#include <linux/delay.h>
#include <linux/pci.h>
-#if defined(__mips__)
-#include <asm/addrspace.h>
-#endif
-
#include <brcmu_utils.h>
#include <aiutils.h>
#include "types.h"
#include "dma.h"
/*
- * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical address.
+ * DMA hardware requires each descriptor ring to be 8kB aligned, and fit within
+ * a contiguous 8kB physical address.
*/
#define D64RINGALIGN_BITS 13
#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS)
@@ -69,21 +66,32 @@
#define D64_XS1_XE_COREE 0x50000000 /* core error */
/* receive channel control */
-#define D64_RC_RE 0x00000001 /* receive enable */
-#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */
+/* receive enable */
+#define D64_RC_RE 0x00000001
+/* receive frame offset */
+#define D64_RC_RO_MASK 0x000000fe
#define D64_RC_RO_SHIFT 1
-#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */
-#define D64_RC_SH 0x00000200 /* separate rx header descriptor enable */
-#define D64_RC_OC 0x00000400 /* overflow continue */
-#define D64_RC_PD 0x00000800 /* parity check disable */
-#define D64_RC_AE 0x00030000 /* address extension bits */
+/* direct fifo receive (pio) mode */
+#define D64_RC_FM 0x00000100
+/* separate rx header descriptor enable */
+#define D64_RC_SH 0x00000200
+/* overflow continue */
+#define D64_RC_OC 0x00000400
+/* parity check disable */
+#define D64_RC_PD 0x00000800
+/* address extension bits */
+#define D64_RC_AE 0x00030000
#define D64_RC_AE_SHIFT 16
/* flags for dma controller */
-#define DMA_CTRL_PEN (1 << 0) /* partity enable */
-#define DMA_CTRL_ROC (1 << 1) /* rx overflow continue */
-#define DMA_CTRL_RXMULTI (1 << 2) /* allow rx scatter to multiple descriptors */
-#define DMA_CTRL_UNFRAMED (1 << 3) /* Unframed Rx/Tx data */
+/* partity enable */
+#define DMA_CTRL_PEN (1 << 0)
+/* rx overflow continue */
+#define DMA_CTRL_ROC (1 << 1)
+/* allow rx scatter to multiple descriptors */
+#define DMA_CTRL_RXMULTI (1 << 2)
+/* Unframed Rx/Tx data */
+#define DMA_CTRL_UNFRAMED (1 << 3)
/* receive descriptor table pointer */
#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */
@@ -131,10 +139,13 @@
#define D64_CTRL1_SOF ((u32)1 << 31) /* start of frame */
/* descriptor control flags 2 */
-#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count. real data len must <= 16KB */
-#define D64_CTRL2_AE 0x00030000 /* address extension bits */
+/* buffer byte count. real data len must <= 16KB */
+#define D64_CTRL2_BC_MASK 0x00007fff
+/* address extension bits */
+#define D64_CTRL2_AE 0x00030000
#define D64_CTRL2_AE_SHIFT 16
-#define D64_CTRL2_PARITY 0x00040000 /* parity bit */
+/* parity bit */
+#define D64_CTRL2_PARITY 0x00040000
/* control flags in the range [27:20] are core-specific and not defined here */
#define D64_CTRL_CORE_MASK 0x0ff00000
@@ -144,15 +155,13 @@
#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1 */
#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */
-#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */
-#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */
-#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */
-#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */
-
-/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF).
- * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL.
- * There is a compile time check in wlc.c which ensure that this value is at least as big
- * as TXOFF. This value is used in dma_rxfill (dma.c).
+/*
+ * packet headroom necessary to accommodate the largest header
+ * in the system, (i.e TXOFF). By doing, we avoid the need to
+ * allocate an extra buffer for the header when bridging to WL.
+ * There is a compile time check in wlc.c which ensure that this
+ * value is at least as big as TXOFF. This value is used in
+ * dma_rxfill().
*/
#define BCMEXTRAHDROOM 172
@@ -180,52 +189,27 @@
#define DMA_NONE(args)
-typedef unsigned long dmaaddr_t;
-#define PHYSADDRHI(_pa) (0)
-#define PHYSADDRHISET(_pa, _val)
-#define PHYSADDRLO(_pa) ((_pa))
-#define PHYSADDRLOSET(_pa, _val) \
- do { \
- (_pa) = (_val); \
- } while (0)
-
-#define d64txregs dregs.d64_u.txregs_64
-#define d64rxregs dregs.d64_u.rxregs_64
-#define txd64 dregs.d64_u.txd_64
-#define rxd64 dregs.d64_u.rxd_64
-
-/* default dma message level (if input msg_level pointer is null in dma_attach()) */
-static uint dma_msg_level;
-
#define MAXNAMEL 8 /* 8 char names */
-#define DI_INFO(dmah) ((dma_info_t *)dmah)
-
-#define R_SM(r) (*(r))
-#define W_SM(r, v) (*(r) = (v))
+/* macros to convert between byte offsets and indexes */
+#define B2I(bytes, type) ((bytes) / sizeof(type))
+#define I2B(index, type) ((index) * sizeof(type))
-/* One physical DMA segment */
-struct dma_seg {
- dmaaddr_t addr;
- u32 length;
-};
+#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */
+#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */
-struct dma_seg_map {
- void *oshdmah; /* Opaque handle for OSL to store its information */
- uint origsize; /* Size of the virtual packet */
- uint nsegs;
- struct dma_seg segs[MAX_DMA_SEGS];
-};
+#define PCI64ADDR_HIGH 0x80000000 /* address[63] */
+#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */
/*
* DMA Descriptor
* Descriptors are only read by the hardware, never written back.
*/
struct dma64desc {
- u32 ctrl1; /* misc control bits & bufcount */
- u32 ctrl2; /* buffer count and address extension */
- u32 addrlow; /* memory address of the date buffer, bits 31:0 */
- u32 addrhigh; /* memory address of the date buffer, bits 63:32 */
+ __le32 ctrl1; /* misc control bits & bufcount */
+ __le32 ctrl2; /* buffer count and address extension */
+ __le32 addrlow; /* memory address of the date buffer, bits 31:0 */
+ __le32 addrhigh; /* memory address of the date buffer, bits 63:32 */
};
/* dma engine software state */
@@ -234,208 +218,344 @@ struct dma_info {
uint *msg_level; /* message level pointer */
char name[MAXNAMEL]; /* callers name for diag msgs */
- void *pbus; /* bus handle */
+ struct pci_dev *pbus; /* bus handle */
- bool dma64; /* this dma engine is operating in 64-bit mode */
- bool addrext; /* this dma engine supports DmaExtendedAddrChanges */
+ bool dma64; /* this dma engine is operating in 64-bit mode */
+ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */
- union {
- struct {
- dma64regs_t *txregs_64; /* 64-bit dma tx engine registers */
- dma64regs_t *rxregs_64; /* 64-bit dma rx engine registers */
- /* pointer to dma64 tx descriptor ring */
- struct dma64desc *txd_64;
- /* pointer to dma64 rx descriptor ring */
- struct dma64desc *rxd_64;
- } d64_u;
- } dregs;
+ /* 64-bit dma tx engine registers */
+ struct dma64regs __iomem *d64txregs;
+ /* 64-bit dma rx engine registers */
+ struct dma64regs __iomem *d64rxregs;
+ /* pointer to dma64 tx descriptor ring */
+ struct dma64desc *txd64;
+ /* pointer to dma64 rx descriptor ring */
+ struct dma64desc *rxd64;
u16 dmadesc_align; /* alignment requirement for dma descriptors */
u16 ntxd; /* # tx descriptors tunable */
u16 txin; /* index of next descriptor to reclaim */
u16 txout; /* index of next descriptor to post */
- void **txp; /* pointer to parallel array of pointers to packets */
- struct dma_seg_map *txp_dmah; /* DMA MAP meta-data handle */
- dmaaddr_t txdpa; /* Aligned physical address of descriptor ring */
- dmaaddr_t txdpaorig; /* Original physical address of descriptor ring */
+ /* pointer to parallel array of pointers to packets */
+ struct sk_buff **txp;
+ /* Aligned physical address of descriptor ring */
+ dma_addr_t txdpa;
+ /* Original physical address of descriptor ring */
+ dma_addr_t txdpaorig;
u16 txdalign; /* #bytes added to alloc'd mem to align txd */
u32 txdalloc; /* #bytes allocated for the ring */
u32 xmtptrbase; /* When using unaligned descriptors, the ptr register
- * is not just an index, it needs all 13 bits to be
- * an offset from the addr register.
- */
+ * is not just an index, it needs all 13 bits to be
+ * an offset from the addr register.
+ */
- u16 nrxd; /* # rx descriptors tunable */
- u16 rxin; /* index of next descriptor to reclaim */
- u16 rxout; /* index of next descriptor to post */
- void **rxp; /* pointer to parallel array of pointers to packets */
- struct dma_seg_map *rxp_dmah; /* DMA MAP meta-data handle */
- dmaaddr_t rxdpa; /* Aligned physical address of descriptor ring */
- dmaaddr_t rxdpaorig; /* Original physical address of descriptor ring */
+ u16 nrxd; /* # rx descriptors tunable */
+ u16 rxin; /* index of next descriptor to reclaim */
+ u16 rxout; /* index of next descriptor to post */
+ /* pointer to parallel array of pointers to packets */
+ struct sk_buff **rxp;
+ /* Aligned physical address of descriptor ring */
+ dma_addr_t rxdpa;
+ /* Original physical address of descriptor ring */
+ dma_addr_t rxdpaorig;
u16 rxdalign; /* #bytes added to alloc'd mem to align rxd */
u32 rxdalloc; /* #bytes allocated for the ring */
u32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */
/* tunables */
- unsigned int rxbufsize; /* rx buffer size in bytes,
- * not including the extra headroom
+ unsigned int rxbufsize; /* rx buffer size in bytes, not including
+ * the extra headroom
*/
- uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper stack
- * e.g. some rx pkt buffers will be bridged to tx side
- * without byte copying. The extra headroom needs to be
- * large enough to fit txheader needs.
- * Some dongle driver may not need it.
+ uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper
+ * stack, e.g. some rx pkt buffers will be
+ * bridged to tx side without byte copying.
+ * The extra headroom needs to be large enough
+ * to fit txheader needs. Some dongle driver may
+ * not need it.
*/
uint nrxpost; /* # rx buffers to keep posted */
unsigned int rxoffset; /* rxcontrol offset */
- uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */
- uint ddoffsethigh; /* high 32 bits */
- uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */
- uint dataoffsethigh; /* high 32 bits */
- bool aligndesc_4k; /* descriptor base need to be aligned or not */
+ /* add to get dma address of descriptor ring, low 32 bits */
+ uint ddoffsetlow;
+ /* high 32 bits */
+ uint ddoffsethigh;
+ /* add to get dma address of data buffer, low 32 bits */
+ uint dataoffsetlow;
+ /* high 32 bits */
+ uint dataoffsethigh;
+ /* descriptor base need to be aligned or not */
+ bool aligndesc_4k;
};
-/* DMA Scatter-gather list is supported. Note this is limited to TX direction only */
-#ifdef BCMDMASGLISTOSL
-#define DMASGLIST_ENAB true
-#else
-#define DMASGLIST_ENAB false
-#endif /* BCMDMASGLISTOSL */
+/*
+ * default dma message level (if input msg_level
+ * pointer is null in dma_attach())
+ */
+static uint dma_msg_level;
-/* descriptor bumping macros */
-#define XXD(x, n) ((x) & ((n) - 1)) /* faster than %, but n must be power of 2 */
-#define TXD(x) XXD((x), di->ntxd)
-#define RXD(x) XXD((x), di->nrxd)
-#define NEXTTXD(i) TXD((i) + 1)
-#define PREVTXD(i) TXD((i) - 1)
-#define NEXTRXD(i) RXD((i) + 1)
-#define PREVRXD(i) RXD((i) - 1)
+/* Check for odd number of 1's */
+static u32 parity32(__le32 data)
+{
+ /* no swap needed for counting 1's */
+ u32 par_data = *(u32 *)&data;
-#define NTXDACTIVE(h, t) TXD((t) - (h))
-#define NRXDACTIVE(h, t) RXD((t) - (h))
+ par_data ^= par_data >> 16;
+ par_data ^= par_data >> 8;
+ par_data ^= par_data >> 4;
+ par_data ^= par_data >> 2;
+ par_data ^= par_data >> 1;
-/* macros to convert between byte offsets and indexes */
-#define B2I(bytes, type) ((bytes) / sizeof(type))
-#define I2B(index, type) ((index) * sizeof(type))
+ return par_data & 1;
+}
-#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */
-#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */
+static bool dma64_dd_parity(struct dma64desc *dd)
+{
+ return parity32(dd->addrlow ^ dd->addrhigh ^ dd->ctrl1 ^ dd->ctrl2);
+}
-#define PCI64ADDR_HIGH 0x80000000 /* address[63] */
-#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */
+/* descriptor bumping functions */
+
+static uint xxd(uint x, uint n)
+{
+ return x & (n - 1); /* faster than %, but n must be power of 2 */
+}
+
+static uint txd(struct dma_info *di, uint x)
+{
+ return xxd(x, di->ntxd);
+}
+
+static uint rxd(struct dma_info *di, uint x)
+{
+ return xxd(x, di->nrxd);
+}
+
+static uint nexttxd(struct dma_info *di, uint i)
+{
+ return txd(di, i + 1);
+}
+
+static uint prevtxd(struct dma_info *di, uint i)
+{
+ return txd(di, i - 1);
+}
+
+static uint nextrxd(struct dma_info *di, uint i)
+{
+ return txd(di, i + 1);
+}
+
+static uint ntxdactive(struct dma_info *di, uint h, uint t)
+{
+ return txd(di, t-h);
+}
+
+static uint nrxdactive(struct dma_info *di, uint h, uint t)
+{
+ return rxd(di, t-h);
+}
+
+static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
+{
+ uint dmactrlflags = di->dma.dmactrlflags;
+
+ if (di == NULL) {
+ DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name));
+ return 0;
+ }
+
+ dmactrlflags &= ~mask;
+ dmactrlflags |= flags;
+
+ /* If trying to enable parity, check if parity is actually supported */
+ if (dmactrlflags & DMA_CTRL_PEN) {
+ u32 control;
+
+ control = R_REG(&di->d64txregs->control);
+ W_REG(&di->d64txregs->control,
+ control | D64_XC_PD);
+ if (R_REG(&di->d64txregs->control) & D64_XC_PD)
+ /* We *can* disable it so it is supported,
+ * restore control register
+ */
+ W_REG(&di->d64txregs->control,
+ control);
+ else
+ /* Not supported, don't allow it to be enabled */
+ dmactrlflags &= ~DMA_CTRL_PEN;
+ }
+
+ di->dma.dmactrlflags = dmactrlflags;
+
+ return dmactrlflags;
+}
+
+static bool _dma64_addrext(struct dma64regs __iomem *dma64regs)
+{
+ u32 w;
+ OR_REG(&dma64regs->control, D64_XC_AE);
+ w = R_REG(&dma64regs->control);
+ AND_REG(&dma64regs->control, ~D64_XC_AE);
+ return (w & D64_XC_AE) == D64_XC_AE;
+}
+
+/*
+ * return true if this dma engine supports DmaExtendedAddrChanges,
+ * otherwise false
+ */
+static bool _dma_isaddrext(struct dma_info *di)
+{
+ /* DMA64 supports full 32- or 64-bit operation. AE is always valid */
+
+ /* not all tx or rx channel are available */
+ if (di->d64txregs != NULL) {
+ if (!_dma64_addrext(di->d64txregs))
+ DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have "
+ "AE set\n", di->name));
+ return true;
+ } else if (di->d64rxregs != NULL) {
+ if (!_dma64_addrext(di->d64rxregs))
+ DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have "
+ "AE set\n", di->name));
+ return true;
+ }
-/* Common prototypes */
-static bool _dma_isaddrext(struct dma_info *di);
-static bool _dma_descriptor_align(struct dma_info *di);
-static bool _dma_alloc(struct dma_info *di, uint direction);
-static void _dma_detach(struct dma_info *di);
-static void _dma_ddtable_init(struct dma_info *di, uint direction,
- dmaaddr_t pa);
-static void _dma_rxinit(struct dma_info *di);
-static void *_dma_rx(struct dma_info *di);
-static bool _dma_rxfill(struct dma_info *di);
-static void _dma_rxreclaim(struct dma_info *di);
-static void _dma_rxenable(struct dma_info *di);
-static void *_dma_getnextrxp(struct dma_info *di, bool forceall);
-static void _dma_rx_param_get(struct dma_info *di, u16 *rxoffset,
- u16 *rxbufsize);
-
-static void _dma_txblock(struct dma_info *di);
-static void _dma_txunblock(struct dma_info *di);
-static uint _dma_txactive(struct dma_info *di);
-static uint _dma_rxactive(struct dma_info *di);
-static uint _dma_txpending(struct dma_info *di);
-static uint _dma_txcommitted(struct dma_info *di);
-
-static void *_dma_peeknexttxp(struct dma_info *di);
-static void *_dma_peeknextrxp(struct dma_info *di);
-static unsigned long _dma_getvar(struct dma_info *di, const char *name);
-static void _dma_counterreset(struct dma_info *di);
-static void _dma_fifoloopbackenable(struct dma_info *di);
-static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags);
-static u8 dma_align_sizetobits(uint size);
+ return false;
+}
+
+static bool _dma_descriptor_align(struct dma_info *di)
+{
+ u32 addrl;
+
+ /* Check to see if the descriptors need to be aligned on 4K/8K or not */
+ if (di->d64txregs != NULL) {
+ W_REG(&di->d64txregs->addrlow, 0xff0);
+ addrl = R_REG(&di->d64txregs->addrlow);
+ if (addrl != 0)
+ return false;
+ } else if (di->d64rxregs != NULL) {
+ W_REG(&di->d64rxregs->addrlow, 0xff0);
+ addrl = R_REG(&di->d64rxregs->addrlow);
+ if (addrl != 0)
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Descriptor table must start at the DMA hardware dictated alignment, so
+ * allocated memory must be large enough to support this requirement.
+ */
+static void *dma_alloc_consistent(struct pci_dev *pdev, uint size,
+ u16 align_bits, uint *alloced,
+ dma_addr_t *pap)
+{
+ if (align_bits) {
+ u16 align = (1 << align_bits);
+ if (!IS_ALIGNED(PAGE_SIZE, align))
+ size += align;
+ *alloced = size;
+ }
+ return pci_alloc_consistent(pdev, size, pap);
+}
+
+static
+u8 dma_align_sizetobits(uint size)
+{
+ u8 bitpos = 0;
+ while (size >>= 1)
+ bitpos++;
+ return bitpos;
+}
+
+/* This function ensures that the DMA descriptor ring will not get allocated
+ * across Page boundary. If the allocation is done across the page boundary
+ * at the first time, then it is freed and the allocation is done at
+ * descriptor ring size aligned location. This will ensure that the ring will
+ * not cross page boundary
+ */
static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
u16 *alignbits, uint *alloced,
- dmaaddr_t *descpa);
-
-/* Prototypes for 64-bit routines */
-static bool dma64_alloc(struct dma_info *di, uint direction);
-static bool dma64_txreset(struct dma_info *di);
-static bool dma64_rxreset(struct dma_info *di);
-static bool dma64_txsuspendedidle(struct dma_info *di);
-static int dma64_txfast(struct dma_info *di, struct sk_buff *p0, bool commit);
-static int dma64_txunframed(struct dma_info *di, void *p0, uint len,
- bool commit);
-static void *dma64_getpos(struct dma_info *di, bool direction);
-static void *dma64_getnexttxp(struct dma_info *di, enum txd_range range);
-static void *dma64_getnextrxp(struct dma_info *di, bool forceall);
-static void dma64_txrotate(struct dma_info *di);
-
-static bool dma64_rxidle(struct dma_info *di);
-static void dma64_txinit(struct dma_info *di);
-static bool dma64_txenabled(struct dma_info *di);
-static void dma64_txsuspend(struct dma_info *di);
-static void dma64_txresume(struct dma_info *di);
-static bool dma64_txsuspended(struct dma_info *di);
-static void dma64_txreclaim(struct dma_info *di, enum txd_range range);
-static bool dma64_txstopped(struct dma_info *di);
-static bool dma64_rxstopped(struct dma_info *di);
-static bool dma64_rxenabled(struct dma_info *di);
-static bool _dma64_addrext(dma64regs_t *dma64regs);
-
-static inline u32 parity32(u32 data);
-
-const struct di_fcn_s dma64proc = {
- (di_detach_t) _dma_detach,
- (di_txinit_t) dma64_txinit,
- (di_txreset_t) dma64_txreset,
- (di_txenabled_t) dma64_txenabled,
- (di_txsuspend_t) dma64_txsuspend,
- (di_txresume_t) dma64_txresume,
- (di_txsuspended_t) dma64_txsuspended,
- (di_txsuspendedidle_t) dma64_txsuspendedidle,
- (di_txfast_t) dma64_txfast,
- (di_txunframed_t) dma64_txunframed,
- (di_getpos_t) dma64_getpos,
- (di_txstopped_t) dma64_txstopped,
- (di_txreclaim_t) dma64_txreclaim,
- (di_getnexttxp_t) dma64_getnexttxp,
- (di_peeknexttxp_t) _dma_peeknexttxp,
- (di_txblock_t) _dma_txblock,
- (di_txunblock_t) _dma_txunblock,
- (di_txactive_t) _dma_txactive,
- (di_txrotate_t) dma64_txrotate,
-
- (di_rxinit_t) _dma_rxinit,
- (di_rxreset_t) dma64_rxreset,
- (di_rxidle_t) dma64_rxidle,
- (di_rxstopped_t) dma64_rxstopped,
- (di_rxenable_t) _dma_rxenable,
- (di_rxenabled_t) dma64_rxenabled,
- (di_rx_t) _dma_rx,
- (di_rxfill_t) _dma_rxfill,
- (di_rxreclaim_t) _dma_rxreclaim,
- (di_getnextrxp_t) _dma_getnextrxp,
- (di_peeknextrxp_t) _dma_peeknextrxp,
- (di_rxparam_get_t) _dma_rx_param_get,
-
- (di_fifoloopbackenable_t) _dma_fifoloopbackenable,
- (di_getvar_t) _dma_getvar,
- (di_counterreset_t) _dma_counterreset,
- (di_ctrlflags_t) _dma_ctrlflags,
- NULL,
- NULL,
- NULL,
- (di_rxactive_t) _dma_rxactive,
- (di_txpending_t) _dma_txpending,
- (di_txcommitted_t) _dma_txcommitted,
- 39
-};
+ dma_addr_t *descpa)
+{
+ void *va;
+ u32 desc_strtaddr;
+ u32 alignbytes = 1 << *alignbits;
+
+ va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa);
+
+ if (NULL == va)
+ return NULL;
+
+ desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes);
+ if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
+ & boundary)) {
+ *alignbits = dma_align_sizetobits(size);
+ pci_free_consistent(di->pbus, size, va, *descpa);
+ va = dma_alloc_consistent(di->pbus, size, *alignbits,
+ alloced, descpa);
+ }
+ return va;
+}
+
+static bool dma64_alloc(struct dma_info *di, uint direction)
+{
+ u16 size;
+ uint ddlen;
+ void *va;
+ uint alloced = 0;
+ u16 align;
+ u16 align_bits;
+
+ ddlen = sizeof(struct dma64desc);
+
+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);
+ align_bits = di->dmadesc_align;
+ align = (1 << align_bits);
+
+ if (direction == DMA_TX) {
+ va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
+ &alloced, &di->txdpaorig);
+ if (va == NULL) {
+ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd)"
+ " failed\n", di->name));
+ return false;
+ }
+ align = (1 << align_bits);
+ di->txd64 = (struct dma64desc *)
+ roundup((unsigned long)va, align);
+ di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va);
+ di->txdpa = di->txdpaorig + di->txdalign;
+ di->txdalloc = alloced;
+ } else {
+ va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
+ &alloced, &di->rxdpaorig);
+ if (va == NULL) {
+ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd)"
+ " failed\n", di->name));
+ return false;
+ }
+ align = (1 << align_bits);
+ di->rxd64 = (struct dma64desc *)
+ roundup((unsigned long)va, align);
+ di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va);
+ di->rxdpa = di->rxdpaorig + di->rxdalign;
+ di->rxdalloc = alloced;
+ }
+
+ return true;
+}
+
+static bool _dma_alloc(struct dma_info *di, uint direction)
+{
+ return dma64_alloc(di, direction);
+}
struct dma_pub *dma_attach(char *name, struct si_pub *sih,
- void *dmaregstx, void *dmaregsrx, uint ntxd,
- uint nrxd, uint rxbufsize, int rxextheadroom,
+ void __iomem *dmaregstx, void __iomem *dmaregsrx,
+ uint ntxd, uint nrxd,
+ uint rxbufsize, int rxextheadroom,
uint nrxpost, uint rxoffset, uint *msg_level)
{
struct dma_info *di;
@@ -443,12 +563,8 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
/* allocate private info structure */
di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC);
- if (di == NULL) {
-#ifdef BCMDBG
- printk(KERN_ERR "dma_attach: out of memory\n");
-#endif
+ if (di == NULL)
return NULL;
- }
di->msg_level = msg_level ? msg_level : &dma_msg_level;
@@ -456,17 +572,15 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64);
/* init dma reg pointer */
- di->d64txregs = (dma64regs_t *) dmaregstx;
- di->d64rxregs = (dma64regs_t *) dmaregsrx;
- di->dma.di_fn = (const struct di_fcn_s *)&dma64proc;
-
- /* Default flags (which can be changed by the driver calling dma_ctrlflags
- * before enable): For backwards compatibility both Rx Overflow Continue
- * and Parity are DISABLED.
- * supports it.
+ di->d64txregs = (struct dma64regs __iomem *) dmaregstx;
+ di->d64rxregs = (struct dma64regs __iomem *) dmaregsrx;
+
+ /*
+ * Default flags (which can be changed by the driver calling
+ * dma_ctrlflags before enable): For backwards compatibility
+ * both Rx Overflow Continue and Parity are DISABLED.
*/
- di->dma.di_fn->ctrlflags(&di->dma, DMA_CTRL_ROC | DMA_CTRL_PEN,
- 0);
+ _dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0);
DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d "
"rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
@@ -497,23 +611,18 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
/*
* figure out the DMA physical address offset for dd and data
- * PCI/PCIE: they map silicon backplace address to zero based memory, need offset
- * Other bus: use zero
- * SI_BUS BIGENDIAN kludge: use sdram swapped region for data buffer, not descriptor
+ * PCI/PCIE: they map silicon backplace address to zero
+ * based memory, need offset
+ * Other bus: use zero SI_BUS BIGENDIAN kludge: use sdram
+ * swapped region for data buffer, not descriptor
*/
di->ddoffsetlow = 0;
di->dataoffsetlow = 0;
- /* for pci bus, add offset */
- if (sih->bustype == PCI_BUS) {
- /* pcie with DMA64 */
- di->ddoffsetlow = 0;
- di->ddoffsethigh = SI_PCIE_DMA_H32;
- di->dataoffsetlow = di->ddoffsetlow;
- di->dataoffsethigh = di->ddoffsethigh;
- }
-#if defined(__mips__) && defined(IL_BIGENDIAN)
- di->dataoffsetlow = di->dataoffsetlow + SI_SDRAM_SWAPPED;
-#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */
+ /* add offset for pcie with DMA64 bus */
+ di->ddoffsetlow = 0;
+ di->ddoffsethigh = SI_PCIE_DMA_H32;
+ di->dataoffsetlow = di->ddoffsetlow;
+ di->dataoffsethigh = di->ddoffsethigh;
/* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */
if ((ai_coreid(sih) == SDIOD_CORE_ID)
&& ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2)))
@@ -524,16 +633,16 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
else
di->addrext = _dma_isaddrext(di);
- /* does the descriptors need to be aligned and if yes, on 4K/8K or not */
+ /* does the descriptor need to be aligned and if yes, on 4K/8K or not */
di->aligndesc_4k = _dma_descriptor_align(di);
if (di->aligndesc_4k) {
di->dmadesc_align = D64RINGALIGN_BITS;
- if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) {
+ if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2))
/* for smaller dd table, HW relax alignment reqmnt */
di->dmadesc_align = D64RINGALIGN_BITS - 1;
- }
- } else
+ } else {
di->dmadesc_align = 4; /* 16 byte alignment */
+ }
DMA_NONE(("DMA descriptor align_needed %d, align %d\n",
di->aligndesc_4k, di->dmadesc_align));
@@ -542,148 +651,97 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
if (ntxd) {
size = ntxd * sizeof(void *);
di->txp = kzalloc(size, GFP_ATOMIC);
- if (di->txp == NULL) {
- DMA_ERROR(("%s: dma_attach: out of tx memory\n", di->name));
+ if (di->txp == NULL)
goto fail;
- }
}
/* allocate rx packet pointer vector */
if (nrxd) {
size = nrxd * sizeof(void *);
di->rxp = kzalloc(size, GFP_ATOMIC);
- if (di->rxp == NULL) {
- DMA_ERROR(("%s: dma_attach: out of rx memory\n", di->name));
+ if (di->rxp == NULL)
goto fail;
- }
}
- /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */
+ /*
+ * allocate transmit descriptor ring, only need ntxd descriptors
+ * but it must be aligned
+ */
if (ntxd) {
if (!_dma_alloc(di, DMA_TX))
goto fail;
}
- /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */
+ /*
+ * allocate receive descriptor ring, only need nrxd descriptors
+ * but it must be aligned
+ */
if (nrxd) {
if (!_dma_alloc(di, DMA_RX))
goto fail;
}
if ((di->ddoffsetlow != 0) && !di->addrext) {
- if (PHYSADDRLO(di->txdpa) > SI_PCI_DMA_SZ) {
- DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(di->txdpa)));
+ if (di->txdpa > SI_PCI_DMA_SZ) {
+ DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not "
+ "supported\n", di->name, (u32)di->txdpa));
goto fail;
}
- if (PHYSADDRLO(di->rxdpa) > SI_PCI_DMA_SZ) {
- DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(di->rxdpa)));
+ if (di->rxdpa > SI_PCI_DMA_SZ) {
+ DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not "
+ "supported\n", di->name, (u32)di->rxdpa));
goto fail;
}
}
- DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh " "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow, di->dataoffsethigh, di->addrext));
-
- /* allocate DMA mapping vectors */
- if (DMASGLIST_ENAB) {
- if (ntxd) {
- size = ntxd * sizeof(struct dma_seg_map);
- di->txp_dmah = kzalloc(size, GFP_ATOMIC);
- if (di->txp_dmah == NULL)
- goto fail;
- }
-
- if (nrxd) {
- size = nrxd * sizeof(struct dma_seg_map);
- di->rxp_dmah = kzalloc(size, GFP_ATOMIC);
- if (di->rxp_dmah == NULL)
- goto fail;
- }
- }
+ DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x "
+ "dataoffsethigh " "0x%x addrext %d\n", di->ddoffsetlow,
+ di->ddoffsethigh, di->dataoffsetlow, di->dataoffsethigh,
+ di->addrext));
return (struct dma_pub *) di;
fail:
- _dma_detach(di);
+ dma_detach((struct dma_pub *)di);
return NULL;
}
-/* Check for odd number of 1's */
-static inline u32 parity32(u32 data)
-{
- data ^= data >> 16;
- data ^= data >> 8;
- data ^= data >> 4;
- data ^= data >> 2;
- data ^= data >> 1;
-
- return data & 1;
-}
-
-#define DMA64_DD_PARITY(dd) parity32((dd)->addrlow ^ (dd)->addrhigh ^ (dd)->ctrl1 ^ (dd)->ctrl2)
-
static inline void
dma64_dd_upd(struct dma_info *di, struct dma64desc *ddring,
- dmaaddr_t pa, uint outidx, u32 *flags, u32 bufcount)
+ dma_addr_t pa, uint outidx, u32 *flags, u32 bufcount)
{
u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK;
/* PCI bus with big(>1G) physical address, use address extension */
-#if defined(__mips__) && defined(IL_BIGENDIAN)
- if ((di->dataoffsetlow == SI_SDRAM_SWAPPED)
- || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
-#else
- if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
-#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */
-
- W_SM(&ddring[outidx].addrlow,
- BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
- W_SM(&ddring[outidx].addrhigh,
- BUS_SWAP32(PHYSADDRHI(pa) + di->dataoffsethigh));
- W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags));
- W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2));
+ if ((di->dataoffsetlow == 0) || !(pa & PCI32ADDR_HIGH)) {
+ ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow);
+ ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh);
+ ddring[outidx].ctrl1 = cpu_to_le32(*flags);
+ ddring[outidx].ctrl2 = cpu_to_le32(ctrl2);
} else {
/* address extension for 32-bit PCI */
u32 ae;
- ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
- PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
+ pa &= ~PCI32ADDR_HIGH;
ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE;
- W_SM(&ddring[outidx].addrlow,
- BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
- W_SM(&ddring[outidx].addrhigh,
- BUS_SWAP32(0 + di->dataoffsethigh));
- W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags));
- W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2));
+ ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow);
+ ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh);
+ ddring[outidx].ctrl1 = cpu_to_le32(*flags);
+ ddring[outidx].ctrl2 = cpu_to_le32(ctrl2);
}
if (di->dma.dmactrlflags & DMA_CTRL_PEN) {
- if (DMA64_DD_PARITY(&ddring[outidx])) {
- W_SM(&ddring[outidx].ctrl2,
- BUS_SWAP32(ctrl2 | D64_CTRL2_PARITY));
- }
- }
-}
-
-static bool _dma_alloc(struct dma_info *di, uint direction)
-{
- return dma64_alloc(di, direction);
-}
-
-void *dma_alloc_consistent(struct pci_dev *pdev, uint size, u16 align_bits,
- uint *alloced, unsigned long *pap)
-{
- if (align_bits) {
- u16 align = (1 << align_bits);
- if (!IS_ALIGNED(PAGE_SIZE, align))
- size += align;
- *alloced = size;
+ if (dma64_dd_parity(&ddring[outidx]))
+ ddring[outidx].ctrl2 =
+ cpu_to_le32(ctrl2 | D64_CTRL2_PARITY);
}
- return pci_alloc_consistent(pdev, size, (dma_addr_t *) pap);
}
/* !! may be called with core in reset */
-static void _dma_detach(struct dma_info *di)
+void dma_detach(struct dma_pub *pub)
{
+ struct dma_info *di = (struct dma_info *)pub;
DMA_TRACE(("%s: dma_detach\n", di->name));
@@ -701,117 +759,78 @@ static void _dma_detach(struct dma_info *di)
kfree(di->txp);
kfree(di->rxp);
- /* free tx packet DMA handles */
- kfree(di->txp_dmah);
-
- /* free rx packet DMA handles */
- kfree(di->rxp_dmah);
-
/* free our private info structure */
kfree(di);
}
-static bool _dma_descriptor_align(struct dma_info *di)
-{
- u32 addrl;
-
- /* Check to see if the descriptors need to be aligned on 4K/8K or not */
- if (di->d64txregs != NULL) {
- W_REG(&di->d64txregs->addrlow, 0xff0);
- addrl = R_REG(&di->d64txregs->addrlow);
- if (addrl != 0)
- return false;
- } else if (di->d64rxregs != NULL) {
- W_REG(&di->d64rxregs->addrlow, 0xff0);
- addrl = R_REG(&di->d64rxregs->addrlow);
- if (addrl != 0)
- return false;
- }
- return true;
-}
-
-/* return true if this dma engine supports DmaExtendedAddrChanges, otherwise false */
-static bool _dma_isaddrext(struct dma_info *di)
-{
- /* DMA64 supports full 32- or 64-bit operation. AE is always valid */
-
- /* not all tx or rx channel are available */
- if (di->d64txregs != NULL) {
- if (!_dma64_addrext(di->d64txregs)) {
- DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have "
- "AE set\n", di->name));
- }
- return true;
- } else if (di->d64rxregs != NULL) {
- if (!_dma64_addrext(di->d64rxregs)) {
- DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have "
- "AE set\n", di->name));
- }
- return true;
- }
- return false;
-}
-
/* initialize descriptor table base address */
-static void _dma_ddtable_init(struct dma_info *di, uint direction, dmaaddr_t pa)
+static void
+_dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa)
{
if (!di->aligndesc_4k) {
if (direction == DMA_TX)
- di->xmtptrbase = PHYSADDRLO(pa);
+ di->xmtptrbase = pa;
else
- di->rcvptrbase = PHYSADDRLO(pa);
+ di->rcvptrbase = pa;
}
if ((di->ddoffsetlow == 0)
- || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
+ || !(pa & PCI32ADDR_HIGH)) {
if (direction == DMA_TX) {
- W_REG(&di->d64txregs->addrlow,
- (PHYSADDRLO(pa) + di->ddoffsetlow));
- W_REG(&di->d64txregs->addrhigh,
- (PHYSADDRHI(pa) + di->ddoffsethigh));
+ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow);
+ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh);
} else {
- W_REG(&di->d64rxregs->addrlow,
- (PHYSADDRLO(pa) + di->ddoffsetlow));
- W_REG(&di->d64rxregs->addrhigh,
- (PHYSADDRHI(pa) + di->ddoffsethigh));
+ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow);
+ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh);
}
} else {
/* DMA64 32bits address extension */
u32 ae;
/* shift the high bit(s) from pa to ae */
- ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >>
- PCI32ADDR_HIGH_SHIFT;
- PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
+ pa &= ~PCI32ADDR_HIGH;
if (direction == DMA_TX) {
- W_REG(&di->d64txregs->addrlow,
- (PHYSADDRLO(pa) + di->ddoffsetlow));
- W_REG(&di->d64txregs->addrhigh,
- di->ddoffsethigh);
+ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow);
+ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh);
SET_REG(&di->d64txregs->control,
D64_XC_AE, (ae << D64_XC_AE_SHIFT));
} else {
- W_REG(&di->d64rxregs->addrlow,
- (PHYSADDRLO(pa) + di->ddoffsetlow));
- W_REG(&di->d64rxregs->addrhigh,
- di->ddoffsethigh);
+ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow);
+ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh);
SET_REG(&di->d64rxregs->control,
D64_RC_AE, (ae << D64_RC_AE_SHIFT));
}
}
}
-static void _dma_fifoloopbackenable(struct dma_info *di)
+static void _dma_rxenable(struct dma_info *di)
{
- DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name));
+ uint dmactrlflags = di->dma.dmactrlflags;
+ u32 control;
+
+ DMA_TRACE(("%s: dma_rxenable\n", di->name));
+
+ control =
+ (R_REG(&di->d64rxregs->control) & D64_RC_AE) |
+ D64_RC_RE;
+
+ if ((dmactrlflags & DMA_CTRL_PEN) == 0)
+ control |= D64_RC_PD;
- OR_REG(&di->d64txregs->control, D64_XC_LE);
+ if (dmactrlflags & DMA_CTRL_ROC)
+ control |= D64_RC_OC;
+
+ W_REG(&di->d64rxregs->control,
+ ((di->rxoffset << D64_RC_RO_SHIFT) | control));
}
-static void _dma_rxinit(struct dma_info *di)
+void dma_rxinit(struct dma_pub *pub)
{
+ struct dma_info *di = (struct dma_info *)pub;
+
DMA_TRACE(("%s: dma_rxinit\n", di->name));
if (di->nrxd == 0)
@@ -820,8 +839,7 @@ static void _dma_rxinit(struct dma_info *di)
di->rxin = di->rxout = 0;
/* clear rx descriptor ring */
- memset((void *)di->rxd64, '\0',
- (di->nrxd * sizeof(struct dma64desc)));
+ memset(di->rxd64, '\0', di->nrxd * sizeof(struct dma64desc));
/* DMA engine with out alignment requirement requires table to be inited
* before enabling the engine
@@ -835,46 +853,64 @@ static void _dma_rxinit(struct dma_info *di)
_dma_ddtable_init(di, DMA_RX, di->rxdpa);
}
-static void _dma_rxenable(struct dma_info *di)
+static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall)
{
- uint dmactrlflags = di->dma.dmactrlflags;
- u32 control;
+ uint i, curr;
+ struct sk_buff *rxp;
+ dma_addr_t pa;
- DMA_TRACE(("%s: dma_rxenable\n", di->name));
+ i = di->rxin;
- control =
- (R_REG(&di->d64rxregs->control) & D64_RC_AE) |
- D64_RC_RE;
+ /* return if no packets posted */
+ if (i == di->rxout)
+ return NULL;
- if ((dmactrlflags & DMA_CTRL_PEN) == 0)
- control |= D64_RC_PD;
+ curr =
+ B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) -
+ di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc);
- if (dmactrlflags & DMA_CTRL_ROC)
- control |= D64_RC_OC;
+ /* ignore curr if forceall */
+ if (!forceall && (i == curr))
+ return NULL;
- W_REG(&di->d64rxregs->control,
- ((di->rxoffset << D64_RC_RO_SHIFT) | control));
+ /* get the packet pointer that corresponds to the rx descriptor */
+ rxp = di->rxp[i];
+ di->rxp[i] = NULL;
+
+ pa = le32_to_cpu(di->rxd64[i].addrlow) - di->dataoffsetlow;
+
+ /* clear this packet from the descriptor ring */
+ pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE);
+
+ di->rxd64[i].addrlow = cpu_to_le32(0xdeadbeef);
+ di->rxd64[i].addrhigh = cpu_to_le32(0xdeadbeef);
+
+ di->rxin = nextrxd(di, i);
+
+ return rxp;
}
-static void
-_dma_rx_param_get(struct dma_info *di, u16 *rxoffset, u16 *rxbufsize)
+static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall)
{
- /* the normal values fit into 16 bits */
- *rxoffset = (u16) di->rxoffset;
- *rxbufsize = (u16) di->rxbufsize;
+ if (di->nrxd == 0)
+ return NULL;
+
+ return dma64_getnextrxp(di, forceall);
}
-/* !! rx entry routine
+/*
+ * !! rx entry routine
* returns a pointer to the next frame received, or NULL if there are no more
- * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is supported
- * with pkts chain
+ * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is
+ * supported with pkts chain
* otherwise, it's treated as giant pkt and will be tossed.
- * The DMA scattering starts with normal DMA header, followed by first buffer data.
- * After it reaches the max size of buffer, the data continues in next DMA descriptor
- * buffer WITHOUT DMA header
+ * The DMA scattering starts with normal DMA header, followed by first
+ * buffer data. After it reaches the max size of buffer, the data continues
+ * in next DMA descriptor buffer WITHOUT DMA header
*/
-static void *_dma_rx(struct dma_info *di)
+struct sk_buff *dma_rx(struct dma_pub *pub)
{
+ struct dma_info *di = (struct dma_info *)pub;
struct sk_buff *p, *head, *tail;
uint len;
uint pkt_len;
@@ -885,7 +921,7 @@ static void *_dma_rx(struct dma_info *di)
if (head == NULL)
return NULL;
- len = le16_to_cpu(*(u16 *) (head->data));
+ len = le16_to_cpu(*(__le16 *) (head->data));
DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));
dma_spin_for_len(len, head);
@@ -899,7 +935,7 @@ static void *_dma_rx(struct dma_info *di)
tail = head;
while ((resid > 0) && (p = _dma_getnextrxp(di, false))) {
tail->next = p;
- pkt_len = min(resid, (int)di->rxbufsize);
+ pkt_len = min_t(uint, resid, di->rxbufsize);
__skb_trim(p, pkt_len);
tail = p;
@@ -914,7 +950,7 @@ static void *_dma_rx(struct dma_info *di)
D64_RS0_CD_MASK) -
di->rcvptrbase) & D64_RS0_CD_MASK,
struct dma64desc);
- DMA_ERROR(("_dma_rx, rxin %d rxout %d, hw_curr %d\n",
+ DMA_ERROR(("dma_rx, rxin %d rxout %d, hw_curr %d\n",
di->rxin, di->rxout, cur));
}
#endif /* BCMDBG */
@@ -931,19 +967,32 @@ static void *_dma_rx(struct dma_info *di)
return head;
}
-/* post receive buffers
- * return false is refill failed completely and ring is empty
- * this will stall the rx dma and user might want to call rxfill again asap
- * This unlikely happens on memory-rich NIC, but often on memory-constrained dongle
+static bool dma64_rxidle(struct dma_info *di)
+{
+ DMA_TRACE(("%s: dma_rxidle\n", di->name));
+
+ if (di->nrxd == 0)
+ return true;
+
+ return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) ==
+ (R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK));
+}
+
+/*
+ * post receive buffers
+ * return false is refill failed completely and ring is empty this will stall
+ * the rx dma and user might want to call rxfill again asap. This unlikely
+ * happens on memory-rich NIC, but often on memory-constrained dongle
*/
-static bool _dma_rxfill(struct dma_info *di)
+bool dma_rxfill(struct dma_pub *pub)
{
+ struct dma_info *di = (struct dma_info *)pub;
struct sk_buff *p;
u16 rxin, rxout;
u32 flags = 0;
uint n;
uint i;
- dmaaddr_t pa;
+ dma_addr_t pa;
uint extra_offset = 0;
bool ring_empty;
@@ -958,7 +1007,7 @@ static bool _dma_rxfill(struct dma_info *di)
rxin = di->rxin;
rxout = di->rxout;
- n = di->nrxpost - NRXDACTIVE(rxin, rxout);
+ n = di->nrxpost - nrxdactive(di, rxin, rxout);
DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n));
@@ -966,10 +1015,10 @@ static bool _dma_rxfill(struct dma_info *di)
extra_offset = di->rxextrahdrroom;
for (i = 0; i < n; i++) {
- /* the di->rxbufsize doesn't include the extra headroom, we need to add it to the
- size to be allocated
+ /*
+ * the di->rxbufsize doesn't include the extra headroom,
+ * we need to add it to the size to be allocated
*/
-
p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset);
if (p == NULL) {
@@ -992,10 +1041,6 @@ static bool _dma_rxfill(struct dma_info *di)
*/
*(u32 *) (p->data) = 0;
- if (DMASGLIST_ENAB)
- memset(&di->rxp_dmah[rxout], 0,
- sizeof(struct dma_seg_map));
-
pa = pci_map_single(di->pbus, p->data,
di->rxbufsize, PCI_DMA_FROMDEVICE);
@@ -1009,7 +1054,7 @@ static bool _dma_rxfill(struct dma_info *di)
dma64_dd_upd(di, di->rxd64, pa, rxout, &flags,
di->rxbufsize);
- rxout = NEXTRXD(rxout);
+ rxout = nextrxd(di, rxout);
}
di->rxout = rxout;
@@ -1021,49 +1066,10 @@ static bool _dma_rxfill(struct dma_info *di)
return ring_empty;
}
-/* like getnexttxp but no reclaim */
-static void *_dma_peeknexttxp(struct dma_info *di)
+void dma_rxreclaim(struct dma_pub *pub)
{
- uint end, i;
-
- if (di->ntxd == 0)
- return NULL;
-
- end =
- B2I(((R_REG(&di->d64txregs->status0) &
- D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
- struct dma64desc);
-
- for (i = di->txin; i != end; i = NEXTTXD(i))
- if (di->txp[i])
- return di->txp[i];
-
- return NULL;
-}
-
-/* like getnextrxp but not take off the ring */
-static void *_dma_peeknextrxp(struct dma_info *di)
-{
- uint end, i;
-
- if (di->nrxd == 0)
- return NULL;
-
- end =
- B2I(((R_REG(&di->d64rxregs->status0) &
- D64_RS0_CD_MASK) - di->rcvptrbase) & D64_RS0_CD_MASK,
- struct dma64desc);
-
- for (i = di->rxin; i != end; i = NEXTRXD(i))
- if (di->rxp[i])
- return di->rxp[i];
-
- return NULL;
-}
-
-static void _dma_rxreclaim(struct dma_info *di)
-{
- void *p;
+ struct dma_info *di = (struct dma_info *)pub;
+ struct sk_buff *p;
DMA_TRACE(("%s: dma_rxreclaim\n", di->name));
@@ -1071,155 +1077,29 @@ static void _dma_rxreclaim(struct dma_info *di)
brcmu_pkt_buf_free_skb(p);
}
-static void *_dma_getnextrxp(struct dma_info *di, bool forceall)
-{
- if (di->nrxd == 0)
- return NULL;
-
- return dma64_getnextrxp(di, forceall);
-}
-
-static void _dma_txblock(struct dma_info *di)
+void dma_counterreset(struct dma_pub *pub)
{
- di->dma.txavail = 0;
-}
-
-static void _dma_txunblock(struct dma_info *di)
-{
- di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-}
-
-static uint _dma_txactive(struct dma_info *di)
-{
- return NTXDACTIVE(di->txin, di->txout);
-}
-
-static uint _dma_txpending(struct dma_info *di)
-{
- uint curr;
-
- curr =
- B2I(((R_REG(&di->d64txregs->status0) &
- D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
- struct dma64desc);
-
- return NTXDACTIVE(curr, di->txout);
-}
-
-static uint _dma_txcommitted(struct dma_info *di)
-{
- uint ptr;
- uint txin = di->txin;
-
- if (txin == di->txout)
- return 0;
-
- ptr = B2I(R_REG(&di->d64txregs->ptr), struct dma64desc);
-
- return NTXDACTIVE(di->txin, ptr);
-}
-
-static uint _dma_rxactive(struct dma_info *di)
-{
- return NRXDACTIVE(di->rxin, di->rxout);
-}
-
-static void _dma_counterreset(struct dma_info *di)
-{
- /* reset all software counter */
- di->dma.rxgiants = 0;
- di->dma.rxnobuf = 0;
- di->dma.txnobuf = 0;
-}
-
-static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
-{
- uint dmactrlflags = di->dma.dmactrlflags;
-
- if (di == NULL) {
- DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name));
- return 0;
- }
-
- dmactrlflags &= ~mask;
- dmactrlflags |= flags;
-
- /* If trying to enable parity, check if parity is actually supported */
- if (dmactrlflags & DMA_CTRL_PEN) {
- u32 control;
-
- control = R_REG(&di->d64txregs->control);
- W_REG(&di->d64txregs->control,
- control | D64_XC_PD);
- if (R_REG(&di->d64txregs->control) & D64_XC_PD) {
- /* We *can* disable it so it is supported,
- * restore control register
- */
- W_REG(&di->d64txregs->control,
- control);
- } else {
- /* Not supported, don't allow it to be enabled */
- dmactrlflags &= ~DMA_CTRL_PEN;
- }
- }
-
- di->dma.dmactrlflags = dmactrlflags;
-
- return dmactrlflags;
+ /* reset all software counters */
+ pub->rxgiants = 0;
+ pub->rxnobuf = 0;
+ pub->txnobuf = 0;
}
/* get the address of the var in order to change later */
-static unsigned long _dma_getvar(struct dma_info *di, const char *name)
+unsigned long dma_getvar(struct dma_pub *pub, const char *name)
{
+ struct dma_info *di = (struct dma_info *)pub;
+
if (!strcmp(name, "&txavail"))
return (unsigned long)&(di->dma.txavail);
return 0;
}
-static
-u8 dma_align_sizetobits(uint size)
-{
- u8 bitpos = 0;
- while (size >>= 1) {
- bitpos++;
- }
- return bitpos;
-}
-
-/* This function ensures that the DMA descriptor ring will not get allocated
- * across Page boundary. If the allocation is done across the page boundary
- * at the first time, then it is freed and the allocation is done at
- * descriptor ring size aligned location. This will ensure that the ring will
- * not cross page boundary
- */
-static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
- u16 *alignbits, uint *alloced,
- dmaaddr_t *descpa)
-{
- void *va;
- u32 desc_strtaddr;
- u32 alignbytes = 1 << *alignbits;
-
- va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa);
-
- if (NULL == va)
- return NULL;
-
- desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes);
- if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
- & boundary)) {
- *alignbits = dma_align_sizetobits(size);
- pci_free_consistent(di->pbus, size, va, *descpa);
- va = dma_alloc_consistent(di->pbus, size, *alignbits,
- alloced, descpa);
- }
- return va;
-}
-
/* 64-bit DMA functions */
-static void dma64_txinit(struct dma_info *di)
+void dma_txinit(struct dma_pub *pub)
{
+ struct dma_info *di = (struct dma_info *)pub;
u32 control = D64_XC_XE;
DMA_TRACE(("%s: dma_txinit\n", di->name));
@@ -1231,7 +1111,7 @@ static void dma64_txinit(struct dma_info *di)
di->dma.txavail = di->ntxd - 1;
/* clear tx descriptor ring */
- memset((void *)di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc)));
+ memset(di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc)));
/* DMA engine with out alignment requirement requires table to be inited
* before enabling the engine
@@ -1250,17 +1130,10 @@ static void dma64_txinit(struct dma_info *di)
_dma_ddtable_init(di, DMA_TX, di->txdpa);
}
-static bool dma64_txenabled(struct dma_info *di)
+void dma_txsuspend(struct dma_pub *pub)
{
- u32 xc;
+ struct dma_info *di = (struct dma_info *)pub;
- /* If the chip is dead, it is not enabled :-) */
- xc = R_REG(&di->d64txregs->control);
- return (xc != 0xffffffff) && (xc & D64_XC_XE);
-}
-
-static void dma64_txsuspend(struct dma_info *di)
-{
DMA_TRACE(("%s: dma_txsuspend\n", di->name));
if (di->ntxd == 0)
@@ -1269,8 +1142,10 @@ static void dma64_txsuspend(struct dma_info *di)
OR_REG(&di->d64txregs->control, D64_XC_SE);
}
-static void dma64_txresume(struct dma_info *di)
+void dma_txresume(struct dma_pub *pub)
{
+ struct dma_info *di = (struct dma_info *)pub;
+
DMA_TRACE(("%s: dma_txresume\n", di->name));
if (di->ntxd == 0)
@@ -1279,16 +1154,19 @@ static void dma64_txresume(struct dma_info *di)
AND_REG(&di->d64txregs->control, ~D64_XC_SE);
}
-static bool dma64_txsuspended(struct dma_info *di)
+bool dma_txsuspended(struct dma_pub *pub)
{
+ struct dma_info *di = (struct dma_info *)pub;
+
return (di->ntxd == 0) ||
((R_REG(&di->d64txregs->control) & D64_XC_SE) ==
D64_XC_SE);
}
-static void dma64_txreclaim(struct dma_info *di, enum txd_range range)
+void dma_txreclaim(struct dma_pub *pub, enum txd_range range)
{
- void *p;
+ struct dma_info *di = (struct dma_info *)pub;
+ struct sk_buff *p;
DMA_TRACE(("%s: dma_txreclaim %s\n", di->name,
(range == DMA_RANGE_ALL) ? "all" :
@@ -1299,77 +1177,16 @@ static void dma64_txreclaim(struct dma_info *di, enum txd_range range)
if (di->txin == di->txout)
return;
- while ((p = dma64_getnexttxp(di, range))) {
+ while ((p = dma_getnexttxp(pub, range))) {
/* For unframed data, we don't have any packets to free */
if (!(di->dma.dmactrlflags & DMA_CTRL_UNFRAMED))
brcmu_pkt_buf_free_skb(p);
}
}
-static bool dma64_txstopped(struct dma_info *di)
-{
- return ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
- D64_XS0_XS_STOPPED);
-}
-
-static bool dma64_rxstopped(struct dma_info *di)
-{
- return ((R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK) ==
- D64_RS0_RS_STOPPED);
-}
-
-static bool dma64_alloc(struct dma_info *di, uint direction)
-{
- u16 size;
- uint ddlen;
- void *va;
- uint alloced = 0;
- u16 align;
- u16 align_bits;
-
- ddlen = sizeof(struct dma64desc);
-
- size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);
- align_bits = di->dmadesc_align;
- align = (1 << align_bits);
-
- if (direction == DMA_TX) {
- va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
- &alloced, &di->txdpaorig);
- if (va == NULL) {
- DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name));
- return false;
- }
- align = (1 << align_bits);
- di->txd64 = (struct dma64desc *)
- roundup((unsigned long)va, align);
- di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va);
- PHYSADDRLOSET(di->txdpa,
- PHYSADDRLO(di->txdpaorig) + di->txdalign);
- PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig));
- di->txdalloc = alloced;
- } else {
- va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
- &alloced, &di->rxdpaorig);
- if (va == NULL) {
- DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name));
- return false;
- }
- align = (1 << align_bits);
- di->rxd64 = (struct dma64desc *)
- roundup((unsigned long)va, align);
- di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va);
- PHYSADDRLOSET(di->rxdpa,
- PHYSADDRLO(di->rxdpaorig) + di->rxdalign);
- PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig));
- di->rxdalloc = alloced;
- }
-
- return true;
-}
-
-static bool dma64_txreset(struct dma_info *di)
+bool dma_txreset(struct dma_pub *pub)
{
+ struct dma_info *di = (struct dma_info *)pub;
u32 status;
if (di->ntxd == 0)
@@ -1393,19 +1210,9 @@ static bool dma64_txreset(struct dma_info *di)
return status == D64_XS0_XS_DISABLED;
}
-static bool dma64_rxidle(struct dma_info *di)
-{
- DMA_TRACE(("%s: dma_rxidle\n", di->name));
-
- if (di->nrxd == 0)
- return true;
-
- return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) ==
- (R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK));
-}
-
-static bool dma64_rxreset(struct dma_info *di)
+bool dma_rxreset(struct dma_pub *pub)
{
+ struct dma_info *di = (struct dma_info *)pub;
u32 status;
if (di->nrxd == 0)
@@ -1419,132 +1226,21 @@ static bool dma64_rxreset(struct dma_info *di)
return status == D64_RS0_RS_DISABLED;
}
-static bool dma64_rxenabled(struct dma_info *di)
-{
- u32 rc;
-
- rc = R_REG(&di->d64rxregs->control);
- return (rc != 0xffffffff) && (rc & D64_RC_RE);
-}
-
-static bool dma64_txsuspendedidle(struct dma_info *di)
-{
-
- if (di->ntxd == 0)
- return true;
-
- if (!(R_REG(&di->d64txregs->control) & D64_XC_SE))
- return 0;
-
- if ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
- D64_XS0_XS_IDLE)
- return 1;
-
- return 0;
-}
-
-/* Useful when sending unframed data. This allows us to get a progress report from the DMA.
- * We return a pointer to the beginning of the DATA buffer of the current descriptor.
- * If DMA is idle, we return NULL.
- */
-static void *dma64_getpos(struct dma_info *di, bool direction)
-{
- void *va;
- bool idle;
- u32 cd_offset;
-
- if (direction == DMA_TX) {
- cd_offset =
- R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK;
- idle = !NTXDACTIVE(di->txin, di->txout);
- va = di->txp[B2I(cd_offset, struct dma64desc)];
- } else {
- cd_offset =
- R_REG(&di->d64rxregs->status0) & D64_XS0_CD_MASK;
- idle = !NRXDACTIVE(di->rxin, di->rxout);
- va = di->rxp[B2I(cd_offset, struct dma64desc)];
- }
-
- /* If DMA is IDLE, return NULL */
- if (idle) {
- DMA_TRACE(("%s: DMA idle, return NULL\n", __func__));
- va = NULL;
- }
-
- return va;
-}
-
-/* TX of unframed data
- *
- * Adds a DMA ring descriptor for the data pointed to by "buf".
- * This is for DMA of a buffer of data and is unlike other dma TX functions
- * that take a pointer to a "packet"
- * Each call to this is results in a single descriptor being added for "len" bytes of
- * data starting at "buf", it doesn't handle chained buffers.
- */
-static int
-dma64_txunframed(struct dma_info *di, void *buf, uint len, bool commit)
-{
- u16 txout;
- u32 flags = 0;
- dmaaddr_t pa; /* phys addr */
-
- txout = di->txout;
-
- /* return nonzero if out of tx descriptors */
- if (NEXTTXD(txout) == di->txin)
- goto outoftxd;
-
- if (len == 0)
- return 0;
-
- pa = pci_map_single(di->pbus, buf, len, PCI_DMA_TODEVICE);
-
- flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF);
-
- if (txout == (di->ntxd - 1))
- flags |= D64_CTRL1_EOT;
-
- dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
-
- /* save the buffer pointer - used by dma_getpos */
- di->txp[txout] = buf;
-
- txout = NEXTTXD(txout);
- /* bump the tx descriptor index */
- di->txout = txout;
-
- /* kick the chip */
- if (commit) {
- W_REG(&di->d64txregs->ptr,
- di->xmtptrbase + I2B(txout, struct dma64desc));
- }
-
- /* tx flow control */
- di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
- return 0;
-
- outoftxd:
- DMA_ERROR(("%s: %s: out of txds !!!\n", di->name, __func__));
- di->dma.txavail = 0;
- di->dma.txnobuf++;
- return -1;
-}
-
-/* !! tx entry routine
+/*
+ * !! tx entry routine
* WARNING: call must check the return value for error.
- * the error(toss frames) could be fatal and cause many subsequent hard to debug problems
+ * the error(toss frames) could be fatal and cause many subsequent hard
+ * to debug problems
*/
-static int dma64_txfast(struct dma_info *di, struct sk_buff *p0,
- bool commit)
+int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit)
{
+ struct dma_info *di = (struct dma_info *)pub;
struct sk_buff *p, *next;
unsigned char *data;
uint len;
u16 txout;
u32 flags = 0;
- dmaaddr_t pa;
+ dma_addr_t pa;
DMA_TRACE(("%s: dma_txfast\n", di->name));
@@ -1555,77 +1251,46 @@ static int dma64_txfast(struct dma_info *di, struct sk_buff *p0,
* allocating and initializing transmit descriptor entries.
*/
for (p = p0; p; p = next) {
- uint nsegs, j;
- struct dma_seg_map *map;
-
data = p->data;
len = p->len;
next = p->next;
/* return nonzero if out of tx descriptors */
- if (NEXTTXD(txout) == di->txin)
+ if (nexttxd(di, txout) == di->txin)
goto outoftxd;
if (len == 0)
continue;
/* get physical address of buffer start */
- if (DMASGLIST_ENAB)
- memset(&di->txp_dmah[txout], 0,
- sizeof(struct dma_seg_map));
-
pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE);
- if (DMASGLIST_ENAB) {
- map = &di->txp_dmah[txout];
-
- /* See if all the segments can be accounted for */
- if (map->nsegs >
- (uint) (di->ntxd - NTXDACTIVE(di->txin, di->txout) -
- 1))
- goto outoftxd;
-
- nsegs = map->nsegs;
- } else
- nsegs = 1;
-
- for (j = 1; j <= nsegs; j++) {
- flags = 0;
- if (p == p0 && j == 1)
- flags |= D64_CTRL1_SOF;
+ flags = 0;
+ if (p == p0)
+ flags |= D64_CTRL1_SOF;
- /* With a DMA segment list, Descriptor table is filled
- * using the segment list instead of looping over
- * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when
- * end of segment list is reached.
- */
- if ((!DMASGLIST_ENAB && next == NULL) ||
- (DMASGLIST_ENAB && j == nsegs))
- flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF);
- if (txout == (di->ntxd - 1))
- flags |= D64_CTRL1_EOT;
-
- if (DMASGLIST_ENAB) {
- len = map->segs[j - 1].length;
- pa = map->segs[j - 1].addr;
- }
- dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
+ /* With a DMA segment list, Descriptor table is filled
+ * using the segment list instead of looping over
+ * buffers in multi-chain DMA. Therefore, EOF for SGLIST
+ * is when end of segment list is reached.
+ */
+ if (next == NULL)
+ flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF);
+ if (txout == (di->ntxd - 1))
+ flags |= D64_CTRL1_EOT;
- txout = NEXTTXD(txout);
- }
+ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
- /* See above. No need to loop over individual buffers */
- if (DMASGLIST_ENAB)
- break;
+ txout = nexttxd(di, txout);
}
/* if last txd eof not set, fix it */
if (!(flags & D64_CTRL1_EOF))
- W_SM(&di->txd64[PREVTXD(txout)].ctrl1,
- BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF));
+ di->txd64[prevtxd(di, txout)].ctrl1 =
+ cpu_to_le32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF);
/* save the packet */
- di->txp[PREVTXD(txout)] = p0;
+ di->txp[prevtxd(di, txout)] = p0;
/* bump the tx descriptor index */
di->txout = txout;
@@ -1636,7 +1301,7 @@ static int dma64_txfast(struct dma_info *di, struct sk_buff *p0,
di->xmtptrbase + I2B(txout, struct dma64desc));
/* tx flow control */
- di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
+ di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1;
return 0;
@@ -1658,11 +1323,12 @@ static int dma64_txfast(struct dma_info *di, struct sk_buff *p0,
* If range is DMA_RANGE_ALL, reclaim all txd(s) posted to the ring and
* return associated packet regardless of the value of hardware pointers.
*/
-static void *dma64_getnexttxp(struct dma_info *di, enum txd_range range)
+struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
{
+ struct dma_info *di = (struct dma_info *)pub;
u16 start, end, i;
u16 active_desc;
- void *txp;
+ struct sk_buff *txp;
DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name,
(range == DMA_RANGE_ALL) ? "all" :
@@ -1679,7 +1345,7 @@ static void *dma64_getnexttxp(struct dma_info *di, enum txd_range range)
if (range == DMA_RANGE_ALL)
end = di->txout;
else {
- dma64regs_t *dregs = di->d64txregs;
+ struct dma64regs __iomem *dregs = di->d64txregs;
end = (u16) (B2I(((R_REG(&dregs->status0) &
D64_XS0_CD_MASK) -
@@ -1694,45 +1360,28 @@ static void *dma64_getnexttxp(struct dma_info *di, enum txd_range range)
(active_desc - di->xmtptrbase) & D64_XS0_CD_MASK;
active_desc = B2I(active_desc, struct dma64desc);
if (end != active_desc)
- end = PREVTXD(active_desc);
+ end = prevtxd(di, active_desc);
}
}
if ((start == 0) && (end > di->txout))
goto bogus;
- for (i = start; i != end && !txp; i = NEXTTXD(i)) {
- dmaaddr_t pa;
- struct dma_seg_map *map = NULL;
- uint size, j, nsegs;
-
- PHYSADDRLOSET(pa,
- (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) -
- di->dataoffsetlow));
- PHYSADDRHISET(pa,
- (BUS_SWAP32(R_SM(&di->txd64[i].addrhigh)) -
- di->dataoffsethigh));
-
- if (DMASGLIST_ENAB) {
- map = &di->txp_dmah[i];
- size = map->origsize;
- nsegs = map->nsegs;
- } else {
- size =
- (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) &
- D64_CTRL2_BC_MASK);
- nsegs = 1;
- }
+ for (i = start; i != end && !txp; i = nexttxd(di, i)) {
+ dma_addr_t pa;
+ uint size;
- for (j = nsegs; j > 0; j--) {
- W_SM(&di->txd64[i].addrlow, 0xdeadbeef);
- W_SM(&di->txd64[i].addrhigh, 0xdeadbeef);
+ pa = le32_to_cpu(di->txd64[i].addrlow) - di->dataoffsetlow;
- txp = di->txp[i];
- di->txp[i] = NULL;
- if (j > 1)
- i = NEXTTXD(i);
- }
+ size =
+ (le32_to_cpu(di->txd64[i].ctrl2) &
+ D64_CTRL2_BC_MASK);
+
+ di->txd64[i].addrlow = cpu_to_le32(0xdeadbeef);
+ di->txd64[i].addrhigh = cpu_to_le32(0xdeadbeef);
+
+ txp = di->txp[i];
+ di->txp[i] = NULL;
pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE);
}
@@ -1740,157 +1389,16 @@ static void *dma64_getnexttxp(struct dma_info *di, enum txd_range range)
di->txin = i;
/* tx flow control */
- di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
+ di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1;
return txp;
bogus:
- DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", start, end, di->txout, forceall));
+ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d "
+ "force %d\n", start, end, di->txout, forceall));
return NULL;
}
-static void *dma64_getnextrxp(struct dma_info *di, bool forceall)
-{
- uint i, curr;
- void *rxp;
- dmaaddr_t pa;
-
- i = di->rxin;
-
- /* return if no packets posted */
- if (i == di->rxout)
- return NULL;
-
- curr =
- B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) -
- di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc);
-
- /* ignore curr if forceall */
- if (!forceall && (i == curr))
- return NULL;
-
- /* get the packet pointer that corresponds to the rx descriptor */
- rxp = di->rxp[i];
- di->rxp[i] = NULL;
-
- PHYSADDRLOSET(pa,
- (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) -
- di->dataoffsetlow));
- PHYSADDRHISET(pa,
- (BUS_SWAP32(R_SM(&di->rxd64[i].addrhigh)) -
- di->dataoffsethigh));
-
- /* clear this packet from the descriptor ring */
- pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE);
-
- W_SM(&di->rxd64[i].addrlow, 0xdeadbeef);
- W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef);
-
- di->rxin = NEXTRXD(i);
-
- return rxp;
-}
-
-static bool _dma64_addrext(dma64regs_t *dma64regs)
-{
- u32 w;
- OR_REG(&dma64regs->control, D64_XC_AE);
- w = R_REG(&dma64regs->control);
- AND_REG(&dma64regs->control, ~D64_XC_AE);
- return (w & D64_XC_AE) == D64_XC_AE;
-}
-
-/*
- * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin).
- */
-static void dma64_txrotate(struct dma_info *di)
-{
- u16 ad;
- uint nactive;
- uint rot;
- u16 old, new;
- u32 w;
- u16 first, last;
-
- nactive = _dma_txactive(di);
- ad = (u16) (B2I((((R_REG(&di->d64txregs->status1) &
- D64_XS1_AD_MASK) - di->xmtptrbase) &
- D64_XS1_AD_MASK), struct dma64desc));
- rot = TXD(ad - di->txin);
-
- /* full-ring case is a lot harder - don't worry about this */
- if (rot >= (di->ntxd - nactive)) {
- DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name));
- return;
- }
-
- first = di->txin;
- last = PREVTXD(di->txout);
-
- /* move entries starting at last and moving backwards to first */
- for (old = last; old != PREVTXD(first); old = PREVTXD(old)) {
- new = TXD(old + rot);
-
- /*
- * Move the tx dma descriptor.
- * EOT is set only in the last entry in the ring.
- */
- w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl1)) & ~D64_CTRL1_EOT;
- if (new == (di->ntxd - 1))
- w |= D64_CTRL1_EOT;
- W_SM(&di->txd64[new].ctrl1, BUS_SWAP32(w));
-
- w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl2));
- W_SM(&di->txd64[new].ctrl2, BUS_SWAP32(w));
-
- W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow));
- W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh));
-
- /* zap the old tx dma descriptor address field */
- W_SM(&di->txd64[old].addrlow, BUS_SWAP32(0xdeadbeef));
- W_SM(&di->txd64[old].addrhigh, BUS_SWAP32(0xdeadbeef));
-
- /* move the corresponding txp[] entry */
- di->txp[new] = di->txp[old];
-
- /* Move the map */
- if (DMASGLIST_ENAB) {
- memcpy(&di->txp_dmah[new], &di->txp_dmah[old],
- sizeof(struct dma_seg_map));
- memset(&di->txp_dmah[old], 0,
- sizeof(struct dma_seg_map));
- }
-
- di->txp[old] = NULL;
- }
-
- /* update txin and txout */
- di->txin = ad;
- di->txout = TXD(di->txout + rot);
- di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
- /* kick the chip */
- W_REG(&di->d64txregs->ptr,
- di->xmtptrbase + I2B(di->txout, struct dma64desc));
-}
-
-uint dma_addrwidth(struct si_pub *sih, void *dmaregs)
-{
- /* Perform 64-bit checks only if we want to advertise 64-bit (> 32bit) capability) */
- /* DMA engine is 64-bit capable */
- if ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64) {
- /* backplane are 64-bit capable */
- if (ai_backplane64(sih))
- /* If bus is System Backplane or PCIE then we can access 64-bits */
- if ((sih->bustype == SI_BUS) ||
- ((sih->bustype == PCI_BUS) &&
- (sih->buscoretype == PCIE_CORE_ID)))
- return DMADDRWIDTH_64;
- }
- /* DMA hardware not supported by this driver*/
- return DMADDRWIDTH_64;
-}
-
/*
* Mac80211 initiated actions sometimes require packets in the DMA queue to be
* modified. The modified portion of the packet is not under control of the DMA
@@ -1912,6 +1420,6 @@ void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
tx_info = (struct ieee80211_tx_info *)skb->cb;
(callback_fnc)(tx_info, arg_a);
}
- i = NEXTTXD(i);
+ i = nexttxd(di, i);
}
}
diff --git a/drivers/staging/brcm80211/brcmsmac/dma.h b/drivers/staging/brcm80211/brcmsmac/dma.h
index 9c8b9a6a557e..ebc5bc546f3b 100644
--- a/drivers/staging/brcm80211/brcmsmac/dma.h
+++ b/drivers/staging/brcm80211/brcmsmac/dma.h
@@ -17,8 +17,13 @@
#ifndef _BRCM_DMA_H_
#define _BRCM_DMA_H_
+#include <linux/delay.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)
@@ -38,19 +43,14 @@ struct dma32diag { /* diag access */
/* dma registers per channel(xmt or rcv) */
struct dma64regs {
- u32 control; /* enable, et al */
- u32 ptr; /* last descriptor posted to chip */
- u32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */
- u32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */
- u32 status0; /* current descriptor, xmt state */
- u32 status1; /* active descriptor, xmt error */
+ 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 */
};
-/* map/unmap direction */
-#define DMA_TX 1 /* TX direction for DMA */
-#define DMA_RX 2 /* RX direction for DMA */
-#define BUS_SWAP32(v) (v)
-
/* range param for dma_getnexttxp() and dma_txreclaim */
enum txd_range {
DMA_RANGE_ALL = 1,
@@ -58,110 +58,11 @@ enum txd_range {
DMA_RANGE_TRANSFERED
};
-/* dma function type */
-typedef void (*di_detach_t) (struct dma_pub *dmah);
-typedef bool(*di_txreset_t) (struct dma_pub *dmah);
-typedef bool(*di_rxreset_t) (struct dma_pub *dmah);
-typedef bool(*di_rxidle_t) (struct dma_pub *dmah);
-typedef void (*di_txinit_t) (struct dma_pub *dmah);
-typedef bool(*di_txenabled_t) (struct dma_pub *dmah);
-typedef void (*di_rxinit_t) (struct dma_pub *dmah);
-typedef void (*di_txsuspend_t) (struct dma_pub *dmah);
-typedef void (*di_txresume_t) (struct dma_pub *dmah);
-typedef bool(*di_txsuspended_t) (struct dma_pub *dmah);
-typedef bool(*di_txsuspendedidle_t) (struct dma_pub *dmah);
-typedef int (*di_txfast_t) (struct dma_pub *dmah, struct sk_buff *p,
- bool commit);
-typedef int (*di_txunframed_t) (struct dma_pub *dmah, void *p, uint len,
- bool commit);
-typedef void *(*di_getpos_t) (struct dma_pub *di, bool direction);
-typedef void (*di_fifoloopbackenable_t) (struct dma_pub *dmah);
-typedef bool(*di_txstopped_t) (struct dma_pub *dmah);
-typedef bool(*di_rxstopped_t) (struct dma_pub *dmah);
-typedef bool(*di_rxenable_t) (struct dma_pub *dmah);
-typedef bool(*di_rxenabled_t) (struct dma_pub *dmah);
-typedef void *(*di_rx_t) (struct dma_pub *dmah);
-typedef bool(*di_rxfill_t) (struct dma_pub *dmah);
-typedef void (*di_txreclaim_t) (struct dma_pub *dmah, enum txd_range range);
-typedef void (*di_rxreclaim_t) (struct dma_pub *dmah);
-typedef unsigned long (*di_getvar_t) (struct dma_pub *dmah,
- const char *name);
-typedef void *(*di_getnexttxp_t) (struct dma_pub *dmah, enum txd_range range);
-typedef void *(*di_getnextrxp_t) (struct dma_pub *dmah, bool forceall);
-typedef void *(*di_peeknexttxp_t) (struct dma_pub *dmah);
-typedef void *(*di_peeknextrxp_t) (struct dma_pub *dmah);
-typedef void (*di_rxparam_get_t) (struct dma_pub *dmah, u16 *rxoffset,
- u16 *rxbufsize);
-typedef void (*di_txblock_t) (struct dma_pub *dmah);
-typedef void (*di_txunblock_t) (struct dma_pub *dmah);
-typedef uint(*di_txactive_t) (struct dma_pub *dmah);
-typedef void (*di_txrotate_t) (struct dma_pub *dmah);
-typedef void (*di_counterreset_t) (struct dma_pub *dmah);
-typedef uint(*di_ctrlflags_t) (struct dma_pub *dmah, uint mask, uint flags);
-typedef char *(*di_dump_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
- bool dumpring);
-typedef char *(*di_dumptx_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
- bool dumpring);
-typedef char *(*di_dumprx_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
- bool dumpring);
-typedef uint(*di_rxactive_t) (struct dma_pub *dmah);
-typedef uint(*di_txpending_t) (struct dma_pub *dmah);
-typedef uint(*di_txcommitted_t) (struct dma_pub *dmah);
-
-/* dma opsvec */
-struct di_fcn_s {
- di_detach_t detach;
- di_txinit_t txinit;
- di_txreset_t txreset;
- di_txenabled_t txenabled;
- di_txsuspend_t txsuspend;
- di_txresume_t txresume;
- di_txsuspended_t txsuspended;
- di_txsuspendedidle_t txsuspendedidle;
- di_txfast_t txfast;
- di_txunframed_t txunframed;
- di_getpos_t getpos;
- di_txstopped_t txstopped;
- di_txreclaim_t txreclaim;
- di_getnexttxp_t getnexttxp;
- di_peeknexttxp_t peeknexttxp;
- di_txblock_t txblock;
- di_txunblock_t txunblock;
- di_txactive_t txactive;
- di_txrotate_t txrotate;
-
- di_rxinit_t rxinit;
- di_rxreset_t rxreset;
- di_rxidle_t rxidle;
- di_rxstopped_t rxstopped;
- di_rxenable_t rxenable;
- di_rxenabled_t rxenabled;
- di_rx_t rx;
- di_rxfill_t rxfill;
- di_rxreclaim_t rxreclaim;
- di_getnextrxp_t getnextrxp;
- di_peeknextrxp_t peeknextrxp;
- di_rxparam_get_t rxparam_get;
-
- di_fifoloopbackenable_t fifoloopbackenable;
- di_getvar_t d_getvar;
- di_counterreset_t counterreset;
- di_ctrlflags_t ctrlflags;
- di_dump_t dump;
- di_dumptx_t dumptx;
- di_dumprx_t dumprx;
- di_rxactive_t rxactive;
- di_txpending_t txpending;
- di_txcommitted_t txcommitted;
- uint endnum;
-};
-
/*
* Exported data structure (read-only)
*/
/* export structure */
struct dma_pub {
- const struct di_fcn_s *di_fn; /* DMA function pointers */
uint txavail; /* # free tx descriptors */
uint dmactrlflags; /* dma control flags */
@@ -173,78 +74,47 @@ struct dma_pub {
};
extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
- void *dmaregstx, void *dmaregsrx, uint ntxd,
- uint nrxd, uint rxbufsize, int rxextheadroom,
+ void __iomem *dmaregstx, void __iomem *dmaregsrx,
+ uint ntxd, uint nrxd,
+ uint rxbufsize, int rxextheadroom,
uint nrxpost, uint rxoffset, uint *msg_level);
-extern const struct di_fcn_s dma64proc;
-
-#define dma_detach(di) (dma64proc.detach(di))
-#define dma_txreset(di) (dma64proc.txreset(di))
-#define dma_rxreset(di) (dma64proc.rxreset(di))
-#define dma_rxidle(di) (dma64proc.rxidle(di))
-#define dma_txinit(di) (dma64proc.txinit(di))
-#define dma_txenabled(di) (dma64proc.txenabled(di))
-#define dma_rxinit(di) (dma64proc.rxinit(di))
-#define dma_txsuspend(di) (dma64proc.txsuspend(di))
-#define dma_txresume(di) (dma64proc.txresume(di))
-#define dma_txsuspended(di) (dma64proc.txsuspended(di))
-#define dma_txsuspendedidle(di) (dma64proc.txsuspendedidle(di))
-#define dma_txfast(di, p, commit) (dma64proc.txfast(di, p, commit))
-#define dma_txunframed(di, p, l, commit)(dma64proc.txunframed(di, p, l, commit))
-#define dma_getpos(di, dir) (dma64proc.getpos(di, dir))
-#define dma_fifoloopbackenable(di) (dma64proc.fifoloopbackenable(di))
-#define dma_txstopped(di) (dma64proc.txstopped(di))
-#define dma_rxstopped(di) (dma64proc.rxstopped(di))
-#define dma_rxenable(di) (dma64proc.rxenable(di))
-#define dma_rxenabled(di) (dma64proc.rxenabled(di))
-#define dma_rx(di) (dma64proc.rx(di))
-#define dma_rxfill(di) (dma64proc.rxfill(di))
-#define dma_txreclaim(di, range) (dma64proc.txreclaim(di, range))
-#define dma_rxreclaim(di) (dma64proc.rxreclaim(di))
-#define dma_getvar(di, name) (dma64proc.d_getvar(di, name))
-#define dma_getnexttxp(di, range) (dma64proc.getnexttxp(di, range))
-#define dma_getnextrxp(di, forceall) (dma64proc.getnextrxp(di, forceall))
-#define dma_peeknexttxp(di) (dma64proc.peeknexttxp(di))
-#define dma_peeknextrxp(di) (dma64proc.peeknextrxp(di))
-#define dma_rxparam_get(di, off, bufs) (dma64proc.rxparam_get(di, off, bufs))
-
-#define dma_txblock(di) (dma64proc.txblock(di))
-#define dma_txunblock(di) (dma64proc.txunblock(di))
-#define dma_txactive(di) (dma64proc.txactive(di))
-#define dma_rxactive(di) (dma64proc.rxactive(di))
-#define dma_txrotate(di) (dma64proc.txrotate(di))
-#define dma_counterreset(di) (dma64proc.counterreset(di))
-#define dma_ctrlflags(di, mask, flags) (dma64proc.ctrlflags((di), (mask), (flags)))
-#define dma_txpending(di) (dma64proc.txpending(di))
-#define dma_txcommitted(di) (dma64proc.txcommitted(di))
-
-
-/* return addresswidth allowed
- * This needs to be done after SB attach but before dma attach.
- * SB attach provides ability to probe backplane and dma core capabilities
- * This info is needed by DMA_ALLOC_CONSISTENT in dma attach
- */
-extern uint dma_addrwidth(struct si_pub *sih, void *dmaregs);
+void dma_rxinit(struct dma_pub *pub);
+struct sk_buff *dma_rx(struct dma_pub *pub);
+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 dma_pub *pub, struct sk_buff *p0, bool commit);
+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 some chips seems to declare that the packet is ready, but the
- * packet length is not updated yet (by DMA) on the expected time.
+ * 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(__mips__)
+#if defined(CONFIG_BCM47XX)
if (!len) {
while (!(len = *(u16 *) KSEG1ADDR(head->data)))
udelay(1);
*(u16 *) (head->data) = cpu_to_le16((u16) len);
}
-#endif /* defined(__mips__) */
+#endif /* defined(CONFIG_BCM47XX) */
}
#endif /* _BRCM_DMA_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/mac80211_if.c b/drivers/staging/brcm80211/brcmsmac/mac80211_if.c
index 3cb92fc0391a..ac8d02bd34f2 100644
--- a/drivers/staging/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/staging/brcm80211/brcmsmac/mac80211_if.c
@@ -31,38 +31,10 @@
#include "pub.h"
#include "ucode_loader.h"
#include "mac80211_if.h"
+#include "main.h"
#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */
-#define LOCK(wl) spin_lock_bh(&(wl)->lock)
-#define UNLOCK(wl) spin_unlock_bh(&(wl)->lock)
-
-/* locking from inside brcms_isr */
-#define ISR_LOCK(wl, flags)\
- do {\
- spin_lock(&(wl)->isr_lock);\
- (void)(flags); } \
- while (0)
-
-#define ISR_UNLOCK(wl, flags)\
- do {\
- spin_unlock(&(wl)->isr_lock);\
- (void)(flags); } \
- while (0)
-
-/* locking under LOCK() to synchronize with brcms_isr */
-#define INT_LOCK(wl, flags) spin_lock_irqsave(&(wl)->isr_lock, flags)
-#define INT_UNLOCK(wl, flags) spin_unlock_irqrestore(&(wl)->isr_lock, flags)
-
-static void brcms_timer(unsigned long data);
-static void _brcms_timer(struct brcms_timer *t);
-
-
-static int ieee_hw_init(struct ieee80211_hw *hw);
-static int ieee_hw_rate_init(struct ieee80211_hw *hw);
-
-static int wl_linux_watchdog(void *ctx);
-
/* Flags we support */
#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | \
@@ -72,20 +44,42 @@ static int wl_linux_watchdog(void *ctx);
FIF_OTHER_BSS | \
FIF_BCN_PRBRESP_PROMISC)
-static int n_adapters_found;
+#define CHAN2GHZ(channel, freqency, chflags) { \
+ .band = IEEE80211_BAND_2GHZ, \
+ .center_freq = (freqency), \
+ .hw_value = (channel), \
+ .flags = chflags, \
+ .max_antenna_gain = 0, \
+ .max_power = 19, \
+}
+
+#define CHAN5GHZ(channel, chflags) { \
+ .band = IEEE80211_BAND_5GHZ, \
+ .center_freq = 5000 + 5*(channel), \
+ .hw_value = (channel), \
+ .flags = chflags, \
+ .max_antenna_gain = 0, \
+ .max_power = 21, \
+}
+
+#define RATE(rate100m, _flags) { \
+ .bitrate = (rate100m), \
+ .flags = (_flags), \
+ .hw_value = (rate100m / 5), \
+}
-static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev);
-static void brcms_release_fw(struct brcms_info *wl);
+struct firmware_hdr {
+ __le32 offset;
+ __le32 len;
+ __le32 idx;
+};
-/* local prototypes */
-static void brcms_dpc(unsigned long data);
-static irqreturn_t brcms_isr(int irq, void *dev_id);
+static const char * const brcms_firmwares[MAX_FW_IMAGES] = {
+ "brcm/bcm43xx",
+ NULL
+};
-static int __devinit brcms_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent);
-static void brcms_remove(struct pci_dev *pdev);
-static void brcms_free(struct brcms_info *wl);
-static void brcms_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br);
+static int n_adapters_found;
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
@@ -94,11 +88,10 @@ MODULE_LICENSE("Dual BSD/GPL");
/* recognized PCI IDs */
static DEFINE_PCI_DEVICE_TABLE(brcms_pci_id_table) = {
- {PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 43225 2G */
- {PCI_VENDOR_ID_BROADCOM, 0x4353, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 43224 DUAL */
- {PCI_VENDOR_ID_BROADCOM, 0x4727, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 4313 DUAL */
- /* 43224 Ven */
- {PCI_VENDOR_ID_BROADCOM, 0x0576, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, /* 43225 2G */
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, /* 43224 DUAL */
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, /* 4313 DUAL */
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, /* 43224 Ven */
{0}
};
@@ -107,60 +100,178 @@ MODULE_DEVICE_TABLE(pci, brcms_pci_id_table);
#ifdef BCMDBG
static int msglevel = 0xdeadbeef;
module_param(msglevel, int, 0);
-static int phymsglevel = 0xdeadbeef;
-module_param(phymsglevel, int, 0);
#endif /* BCMDBG */
-#define HW_TO_WL(hw) (hw->priv)
-#define WL_TO_HW(wl) (wl->pub->ieee_hw)
-
-/* MAC80211 callback functions */
-static int brcms_ops_start(struct ieee80211_hw *hw);
-static void brcms_ops_stop(struct ieee80211_hw *hw);
-static int brcms_ops_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-static void brcms_ops_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed);
-static void brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *info,
- u32 changed);
-static void brcms_ops_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *total_flags, u64 multicast);
-static int brcms_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
- bool set);
-static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw);
-static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw);
-static void brcms_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf);
-static int brcms_ops_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats);
-static void brcms_ops_sta_notify(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- enum sta_notify_cmd cmd,
- struct ieee80211_sta *sta);
-static int brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
- const struct ieee80211_tx_queue_params *params);
-static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw);
-static int brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-static int brcms_ops_sta_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-static int brcms_ops_ampdu_action(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size);
-static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw);
-static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop);
+static struct ieee80211_channel brcms_2ghz_chantable[] = {
+ CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN2GHZ(5, 2432, 0),
+ CHAN2GHZ(6, 2437, 0),
+ CHAN2GHZ(7, 2442, 0),
+ CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(12, 2467,
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(13, 2472,
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(14, 2484,
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+};
+
+static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = {
+ /* UNII-1 */
+ CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
+ /* UNII-2 */
+ CHAN5GHZ(52,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(56,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(60,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(64,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ /* MID */
+ CHAN5GHZ(100,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(104,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(108,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(112,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(116,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(120,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(124,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(128,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(132,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(136,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(140,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
+ IEEE80211_CHAN_NO_HT40MINUS),
+ /* UNII-3 */
+ CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+};
+
+/*
+ * The rate table is used for both 2.4G and 5G rates. The
+ * latter being a subset as it does not support CCK rates.
+ */
+static struct ieee80211_rate legacy_ratetable[] = {
+ RATE(10, 0),
+ RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(60, 0),
+ RATE(90, 0),
+ RATE(120, 0),
+ RATE(180, 0),
+ RATE(240, 0),
+ RATE(360, 0),
+ RATE(480, 0),
+ RATE(540, 0),
+};
+
+static const struct ieee80211_supported_band brcms_band_2GHz_nphy_template = {
+ .band = IEEE80211_BAND_2GHZ,
+ .channels = brcms_2ghz_chantable,
+ .n_channels = ARRAY_SIZE(brcms_2ghz_chantable),
+ .bitrates = legacy_ratetable,
+ .n_bitrates = ARRAY_SIZE(legacy_ratetable),
+ .ht_cap = {
+ /* from include/linux/ieee80211.h */
+ .cap = IEEE80211_HT_CAP_GRN_FLD |
+ IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
+ .ht_supported = true,
+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+ .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
+ .mcs = {
+ /* placeholders for now */
+ .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
+ .rx_highest = cpu_to_le16(500),
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
+ }
+};
+
+static const struct ieee80211_supported_band brcms_band_5GHz_nphy_template = {
+ .band = IEEE80211_BAND_5GHZ,
+ .channels = brcms_5ghz_nphy_chantable,
+ .n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable),
+ .bitrates = legacy_ratetable + BRCMS_LEGACY_5G_RATE_OFFSET,
+ .n_bitrates = ARRAY_SIZE(legacy_ratetable) -
+ BRCMS_LEGACY_5G_RATE_OFFSET,
+ .ht_cap = {
+ .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_SGI_40 |
+ IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */
+ .ht_supported = true,
+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+ .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
+ .mcs = {
+ /* placeholders for now */
+ .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
+ .rx_highest = cpu_to_le16(500),
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
+ }
+};
+
+/* flags the given rate in rateset as requested */
+static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br)
+{
+ u32 i;
+
+ for (i = 0; i < rs->count; i++) {
+ if (rate != (rs->rates[i] & 0x7f))
+ continue;
+
+ if (is_br)
+ rs->rates[i] |= BRCMS_RATE_FLAG;
+ else
+ rs->rates[i] &= BRCMS_RATE_MASK;
+ return;
+ }
+}
static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct brcms_info *wl = hw->priv;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
if (!wl->pub->up) {
wiphy_err(wl->wiphy, "ops->tx called while down\n");
kfree_skb(skb);
@@ -168,21 +279,18 @@ static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
}
brcms_c_sendpkt_mac80211(wl->wlc, skb, hw);
done:
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
}
static int brcms_ops_start(struct ieee80211_hw *hw)
{
struct brcms_info *wl = hw->priv;
bool blocked;
- /*
- struct ieee80211_channel *curchan = hw->conf.channel;
- */
ieee80211_wake_queues(hw);
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
blocked = brcms_rfkill_set_hw_state(wl);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
if (!blocked)
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
@@ -211,15 +319,18 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
return -EOPNOTSUPP;
}
- wl = HW_TO_WL(hw);
- LOCK(wl);
- err = brcms_up(wl);
- UNLOCK(wl);
+ wl = hw->priv;
+ spin_lock_bh(&wl->lock);
+ if (!wl->pub->up)
+ err = brcms_up(wl);
+ else
+ err = -ENODEV;
+ spin_unlock_bh(&wl->lock);
- if (err != 0) {
+ if (err != 0)
wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__,
err);
- }
+
return err;
}
@@ -228,60 +339,26 @@ brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct brcms_info *wl;
- wl = HW_TO_WL(hw);
+ wl = hw->priv;
/* put driver in down state */
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_down(wl);
- UNLOCK(wl);
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-static int
-ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
- enum nl80211_channel_type type)
-{
- struct brcms_info *wl = HW_TO_WL(hw);
- int err = 0;
-
- switch (type) {
- case NL80211_CHAN_HT20:
- case NL80211_CHAN_NO_HT:
- err = brcms_c_set(wl->wlc, BRCM_SET_CHANNEL, chan->hw_value);
- break;
- case NL80211_CHAN_HT40MINUS:
- case NL80211_CHAN_HT40PLUS:
- wiphy_err(hw->wiphy,
- "%s: Need to implement 40 Mhz Channels!\n", __func__);
- err = 1;
- break;
- }
-
- if (err)
- return -EIO;
- return err;
+ spin_unlock_bh(&wl->lock);
}
static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
{
struct ieee80211_conf *conf = &hw->conf;
- struct brcms_info *wl = HW_TO_WL(hw);
+ struct brcms_info *wl = hw->priv;
int err = 0;
int new_int;
struct wiphy *wiphy = hw->wiphy;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
- if (brcms_c_set_par(wl->wlc, IOV_BCN_LI_BCN,
- conf->listen_interval) < 0) {
- wiphy_err(wiphy, "%s: Error setting listen_interval\n",
- __func__);
- err = -EIO;
- goto config_out;
- }
- brcms_c_get_par(wl->wlc, IOV_BCN_LI_BCN, &new_int);
+ brcms_c_set_beacon_listen_interval(wl->wlc,
+ conf->listen_interval);
}
if (changed & IEEE80211_CONF_CHANGE_MONITOR)
wiphy_err(wiphy, "%s: change monitor mode: %s (implement)\n",
@@ -293,40 +370,33 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
"true" : "false");
if (changed & IEEE80211_CONF_CHANGE_POWER) {
- if (brcms_c_set_par(wl->wlc, IOV_QTXPOWER,
- conf->power_level * 4) < 0) {
+ err = brcms_c_set_tx_power(wl->wlc, conf->power_level);
+ if (err < 0) {
wiphy_err(wiphy, "%s: Error setting power_level\n",
__func__);
- err = -EIO;
goto config_out;
}
- brcms_c_get_par(wl->wlc, IOV_QTXPOWER, &new_int);
- if (new_int != (conf->power_level * 4))
+ new_int = brcms_c_get_tx_power(wl->wlc);
+ if (new_int != conf->power_level)
wiphy_err(wiphy, "%s: Power level req != actual, %d %d"
- "\n", __func__, conf->power_level * 4,
+ "\n", __func__, conf->power_level,
new_int);
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- err = ieee_set_channel(hw, conf->channel, conf->channel_type);
- }
- if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
- if (brcms_c_set
- (wl->wlc, BRCM_SET_SRL,
- conf->short_frame_max_tx_count) < 0) {
- wiphy_err(wiphy, "%s: Error setting srl\n", __func__);
- err = -EIO;
- goto config_out;
- }
- if (brcms_c_set(wl->wlc, BRCM_SET_LRL,
- conf->long_frame_max_tx_count) < 0) {
- wiphy_err(wiphy, "%s: Error setting lrl\n", __func__);
- err = -EIO;
- goto config_out;
- }
+ if (conf->channel_type == NL80211_CHAN_HT20 ||
+ conf->channel_type == NL80211_CHAN_NO_HT)
+ err = brcms_c_set_channel(wl->wlc,
+ conf->channel->hw_value);
+ else
+ err = -ENOTSUPP;
}
+ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+ err = brcms_c_set_rate_limit(wl->wlc,
+ conf->short_frame_max_tx_count,
+ conf->long_frame_max_tx_count);
config_out:
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
return err;
}
@@ -335,9 +405,8 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info, u32 changed)
{
- struct brcms_info *wl = HW_TO_WL(hw);
+ struct brcms_info *wl = hw->priv;
struct wiphy *wiphy = hw->wiphy;
- int val;
if (changed & BSS_CHANGED_ASSOC) {
/* association status changed (associated/disassociated)
@@ -345,51 +414,48 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
*/
wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME,
__func__, info->assoc ? "" : "dis");
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_associate_upd(wl->wlc, info->assoc);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_ERP_SLOT) {
+ s8 val;
+
/* slot timing changed */
if (info->use_short_slot)
val = 1;
else
val = 0;
- LOCK(wl);
- brcms_c_set(wl->wlc, BRCMS_SET_SHORTSLOT_OVERRIDE, val);
- UNLOCK(wl);
+ spin_lock_bh(&wl->lock);
+ brcms_c_set_shortslot_override(wl->wlc, val);
+ spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_HT) {
/* 802.11n parameters changed */
u16 mode = info->ht_operation_mode;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_CFG,
mode & IEEE80211_HT_OP_MODE_PROTECTION);
brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_NONGF,
mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_OBSS,
mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
struct ieee80211_supported_band *bi;
u32 br_mask, i;
u16 rate;
- struct wl_rateset rs;
+ struct brcm_rateset rs;
int error;
/* retrieve the current rates */
- LOCK(wl);
- error = brcms_c_ioctl(wl->wlc, BRCM_GET_CURR_RATESET,
- &rs, sizeof(rs), NULL);
- UNLOCK(wl);
- if (error) {
- wiphy_err(wiphy, "%s: retrieve rateset failed: %d\n",
- __func__, error);
- return;
- }
+ spin_lock_bh(&wl->lock);
+ brcms_c_get_current_rateset(wl->wlc, &rs);
+ spin_unlock_bh(&wl->lock);
+
br_mask = info->basic_rates;
bi = hw->wiphy->bands[brcms_c_get_curband(wl->wlc)];
for (i = 0; i < bi->n_bitrates; i++) {
@@ -402,49 +468,55 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
}
/* update the rate set */
- LOCK(wl);
- brcms_c_ioctl(wl->wlc, BRCM_SET_RATESET, &rs, sizeof(rs), NULL);
- UNLOCK(wl);
+ spin_lock_bh(&wl->lock);
+ error = brcms_c_set_rateset(wl->wlc, &rs);
+ spin_unlock_bh(&wl->lock);
+ if (error)
+ wiphy_err(wiphy, "changing basic rates failed: %d\n",
+ error);
}
if (changed & BSS_CHANGED_BEACON_INT) {
/* Beacon interval changed */
- LOCK(wl);
- brcms_c_set(wl->wlc, BRCM_SET_BCNPRD, info->beacon_int);
- UNLOCK(wl);
+ spin_lock_bh(&wl->lock);
+ brcms_c_set_beacon_period(wl->wlc, info->beacon_int);
+ spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_BSSID) {
/* BSSID changed, for whatever reason (IBSS and managed mode) */
- LOCK(wl);
- brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET,
- info->bssid);
- UNLOCK(wl);
+ spin_lock_bh(&wl->lock);
+ brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid);
+ spin_unlock_bh(&wl->lock);
}
- if (changed & BSS_CHANGED_BEACON) {
+ if (changed & BSS_CHANGED_BEACON)
/* Beacon data changed, retrieve new beacon (beaconing modes) */
wiphy_err(wiphy, "%s: beacon changed\n", __func__);
- }
+
if (changed & BSS_CHANGED_BEACON_ENABLED) {
/* Beaconing should be enabled/disabled (beaconing modes) */
wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__,
info->enable_beacon ? "true" : "false");
}
+
if (changed & BSS_CHANGED_CQM) {
/* Connection quality monitor config changed */
wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d "
" (implement)\n", __func__, info->cqm_rssi_thold,
info->cqm_rssi_hyst);
}
+
if (changed & BSS_CHANGED_IBSS) {
/* IBSS join status changed */
wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__,
info->ibss_joined ? "true" : "false");
}
+
if (changed & BSS_CHANGED_ARP_FILTER) {
/* Hardware ARP filter address list or state changed */
wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d"
" (implement)\n", __func__, info->arp_filter_enabled ?
"true" : "false", info->arp_addr_cnt);
}
+
if (changed & BSS_CHANGED_QOS) {
/*
* QoS for this association was enabled/disabled.
@@ -479,7 +551,7 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw,
if (changed_flags & FIF_OTHER_BSS)
wiphy_err(wiphy, "FIF_OTHER_BSS\n");
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS;
brcms_c_mac_bcn_promisc_change(wl->wlc, 1);
@@ -487,113 +559,54 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw,
brcms_c_mac_bcn_promisc_change(wl->wlc, 0);
wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS;
}
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
}
return;
}
-static int
-brcms_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
-{
- return 0;
-}
-
static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw)
{
struct brcms_info *wl = hw->priv;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_scan_start(wl->wlc);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
return;
}
static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw)
{
struct brcms_info *wl = hw->priv;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_scan_stop(wl->wlc);
- UNLOCK(wl);
- return;
-}
-
-static void brcms_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf)
-{
- wiphy_err(hw->wiphy, "%s: Enter\n", __func__);
+ spin_unlock_bh(&wl->lock);
return;
}
static int
-brcms_ops_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
+brcms_ops_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
{
struct brcms_info *wl = hw->priv;
- struct wl_cnt *cnt;
-
- LOCK(wl);
- cnt = wl->pub->_cnt;
- stats->dot11ACKFailureCount = 0;
- stats->dot11RTSFailureCount = 0;
- stats->dot11FCSErrorCount = 0;
- stats->dot11RTSSuccessCount = 0;
- UNLOCK(wl);
- return 0;
-}
-static void
-brcms_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
-{
- switch (cmd) {
- default:
- wiphy_err(hw->wiphy, "%s: Unknown cmd = %d\n", __func__,
- cmd);
- break;
- }
- return;
-}
-
-static int
-brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
- const struct ieee80211_tx_queue_params *params)
-{
- struct brcms_info *wl = hw->priv;
-
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_wme_setparams(wl->wlc, queue, params, true);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
return 0;
}
-static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw)
-{
- wiphy_err(hw->wiphy, "%s: Enter\n", __func__);
- return 0;
-}
-
static int
brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct scb *scb;
-
- int i;
struct brcms_info *wl = hw->priv;
+ struct scb *scb = &wl->wlc->pri_scb;
- /* Init the scb */
- scb = (struct scb *)sta->drv_priv;
- memset(scb, 0, sizeof(struct scb));
- for (i = 0; i < NUMPRIO; i++)
- scb->seqctl[i] = 0xFFFF;
- scb->seqctl_nonqos = 0xFFFF;
- scb->magic = SCB_MAGIC;
+ brcms_c_init_scb(scb);
- wl->pub->global_scb = scb;
wl->pub->global_ampdu = &(scb->scb_ampdu);
wl->pub->global_ampdu->scb = scb;
wl->pub->global_ampdu->max_pdu = 16;
- brcmu_pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID,
- AMPDU_MAX_SCB_TID * PKTQ_LEN_DEFAULT);
sta->ht_cap.ht_supported = true;
sta->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
@@ -602,14 +615,10 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT;
- /* minstrel_ht initiates addBA on our behalf by calling ieee80211_start_tx_ba_session() */
- return 0;
-}
-
-static int
-brcms_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
+ /*
+ * minstrel_ht initiates addBA on our behalf by calling
+ * ieee80211_start_tx_ba_session()
+ */
return 0;
}
@@ -620,8 +629,8 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
u8 buf_size)
{
- struct scb *scb = (struct scb *)sta->drv_priv;
struct brcms_info *wl = hw->priv;
+ struct scb *scb = &wl->wlc->pri_scb;
int status;
if (WARN_ON(scb->magic != SCB_MAGIC))
@@ -632,23 +641,21 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_RX_STOP:
break;
case IEEE80211_AMPDU_TX_START:
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
status = brcms_c_aggregatable(wl->wlc, tid);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
if (!status) {
wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n",
tid);
return -EINVAL;
}
- /* Future improvement: Use the starting sequence number provided ... */
- *ssn = 0;
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP:
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_ampdu_flush(wl->wlc, sta, tid);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
@@ -658,11 +665,11 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
* recipient and traffic class. 'ampdu_factor' gives maximum
* AMPDU size.
*/
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size,
(1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor)) - 1);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
/* Power save wakeup */
break;
default:
@@ -675,26 +682,26 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw)
{
- struct brcms_info *wl = HW_TO_WL(hw);
+ struct brcms_info *wl = hw->priv;
bool blocked;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
blocked = brcms_c_check_radio_disabled(wl->wlc);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
}
static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
{
- struct brcms_info *wl = HW_TO_WL(hw);
+ struct brcms_info *wl = hw->priv;
no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");
/* wait for packet queue and dma fifos to run empty */
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_wait_for_tx_completion(wl->wlc, drop);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
}
static const struct ieee80211_ops brcms_ops = {
@@ -706,16 +713,10 @@ static const struct ieee80211_ops brcms_ops = {
.config = brcms_ops_config,
.bss_info_changed = brcms_ops_bss_info_changed,
.configure_filter = brcms_ops_configure_filter,
- .set_tim = brcms_ops_set_tim,
.sw_scan_start = brcms_ops_sw_scan_start,
.sw_scan_complete = brcms_ops_sw_scan_complete,
- .set_tsf = brcms_ops_set_tsf,
- .get_stats = brcms_ops_get_stats,
- .sta_notify = brcms_ops_sta_notify,
.conf_tx = brcms_ops_conf_tx,
- .get_tsf = brcms_ops_get_tsf,
.sta_add = brcms_ops_sta_add,
- .sta_remove = brcms_ops_sta_remove,
.ampdu_action = brcms_ops_ampdu_action,
.rfkill_poll = brcms_ops_rfkill_poll,
.flush = brcms_ops_flush,
@@ -729,6 +730,284 @@ static int brcms_set_hint(struct brcms_info *wl, char *abbrev)
return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
}
+void brcms_dpc(unsigned long data)
+{
+ struct brcms_info *wl;
+
+ wl = (struct brcms_info *) data;
+
+ spin_lock_bh(&wl->lock);
+
+ /* call the common second level interrupt handler */
+ if (wl->pub->up) {
+ if (wl->resched) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&wl->isr_lock, flags);
+ brcms_c_intrsupd(wl->wlc);
+ spin_unlock_irqrestore(&wl->isr_lock, flags);
+ }
+
+ wl->resched = brcms_c_dpc(wl->wlc, true);
+ }
+
+ /* brcms_c_dpc() may bring the driver down */
+ if (!wl->pub->up)
+ goto done;
+
+ /* re-schedule dpc */
+ if (wl->resched)
+ tasklet_schedule(&wl->tasklet);
+ else
+ /* re-enable interrupts */
+ brcms_intrson(wl);
+
+ done:
+ spin_unlock_bh(&wl->lock);
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev)
+{
+ int status;
+ struct device *device = &pdev->dev;
+ char fw_name[100];
+ int i;
+
+ memset(&wl->fw, 0, sizeof(struct brcms_firmware));
+ for (i = 0; i < MAX_FW_IMAGES; i++) {
+ if (brcms_firmwares[i] == NULL)
+ break;
+ sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
+ UCODE_LOADER_API_VER);
+ status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
+ if (status) {
+ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+ KBUILD_MODNAME, fw_name);
+ return status;
+ }
+ sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
+ UCODE_LOADER_API_VER);
+ status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
+ if (status) {
+ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+ KBUILD_MODNAME, fw_name);
+ return status;
+ }
+ wl->fw.hdr_num_entries[i] =
+ wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
+ }
+ wl->fw.fw_cnt = i;
+ return brcms_ucode_data_init(wl, &wl->ucode);
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static void brcms_release_fw(struct brcms_info *wl)
+{
+ int i;
+ for (i = 0; i < MAX_FW_IMAGES; i++) {
+ release_firmware(wl->fw.fw_bin[i]);
+ release_firmware(wl->fw.fw_hdr[i]);
+ }
+}
+
+/**
+ * This function frees the WL per-device resources.
+ *
+ * This function frees resources owned by the WL device pointed to
+ * by the wl parameter.
+ *
+ * precondition: can both be called locked and unlocked
+ *
+ */
+static void brcms_free(struct brcms_info *wl)
+{
+ struct brcms_timer *t, *next;
+
+ /* free ucode data */
+ if (wl->fw.fw_cnt)
+ brcms_ucode_data_free(&wl->ucode);
+ if (wl->irq)
+ free_irq(wl->irq, wl);
+
+ /* kill dpc */
+ tasklet_kill(&wl->tasklet);
+
+ if (wl->pub)
+ brcms_c_module_unregister(wl->pub, "linux", wl);
+
+ /* free common resources */
+ if (wl->wlc) {
+ brcms_c_detach(wl->wlc);
+ wl->wlc = NULL;
+ wl->pub = NULL;
+ }
+
+ /* virtual interface deletion is deferred so we cannot spinwait */
+
+ /* wait for all pending callbacks to complete */
+ while (atomic_read(&wl->callbacks) > 0)
+ schedule();
+
+ /* free timers */
+ for (t = wl->timers; t; t = next) {
+ next = t->next;
+#ifdef BCMDBG
+ kfree(t->name);
+#endif
+ kfree(t);
+ }
+
+ /*
+ * unregister_netdev() calls get_stats() which may read chip
+ * registers so we cannot unmap the chip registers until
+ * after calling unregister_netdev() .
+ */
+ if (wl->regsva)
+ iounmap(wl->regsva);
+
+ wl->regsva = NULL;
+}
+
+/*
+* called from both kernel as from this kernel module.
+* precondition: perimeter lock is not acquired.
+*/
+static void brcms_remove(struct pci_dev *pdev)
+{
+ struct brcms_info *wl;
+ struct ieee80211_hw *hw;
+ int status;
+
+ hw = pci_get_drvdata(pdev);
+ wl = hw->priv;
+ if (!wl) {
+ pr_err("wl: brcms_remove: pci_get_drvdata failed\n");
+ return;
+ }
+
+ spin_lock_bh(&wl->lock);
+ status = brcms_c_chipmatch(pdev->vendor, pdev->device);
+ spin_unlock_bh(&wl->lock);
+ if (!status) {
+ wiphy_err(wl->wiphy, "wl: brcms_remove: chipmatch "
+ "failed\n");
+ return;
+ }
+ if (wl->wlc) {
+ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
+ wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+ ieee80211_unregister_hw(hw);
+ spin_lock_bh(&wl->lock);
+ brcms_down(wl);
+ spin_unlock_bh(&wl->lock);
+ }
+ pci_disable_device(pdev);
+
+ brcms_free(wl);
+
+ pci_set_drvdata(pdev, NULL);
+ ieee80211_free_hw(hw);
+}
+
+static irqreturn_t brcms_isr(int irq, void *dev_id)
+{
+ struct brcms_info *wl;
+ bool ours, wantdpc;
+
+ wl = (struct brcms_info *) dev_id;
+
+ spin_lock(&wl->isr_lock);
+
+ /* call common first level interrupt handler */
+ ours = brcms_c_isr(wl->wlc, &wantdpc);
+ if (ours) {
+ /* if more to do... */
+ if (wantdpc) {
+
+ /* ...and call the second level interrupt handler */
+ /* schedule dpc */
+ tasklet_schedule(&wl->tasklet);
+ }
+ }
+
+ spin_unlock(&wl->isr_lock);
+
+ return IRQ_RETVAL(ours);
+}
+
+/*
+ * is called in brcms_pci_probe() context, therefore no locking required.
+ */
+static int ieee_hw_rate_init(struct ieee80211_hw *hw)
+{
+ struct brcms_info *wl = hw->priv;
+ struct brcms_c_info *wlc = wl->wlc;
+ struct ieee80211_supported_band *band;
+ int has_5g = 0;
+ u16 phy_type;
+
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
+
+ phy_type = brcms_c_get_phy_type(wl->wlc, 0);
+ if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) {
+ band = &wlc->bandstate[BAND_2G_INDEX]->band;
+ *band = brcms_band_2GHz_nphy_template;
+ if (phy_type == PHY_TYPE_LCN) {
+ /* Single stream */
+ band->ht_cap.mcs.rx_mask[1] = 0;
+ band->ht_cap.mcs.rx_highest = cpu_to_le16(72);
+ }
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band;
+ } else {
+ return -EPERM;
+ }
+
+ /* Assume all bands use the same phy. True for 11n devices. */
+ if (wl->pub->_nbands > 1) {
+ has_5g++;
+ if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) {
+ band = &wlc->bandstate[BAND_5G_INDEX]->band;
+ *band = brcms_band_5GHz_nphy_template;
+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band;
+ } else {
+ return -EPERM;
+ }
+ }
+ return 0;
+}
+
+/*
+ * is called in brcms_pci_probe() context, therefore no locking required.
+ */
+static int ieee_hw_init(struct ieee80211_hw *hw)
+{
+ hw->flags = IEEE80211_HW_SIGNAL_DBM
+ /* | IEEE80211_HW_CONNECTION_MONITOR What is this? */
+ | IEEE80211_HW_REPORTS_TX_ACK_STATUS
+ | IEEE80211_HW_AMPDU_AGGREGATION;
+
+ hw->extra_tx_headroom = brcms_c_get_header_len();
+ hw->queues = N_TX_QUEUES;
+ hw->max_rates = 2; /* Primary rate and 1 fallback rate */
+
+ /* channel change time is dependent on chip and band */
+ hw->channel_change_time = 7 * 1000;
+ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+ hw->rate_control_algorithm = "minstrel_ht";
+
+ hw->sta_data_size = 0;
+ return ieee_hw_rate_init(hw);
+}
+
/**
* attach to the WL device.
*
@@ -744,21 +1023,19 @@ static int brcms_set_hint(struct brcms_info *wl, char *abbrev)
* is called in brcms_pci_probe() context, therefore no locking required.
*/
static struct brcms_info *brcms_attach(u16 vendor, u16 device,
- unsigned long regs,
- uint bustype, void *btparam, uint irq)
+ resource_size_t regs,
+ struct pci_dev *btparam, uint irq)
{
struct brcms_info *wl = NULL;
int unit, err;
- unsigned long base_addr;
struct ieee80211_hw *hw;
u8 perm[ETH_ALEN];
unit = n_adapters_found;
err = 0;
- if (unit < 0) {
+ if (unit < 0)
return NULL;
- }
/* allocate private info */
hw = pci_get_drvdata(btparam); /* btparam == pdev */
@@ -773,19 +1050,7 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
/* setup the bottom half handler */
tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl);
-
-
- base_addr = regs;
-
- if (bustype == PCI_BUS || bustype == RPC_BUS) {
- /* Do nothing */
- } else {
- bustype = PCI_BUS;
- BCMMSG(wl->wiphy, "force to PCI\n");
- }
- wl->bcm_bustype = bustype;
-
- wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ);
+ wl->regsva = ioremap_nocache(regs, PCI_BAR0_WINSZ);
if (wl->regsva == NULL) {
wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit);
goto fail;
@@ -794,17 +1059,17 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
spin_lock_init(&wl->isr_lock);
/* prepare ucode */
- if (brcms_request_fw(wl, (struct pci_dev *)btparam) < 0) {
+ if (brcms_request_fw(wl, btparam) < 0) {
wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
"%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
brcms_release_fw(wl);
- brcms_remove((struct pci_dev *)btparam);
+ brcms_remove(btparam);
return NULL;
}
/* common load-time initialization */
- wl->wlc = brcms_c_attach((void *)wl, vendor, device, unit, false,
- wl->regsva, wl->bcm_bustype, btparam, &err);
+ wl->wlc = brcms_c_attach(wl, vendor, device, unit, false,
+ wl->regsva, btparam, &err);
brcms_release_fw(wl);
if (!wl->wlc) {
wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
@@ -815,10 +1080,8 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
wl->pub->ieee_hw = hw;
- if (brcms_c_set_par(wl->wlc, IOV_MPC, 0) < 0) {
- wiphy_err(wl->wiphy, "wl%d: Error setting MPC variable to 0\n",
- unit);
- }
+ /* disable mpc */
+ brcms_c_set_radio_mpc(wl->wlc, false);
/* register our interrupt handler */
if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
@@ -828,7 +1091,7 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
wl->irq = irq;
/* register module */
- brcms_c_module_register(wl->pub, "linux", wl, wl_linux_watchdog, NULL);
+ brcms_c_module_register(wl->pub, "linux", wl, NULL);
if (ieee_hw_init(hw)) {
wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit,
@@ -842,19 +1105,17 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
SET_IEEE80211_PERM_ADDR(hw, perm);
err = ieee80211_register_hw(hw);
- if (err) {
+ if (err)
wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status"
"%d\n", __func__, err);
- }
if (wl->pub->srom_ccode[0])
err = brcms_set_hint(wl, wl->pub->srom_ccode);
else
err = brcms_set_hint(wl, "US");
- if (err) {
+ if (err)
wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n",
__func__, err);
- }
n_adapters_found++;
return wl;
@@ -866,241 +1127,6 @@ fail:
-#define CHAN2GHZ(channel, freqency, chflags) { \
- .band = IEEE80211_BAND_2GHZ, \
- .center_freq = (freqency), \
- .hw_value = (channel), \
- .flags = chflags, \
- .max_antenna_gain = 0, \
- .max_power = 19, \
-}
-
-static struct ieee80211_channel brcms_2ghz_chantable[] = {
- CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN2GHZ(5, 2432, 0),
- CHAN2GHZ(6, 2437, 0),
- CHAN2GHZ(7, 2442, 0),
- CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(12, 2467,
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(13, 2472,
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(14, 2484,
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
-};
-
-#define CHAN5GHZ(channel, chflags) { \
- .band = IEEE80211_BAND_5GHZ, \
- .center_freq = 5000 + 5*(channel), \
- .hw_value = (channel), \
- .flags = chflags, \
- .max_antenna_gain = 0, \
- .max_power = 21, \
-}
-
-static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = {
- /* UNII-1 */
- CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
- /* UNII-2 */
- CHAN5GHZ(52,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(56,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(60,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(64,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- /* MID */
- CHAN5GHZ(100,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(104,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(108,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(112,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(116,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(120,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(124,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(128,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(132,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(136,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(140,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
- IEEE80211_CHAN_NO_HT40MINUS),
- /* UNII-3 */
- CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
-};
-
-#define RATE(rate100m, _flags) { \
- .bitrate = (rate100m), \
- .flags = (_flags), \
- .hw_value = (rate100m / 5), \
-}
-
-/*
- * The rate table is used for both 2.4G and 5G rates. The
- * latter being a subset as it does not support CCK rates.
- */
-static struct ieee80211_rate legacy_ratetable[] = {
- RATE(10, 0),
- RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),
- RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),
- RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),
- RATE(60, 0),
- RATE(90, 0),
- RATE(120, 0),
- RATE(180, 0),
- RATE(240, 0),
- RATE(360, 0),
- RATE(480, 0),
- RATE(540, 0),
-};
-
-static struct ieee80211_supported_band brcms_band_2GHz_nphy = {
- .band = IEEE80211_BAND_2GHZ,
- .channels = brcms_2ghz_chantable,
- .n_channels = ARRAY_SIZE(brcms_2ghz_chantable),
- .bitrates = legacy_ratetable,
- .n_bitrates = ARRAY_SIZE(legacy_ratetable),
- .ht_cap = {
- /* from include/linux/ieee80211.h */
- .cap = IEEE80211_HT_CAP_GRN_FLD |
- IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
- .ht_supported = true,
- .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
- .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
- .mcs = {
- /* placeholders for now */
- .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
- .rx_highest = 500,
- .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
- }
-};
-
-static struct ieee80211_supported_band brcms_band_5GHz_nphy = {
- .band = IEEE80211_BAND_5GHZ,
- .channels = brcms_5ghz_nphy_chantable,
- .n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable),
- .bitrates = legacy_ratetable + BRCMS_LEGACY_5G_RATE_OFFSET,
- .n_bitrates = ARRAY_SIZE(legacy_ratetable) -
- BRCMS_LEGACY_5G_RATE_OFFSET,
- .ht_cap = {
- /* use IEEE80211_HT_CAP_* from include/linux/ieee80211.h */
- .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */
- .ht_supported = true,
- .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
- .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
- .mcs = {
- /* placeholders for now */
- .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
- .rx_highest = 500,
- .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
- }
-};
-
-/*
- * is called in brcms_pci_probe() context, therefore no locking required.
- */
-static int ieee_hw_rate_init(struct ieee80211_hw *hw)
-{
- struct brcms_info *wl = HW_TO_WL(hw);
- int has_5g;
- char phy_list[4];
-
- has_5g = 0;
-
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
- hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
-
- if (brcms_c_get(wl->wlc, BRCM_GET_PHYLIST, (int *)&phy_list) < 0)
- wiphy_err(hw->wiphy, "Phy list failed\n");
-
- if (phy_list[0] == 'n' || phy_list[0] == 'c') {
- if (phy_list[0] == 'c') {
- /* Single stream */
- brcms_band_2GHz_nphy.ht_cap.mcs.rx_mask[1] = 0;
- brcms_band_2GHz_nphy.ht_cap.mcs.rx_highest = 72;
- }
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &brcms_band_2GHz_nphy;
- } else {
- return -EPERM;
- }
-
- /* Assume all bands use the same phy. True for 11n devices. */
- if (NBANDS_PUB(wl->pub) > 1) {
- has_5g++;
- if (phy_list[0] == 'n' || phy_list[0] == 'c') {
- hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
- &brcms_band_5GHz_nphy;
- } else {
- return -EPERM;
- }
- }
- return 0;
-}
-
-/*
- * is called in brcms_pci_probe() context, therefore no locking required.
- */
-static int ieee_hw_init(struct ieee80211_hw *hw)
-{
- hw->flags = IEEE80211_HW_SIGNAL_DBM
- /* | IEEE80211_HW_CONNECTION_MONITOR What is this? */
- | IEEE80211_HW_REPORTS_TX_ACK_STATUS
- | IEEE80211_HW_AMPDU_AGGREGATION;
-
- hw->extra_tx_headroom = brcms_c_get_header_len();
- hw->queues = N_TX_QUEUES;
- hw->max_rates = 2; /* Primary rate and 1 fallback rate */
-
- hw->channel_change_time = 7 * 1000; /* channel change time is dependent on chip and band */
- hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
-
- hw->rate_control_algorithm = "minstrel_ht";
-
- hw->sta_data_size = sizeof(struct scb);
- return ieee_hw_rate_init(hw);
-}
-
/**
* determines if a device is a WL device, and if so, attaches it.
*
@@ -1154,7 +1180,7 @@ brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
memset(hw->priv, 0, sizeof(*wl));
wl = brcms_attach(pdev->vendor, pdev->device,
- pci_resource_start(pdev, 0), PCI_BUS, pdev,
+ pci_resource_start(pdev, 0), pdev,
pdev->irq);
if (!wl) {
@@ -1171,7 +1197,7 @@ static int brcms_suspend(struct pci_dev *pdev, pm_message_t state)
struct ieee80211_hw *hw;
hw = pci_get_drvdata(pdev);
- wl = HW_TO_WL(hw);
+ wl = hw->priv;
if (!wl) {
wiphy_err(wl->wiphy,
"brcms_suspend: pci_get_drvdata failed\n");
@@ -1179,9 +1205,9 @@ static int brcms_suspend(struct pci_dev *pdev, pm_message_t state)
}
/* only need to flag hw is down for proper resume */
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
wl->pub->hw_up = false;
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
pci_save_state(pdev);
pci_disable_device(pdev);
@@ -1196,7 +1222,7 @@ static int brcms_resume(struct pci_dev *pdev)
u32 val;
hw = pci_get_drvdata(pdev);
- wl = HW_TO_WL(hw);
+ wl = hw->priv;
if (!wl) {
wiphy_err(wl->wiphy,
"wl: brcms_resume: pci_get_drvdata failed\n");
@@ -1226,47 +1252,6 @@ static int brcms_resume(struct pci_dev *pdev)
return err;
}
-/*
-* called from both kernel as from this kernel module.
-* precondition: perimeter lock is not acquired.
-*/
-static void brcms_remove(struct pci_dev *pdev)
-{
- struct brcms_info *wl;
- struct ieee80211_hw *hw;
- int status;
-
- hw = pci_get_drvdata(pdev);
- wl = HW_TO_WL(hw);
- if (!wl) {
- pr_err("wl: brcms_remove: pci_get_drvdata failed\n");
- return;
- }
-
- LOCK(wl);
- status = brcms_c_chipmatch(pdev->vendor, pdev->device);
- UNLOCK(wl);
- if (!status) {
- wiphy_err(wl->wiphy, "wl: brcms_remove: chipmatch "
- "failed\n");
- return;
- }
- if (wl->wlc) {
- wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
- wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
- ieee80211_unregister_hw(hw);
- LOCK(wl);
- brcms_down(wl);
- UNLOCK(wl);
- }
- pci_disable_device(pdev);
-
- brcms_free(wl);
-
- pci_set_drvdata(pdev, NULL);
- ieee80211_free_hw(hw);
-}
-
static struct pci_driver brcms_pci_driver = {
.name = KBUILD_MODNAME,
.probe = brcms_pci_probe,
@@ -1290,8 +1275,6 @@ static int __init brcms_module_init(void)
#ifdef BCMDBG
if (msglevel != 0xdeadbeef)
brcm_msg_level = msglevel;
- if (phymsglevel != 0xdeadbeef)
- phyhal_msg_level = phymsglevel;
#endif /* BCMDBG */
error = pci_register_driver(&brcms_pci_driver);
@@ -1319,82 +1302,6 @@ static void __exit brcms_module_exit(void)
module_init(brcms_module_init);
module_exit(brcms_module_exit);
-/**
- * This function frees the WL per-device resources.
- *
- * This function frees resources owned by the WL device pointed to
- * by the wl parameter.
- *
- * precondition: can both be called locked and unlocked
- *
- */
-static void brcms_free(struct brcms_info *wl)
-{
- struct brcms_timer *t, *next;
-
- /* free ucode data */
- if (wl->fw.fw_cnt)
- brcms_ucode_data_free();
- if (wl->irq)
- free_irq(wl->irq, wl);
-
- /* kill dpc */
- tasklet_kill(&wl->tasklet);
-
- if (wl->pub) {
- brcms_c_module_unregister(wl->pub, "linux", wl);
- }
-
- /* free common resources */
- if (wl->wlc) {
- brcms_c_detach(wl->wlc);
- wl->wlc = NULL;
- wl->pub = NULL;
- }
-
- /* virtual interface deletion is deferred so we cannot spinwait */
-
- /* wait for all pending callbacks to complete */
- while (atomic_read(&wl->callbacks) > 0)
- schedule();
-
- /* free timers */
- for (t = wl->timers; t; t = next) {
- next = t->next;
-#ifdef BCMDBG
- kfree(t->name);
-#endif
- kfree(t);
- }
-
- /*
- * unregister_netdev() calls get_stats() which may read chip registers
- * so we cannot unmap the chip registers until after calling unregister_netdev() .
- */
- if (wl->regsva && wl->bcm_bustype != SDIO_BUS &&
- wl->bcm_bustype != JTAG_BUS) {
- iounmap((void *)wl->regsva);
- }
- wl->regsva = NULL;
-}
-
-/* flags the given rate in rateset as requested */
-static void brcms_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br)
-{
- u32 i;
-
- for (i = 0; i < rs->count; i++) {
- if (rate != (rs->rates[i] & 0x7f))
- continue;
-
- if (is_br)
- rs->rates[i] |= BRCMS_RATE_FLAG;
- else
- rs->rates[i] &= BRCMS_RATE_MASK;
- return;
- }
-}
-
/*
* precondition: perimeter lock has been acquired
*/
@@ -1409,7 +1316,7 @@ void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
*/
void brcms_init(struct brcms_info *wl)
{
- BCMMSG(WL_TO_HW(wl)->wiphy, "wl%d\n", wl->pub->unit);
+ BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
brcms_reset(wl);
brcms_c_init(wl->wlc);
@@ -1420,7 +1327,7 @@ void brcms_init(struct brcms_info *wl)
*/
uint brcms_reset(struct brcms_info *wl)
{
- BCMMSG(WL_TO_HW(wl)->wiphy, "wl%d\n", wl->pub->unit);
+ BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
brcms_c_reset(wl->wlc);
/* dpc will not be rescheduled */
@@ -1437,17 +1344,9 @@ void brcms_intrson(struct brcms_info *wl)
{
unsigned long flags;
- INT_LOCK(wl, flags);
+ spin_lock_irqsave(&wl->isr_lock, flags);
brcms_c_intrson(wl->wlc);
- INT_UNLOCK(wl, flags);
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-bool wl_alloc_dma_resources(struct brcms_info *wl, uint addrwidth)
-{
- return true;
+ spin_unlock_irqrestore(&wl->isr_lock, flags);
}
u32 brcms_intrsoff(struct brcms_info *wl)
@@ -1455,9 +1354,9 @@ u32 brcms_intrsoff(struct brcms_info *wl)
unsigned long flags;
u32 status;
- INT_LOCK(wl, flags);
+ spin_lock_irqsave(&wl->isr_lock, flags);
status = brcms_c_intrsoff(wl->wlc);
- INT_UNLOCK(wl, flags);
+ spin_unlock_irqrestore(&wl->isr_lock, flags);
return status;
}
@@ -1465,9 +1364,9 @@ void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask)
{
unsigned long flags;
- INT_LOCK(wl, flags);
+ spin_lock_irqsave(&wl->isr_lock, flags);
brcms_c_intrsrestore(wl->wlc, macintmask);
- INT_UNLOCK(wl, flags);
+ spin_unlock_irqrestore(&wl->isr_lock, flags);
}
/*
@@ -1497,110 +1396,42 @@ void brcms_down(struct brcms_info *wl)
callbacks = atomic_read(&wl->callbacks) - ret_val;
/* wait for down callbacks to complete */
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
/* For HIGH_only driver, it's important to actually schedule other work,
* not just spin wait since everything runs at schedule level
*/
SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
- LOCK(wl);
-}
-
-static irqreturn_t brcms_isr(int irq, void *dev_id)
-{
- struct brcms_info *wl;
- bool ours, wantdpc;
- unsigned long flags;
-
- wl = (struct brcms_info *) dev_id;
-
- ISR_LOCK(wl, flags);
-
- /* call common first level interrupt handler */
- ours = brcms_c_isr(wl->wlc, &wantdpc);
- if (ours) {
- /* if more to do... */
- if (wantdpc) {
-
- /* ...and call the second level interrupt handler */
- /* schedule dpc */
- tasklet_schedule(&wl->tasklet);
- }
- }
-
- ISR_UNLOCK(wl, flags);
-
- return IRQ_RETVAL(ours);
-}
-
-static void brcms_dpc(unsigned long data)
-{
- struct brcms_info *wl;
-
- wl = (struct brcms_info *) data;
-
- LOCK(wl);
-
- /* call the common second level interrupt handler */
- if (wl->pub->up) {
- if (wl->resched) {
- unsigned long flags;
-
- INT_LOCK(wl, flags);
- brcms_c_intrsupd(wl->wlc);
- INT_UNLOCK(wl, flags);
- }
-
- wl->resched = brcms_c_dpc(wl->wlc, true);
- }
-
- /* brcms_c_dpc() may bring the driver down */
- if (!wl->pub->up)
- goto done;
-
- /* re-schedule dpc */
- if (wl->resched)
- tasklet_schedule(&wl->tasklet);
- else {
- /* re-enable interrupts */
- brcms_intrson(wl);
- }
-
- done:
- UNLOCK(wl);
-}
-
-/*
- * is called by the kernel from software irq context
- */
-static void brcms_timer(unsigned long data)
-{
- _brcms_timer((struct brcms_timer *) data);
+ spin_lock_bh(&wl->lock);
}
/*
* precondition: perimeter lock is not acquired
*/
-static void _brcms_timer(struct brcms_timer *t)
+static void _brcms_timer(struct work_struct *work)
{
- LOCK(t->wl);
+ struct brcms_timer *t = container_of(work, struct brcms_timer,
+ dly_wrk.work);
+
+ spin_lock_bh(&t->wl->lock);
if (t->set) {
if (t->periodic) {
- t->timer.expires = jiffies + t->ms * HZ / 1000;
atomic_inc(&t->wl->callbacks);
- add_timer(&t->timer);
- t->set = true;
- } else
+ ieee80211_queue_delayed_work(t->wl->pub->ieee_hw,
+ &t->dly_wrk,
+ msecs_to_jiffies(t->ms));
+ } else {
t->set = false;
+ }
t->fn(t->arg);
}
atomic_dec(&t->wl->callbacks);
- UNLOCK(t->wl);
+ spin_unlock_bh(&t->wl->lock);
}
/*
@@ -1616,15 +1447,10 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
struct brcms_timer *t;
t = kzalloc(sizeof(struct brcms_timer), GFP_ATOMIC);
- if (!t) {
- wiphy_err(wl->wiphy, "wl%d: brcms_init_timer: out of memory\n",
- wl->pub->unit);
- return 0;
- }
+ if (!t)
+ return NULL;
- init_timer(&t->timer);
- t->timer.data = (unsigned long) t;
- t->timer.function = brcms_timer;
+ INIT_DELAYED_WORK(&t->dly_wrk, _brcms_timer);
t->wl = wl;
t->fn = fn;
t->arg = arg;
@@ -1640,27 +1466,28 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
return t;
}
-/* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate
+/*
+ * adds only the kernel timer since it's going to be more accurate
* as well as it's easier to make it periodic
*
* precondition: perimeter lock has been acquired
*/
-void brcms_add_timer(struct brcms_info *wl, struct brcms_timer *t, uint ms,
- int periodic)
+void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic)
{
+ struct ieee80211_hw *hw = t->wl->pub->ieee_hw;
+
#ifdef BCMDBG
- if (t->set) {
- wiphy_err(wl->wiphy, "%s: Already set. Name: %s, per %d\n",
+ if (t->set)
+ wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n",
__func__, t->name, periodic);
- }
#endif
t->ms = ms;
t->periodic = (bool) periodic;
t->set = true;
- t->timer.expires = jiffies + ms * HZ / 1000;
- atomic_inc(&wl->callbacks);
- add_timer(&t->timer);
+ atomic_inc(&t->wl->callbacks);
+
+ ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms));
}
/*
@@ -1668,14 +1495,14 @@ void brcms_add_timer(struct brcms_info *wl, struct brcms_timer *t, uint ms,
*
* precondition: perimeter lock has been acquired
*/
-bool brcms_del_timer(struct brcms_info *wl, struct brcms_timer *t)
+bool brcms_del_timer(struct brcms_timer *t)
{
if (t->set) {
t->set = false;
- if (!del_timer(&t->timer)) {
+ if (!cancel_delayed_work(&t->dly_wrk))
return false;
- }
- atomic_dec(&wl->callbacks);
+
+ atomic_dec(&t->wl->callbacks);
}
return true;
@@ -1684,12 +1511,13 @@ bool brcms_del_timer(struct brcms_info *wl, struct brcms_timer *t)
/*
* precondition: perimeter lock has been acquired
*/
-void brcms_free_timer(struct brcms_info *wl, struct brcms_timer *t)
+void brcms_free_timer(struct brcms_timer *t)
{
+ struct brcms_info *wl = t->wl;
struct brcms_timer *tmp;
/* delete the timer in case it is active */
- brcms_del_timer(wl, t);
+ brcms_del_timer(t);
if (wl->timers == t) {
wl->timers = wl->timers->next;
@@ -1717,27 +1545,6 @@ void brcms_free_timer(struct brcms_info *wl, struct brcms_timer *t)
}
/*
- * runs in software irq context
- *
- * precondition: perimeter lock is not acquired
- */
-static int wl_linux_watchdog(void *ctx)
-{
- return 0;
-}
-
-struct firmware_hdr {
- u32 offset;
- u32 len;
- u32 idx;
-};
-
-char *brcms_firmwares[MAX_FW_IMAGES] = {
- "brcm/bcm43xx",
- NULL
-};
-
-/*
* precondition: perimeter lock has been acquired
*/
int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)
@@ -1749,15 +1556,15 @@ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)
hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
for (entry = 0; entry < wl->fw.hdr_num_entries[i];
entry++, hdr++) {
- if (hdr->idx == idx) {
- pdata = wl->fw.fw_bin[i]->data + hdr->offset;
- *pbuf = kmalloc(hdr->len, GFP_ATOMIC);
- if (*pbuf == NULL) {
- wiphy_err(wl->wiphy, "fail to alloc %d"
- " bytes\n", hdr->len);
+ u32 len = le32_to_cpu(hdr->len);
+ if (le32_to_cpu(hdr->idx) == idx) {
+ pdata = wl->fw.fw_bin[i]->data +
+ le32_to_cpu(hdr->offset);
+ *pbuf = kmalloc(len, GFP_ATOMIC);
+ if (*pbuf == NULL)
goto fail;
- }
- memcpy(*pbuf, pdata, hdr->len);
+
+ memcpy(*pbuf, pdata, len);
return 0;
}
}
@@ -1773,7 +1580,7 @@ fail:
* Precondition: Since this function is called in brcms_pci_probe() context,
* no locking is required.
*/
-int brcms_ucode_init_uint(struct brcms_info *wl, u32 *data, u32 idx)
+int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)
{
int i, entry;
const u8 *pdata;
@@ -1782,14 +1589,15 @@ int brcms_ucode_init_uint(struct brcms_info *wl, u32 *data, u32 idx)
hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
for (entry = 0; entry < wl->fw.hdr_num_entries[i];
entry++, hdr++) {
- if (hdr->idx == idx) {
- pdata = wl->fw.fw_bin[i]->data + hdr->offset;
- if (hdr->len != 4) {
+ if (le32_to_cpu(hdr->idx) == idx) {
+ pdata = wl->fw.fw_bin[i]->data +
+ le32_to_cpu(hdr->offset);
+ if (le32_to_cpu(hdr->len) != 4) {
wiphy_err(wl->wiphy,
"ERROR: fw hdr len\n");
return -ENOMSG;
}
- *data = *((u32 *) pdata);
+ *n_bytes = le32_to_cpu(*((__le32 *) pdata));
return 0;
}
}
@@ -1799,44 +1607,6 @@ int brcms_ucode_init_uint(struct brcms_info *wl, u32 *data, u32 idx)
}
/*
- * Precondition: Since this function is called in brcms_pci_probe() context,
- * no locking is required.
- */
-static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev)
-{
- int status;
- struct device *device = &pdev->dev;
- char fw_name[100];
- int i;
-
- memset((void *)&wl->fw, 0, sizeof(struct brcms_firmware));
- for (i = 0; i < MAX_FW_IMAGES; i++) {
- if (brcms_firmwares[i] == NULL)
- break;
- sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
- UCODE_LOADER_API_VER);
- status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
- if (status) {
- wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
- KBUILD_MODNAME, fw_name);
- return status;
- }
- sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
- UCODE_LOADER_API_VER);
- status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
- if (status) {
- wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
- KBUILD_MODNAME, fw_name);
- return status;
- }
- wl->fw.hdr_num_entries[i] =
- wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
- }
- wl->fw.fw_cnt = i;
- return brcms_ucode_data_init(wl);
-}
-
-/*
* precondition: can both be called locked and unlocked
*/
void brcms_ucode_free_buf(void *p)
@@ -1845,20 +1615,6 @@ void brcms_ucode_free_buf(void *p)
}
/*
- * Precondition: Since this function is called in brcms_pci_probe() context,
- * no locking is required.
- */
-static void brcms_release_fw(struct brcms_info *wl)
-{
- int i;
- for (i = 0; i < MAX_FW_IMAGES; i++) {
- release_firmware(wl->fw.fw_bin[i]);
- release_firmware(wl->fw.fw_hdr[i]);
- }
-}
-
-
-/*
* checks validity of all firmware images loaded from user space
*
* Precondition: Since this function is called in brcms_pci_probe() context,
@@ -1895,7 +1651,8 @@ int brcms_check_firmwares(struct brcms_info *wl)
ucode_hdr = (struct firmware_hdr *)fw_hdr->data;
for (entry = 0; entry < wl->fw.hdr_num_entries[i] &&
!rc; entry++, ucode_hdr++) {
- if (ucode_hdr->offset + ucode_hdr->len >
+ if (le32_to_cpu(ucode_hdr->offset) +
+ le32_to_cpu(ucode_hdr->len) >
fw->size) {
wiphy_err(wl->wiphy,
"%s: conflicting bin/hdr\n",
@@ -1920,11 +1677,11 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl)
{
bool blocked = brcms_c_check_radio_disabled(wl->wlc);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
if (blocked)
wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy);
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
return blocked;
}
@@ -1933,7 +1690,7 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl)
*/
void brcms_msleep(struct brcms_info *wl, uint ms)
{
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
msleep(ms);
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
}
diff --git a/drivers/staging/brcm80211/brcmsmac/mac80211_if.h b/drivers/staging/brcm80211/brcmsmac/mac80211_if.h
index 3be8655c57e9..177f0e44e4b6 100644
--- a/drivers/staging/brcm80211/brcmsmac/mac80211_if.h
+++ b/drivers/staging/brcm80211/brcmsmac/mac80211_if.h
@@ -19,7 +19,9 @@
#include <linux/timer.h>
#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include "ucode_loader.h"
/*
* Starting index for 5G rates in the
* legacy rate table.
@@ -29,20 +31,15 @@
/* softmac ioctl definitions */
#define BRCMS_SET_SHORTSLOT_OVERRIDE 146
-
-/* BMAC Note: High-only driver is no longer working in softirq context as it needs to block and
- * sleep so perimeter lock has to be a semaphore instead of spinlock. This requires timers to be
- * submitted to workqueue instead of being on kernel timer
- */
struct brcms_timer {
- struct timer_list timer;
+ struct delayed_work dly_wrk;
struct brcms_info *wl;
- void (*fn) (void *);
- void *arg; /* argument to fn */
+ void (*fn) (void *); /* function called upon expiration */
+ void *arg; /* fixed argument provided to called function */
uint ms;
bool periodic;
- bool set;
- struct brcms_timer *next;
+ bool set; /* indicates if timer is active */
+ struct brcms_timer *next; /* for freeing on unload */
#ifdef BCMDBG
char *name; /* Description of the timer */
#endif
@@ -63,7 +60,7 @@ struct brcms_firmware {
struct brcms_info {
struct brcms_pub *pub; /* pointer to public wlc state */
- void *wlc; /* pointer to private common os-independent data */
+ struct brcms_c_info *wlc; /* pointer to private common data */
u32 magic;
int irq;
@@ -71,9 +68,8 @@ struct brcms_info {
spinlock_t lock; /* per-device perimeter lock */
spinlock_t isr_lock; /* per-device ISR synchronization lock */
- /* bus type and regsva for unmap in brcms_free() */
- uint bcm_bustype; /* bus type */
- void *regsva; /* opaque chip registers virtual address */
+ /* regsva for unmap in brcms_free() */
+ void __iomem *regsva; /* opaque chip registers virtual address */
/* timer related fields */
atomic_t callbacks; /* # outstanding callback functions */
@@ -81,11 +77,9 @@ struct brcms_info {
struct tasklet_struct tasklet; /* dpc tasklet */
bool resched; /* dpc needs to be and is rescheduled */
-#ifdef LINUXSTA_PS
- u32 pci_psstate[16]; /* pci ps-state save/restore */
-#endif
struct brcms_firmware fw;
struct wiphy *wiphy;
+ struct brcms_ucode ucode;
};
/* misc callbacks */
@@ -98,17 +92,17 @@ extern int brcms_up(struct brcms_info *wl);
extern void brcms_down(struct brcms_info *wl);
extern void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
bool state, int prio);
-extern bool wl_alloc_dma_resources(struct brcms_info *wl, uint dmaddrwidth);
extern bool brcms_rfkill_set_hw_state(struct brcms_info *wl);
/* timer functions */
extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
void (*fn) (void *arg), void *arg,
const char *name);
-extern void brcms_free_timer(struct brcms_info *wl, struct brcms_timer *timer);
-extern void brcms_add_timer(struct brcms_info *wl, struct brcms_timer *timer,
- uint ms, int periodic);
-extern bool brcms_del_timer(struct brcms_info *wl, struct brcms_timer *timer);
+extern void brcms_free_timer(struct brcms_timer *timer);
+extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic);
+extern bool brcms_del_timer(struct brcms_timer *timer);
extern void brcms_msleep(struct brcms_info *wl, uint ms);
+extern void brcms_dpc(unsigned long data);
+extern void brcms_timer(struct brcms_timer *t);
#endif /* _BRCM_MAC80211_IF_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/main.c b/drivers/staging/brcm80211/brcmsmac/main.c
index 96541630aada..510e9bb52287 100644
--- a/drivers/staging/brcm80211/brcmsmac/main.c
+++ b/drivers/staging/brcm80211/brcmsmac/main.c
@@ -15,32 +15,23 @@
*/
#include <linux/pci_ids.h>
+#include <linux/if_ether.h>
#include <net/mac80211.h>
-
#include <brcm_hw_ids.h>
#include <aiutils.h>
+#include <chipcommon.h>
#include "rate.h"
#include "scb.h"
#include "phy/phy_hal.h"
#include "channel.h"
-#include "bmac.h"
#include "antsel.h"
#include "stf.h"
#include "ampdu.h"
-#include "alloc.h"
#include "mac80211_if.h"
+#include "ucode_loader.h"
#include "main.h"
/*
- * WPA(2) definitions
- */
-#define RSN_CAP_4_REPLAY_CNTRS 2
-#define RSN_CAP_16_REPLAY_CNTRS 3
-
-#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS
-#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS
-
-/*
* Indication for txflowcontrol that all priority bits in
* TXQ_STOP_FOR_PRIOFC_MASK are to be considered.
*/
@@ -51,8 +42,10 @@
*/
#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1)
-#define TIMER_INTERVAL_WATCHDOG 1000 /* watchdog timer, in unit of ms */
-#define TIMER_INTERVAL_RADIOCHK 800 /* radio monitor timer, in unit of ms */
+/* watchdog timer, in unit of ms */
+#define TIMER_INTERVAL_WATCHDOG 1000
+/* radio monitor timer, in unit of ms */
+#define TIMER_INTERVAL_RADIOCHK 800
/* Max MPC timeout, in unit of watchdog */
#ifndef BRCMS_MPC_MAX_DELAYCNT
@@ -63,20 +56,19 @@
#define BRCMS_MPC_MIN_DELAYCNT 1
#define BRCMS_MPC_THRESHOLD 3 /* MPC count threshold level */
-#define BEACON_INTERVAL_DEFAULT 100 /* beacon interval, in unit of 1024TU */
-#define DTIM_INTERVAL_DEFAULT 3 /* DTIM interval, in unit of beacon interval */
+/* beacon interval, in unit of 1024TU */
+#define BEACON_INTERVAL_DEFAULT 100
+/* DTIM interval, in unit of beacon interval */
+#define DTIM_INTERVAL_DEFAULT 3
/* Scale down delays to accommodate QT slow speed */
-#define BEACON_INTERVAL_DEF_QT 20 /* beacon interval, in unit of 1024TU */
-#define DTIM_INTERVAL_DEF_QT 1 /* DTIM interval, in unit of beacon interval */
+/* beacon interval, in unit of 1024TU */
+#define BEACON_INTERVAL_DEF_QT 20
+/* DTIM interval, in unit of beacon interval */
+#define DTIM_INTERVAL_DEF_QT 1
#define TBTT_ALIGN_LEEWAY_US 100 /* min leeway before first TBTT in us */
-/* Software feature flag defines used by wlfeatureflag */
-#define WL_SWFL_NOHWRADIO 0x0004
-#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */
-#define WL_SWFL_WLBSSSORT 0x0010 /* Per-port supports sorting of BSS */
-
/* n-mode support capability */
/* 2x2 includes both 1x1 & 2x2 devices
* reserved #define 2 for future when we want to separate 1x1 & 2x2 and
@@ -160,62 +152,47 @@
#define AC_VI 2
#define AC_VO 3
-/*
- * driver maintains internal 'tick'(wlc->pub->now) which increments in 1s OS timer(soft
- * watchdog) it is not a wall clock and won't increment when driver is in "down" state
- * this low resolution driver tick can be used for maintenance tasks such as phy
- * calibration and scb update
- */
+#define BCN_TMPL_LEN 512 /* length of the BCN template area */
-/* To inform the ucode of the last mcast frame posted so that it can clear moredata bit */
-#define BCMCFID(wlc, fid) brcms_b_write_shm((wlc)->hw, M_BCMC_FID, (fid))
+/* brcms_bss_info flag bit values */
+#define BRCMS_BSS_HT 0x0020 /* BSS is HT (MIMO) capable */
-#define BRCMS_WAR16165(wlc) (wlc->pub->sih->bustype == PCI_BUS && \
- (!AP_ENAB(wlc->pub)) && (wlc->war16165))
+/* Flags used in brcms_c_txq_info.stopped */
+/* per prio flow control bits */
+#define TXQ_STOP_FOR_PRIOFC_MASK 0x000000FF
+/* stop txq enqueue for packet drain */
+#define TXQ_STOP_FOR_PKT_DRAIN 0x00000100
+/* stop txq enqueue for ampdu flow control */
+#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL 0x00000200
-/* debug/trace */
-uint brcm_msg_level =
-#if defined(BCMDBG)
- LOG_ERROR_VAL;
-#else
- 0;
-#endif /* BCMDBG */
+#define BRCMS_HWRXOFF 38 /* chip rx buffer offset */
/* Find basic rate for a given rate */
-#define BRCMS_BASIC_RATE(wlc, rspec) (IS_MCS(rspec) ? \
- (wlc)->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK].leg_ofdm] : \
- (wlc)->band->basic_rate[rspec & RSPEC_RATE_MASK])
+static u8 brcms_basic_rate(struct brcms_c_info *wlc, u32 rspec)
+{
+ if (is_mcs_rate(rspec))
+ return wlc->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK]
+ .leg_ofdm];
+ return wlc->band->basic_rate[rspec & RSPEC_RATE_MASK];
+}
-#define FRAMETYPE(r, mimoframe) (IS_MCS(r) ? mimoframe : (IS_CCK(r) ? FT_CCK : FT_OFDM))
+static u16 frametype(u32 rspec, u8 mimoframe)
+{
+ if (is_mcs_rate(rspec))
+ return mimoframe;
+ return is_cck_rate(rspec) ? FT_CCK : FT_OFDM;
+}
-#define RFDISABLE_DEFAULT 10000000 /* rfdisable delay timer 500 ms, runs of ALP clock */
+/* rfdisable delay timer 500 ms, runs of ALP clock */
+#define RFDISABLE_DEFAULT 10000000
#define BRCMS_TEMPSENSE_PERIOD 10 /* 10 second timeout */
-#define SCAN_IN_PROGRESS(x) 0
-
-#define EPI_VERSION_NUM 0x054b0b00
-
-#ifdef BCMDBG
-/* pointer to most recently allocated wl/wlc */
-static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL);
-#endif
-
-const u8 prio2fifo[NUMPRIO] = {
- TX_AC_BE_FIFO, /* 0 BE AC_BE Best Effort */
- TX_AC_BK_FIFO, /* 1 BK AC_BK Background */
- TX_AC_BK_FIFO, /* 2 -- AC_BK Background */
- TX_AC_BE_FIFO, /* 3 EE AC_BE Best Effort */
- TX_AC_VI_FIFO, /* 4 CL AC_VI Video */
- TX_AC_VI_FIFO, /* 5 VI AC_VI Video */
- TX_AC_VO_FIFO, /* 6 VO AC_VO Voice */
- TX_AC_VO_FIFO /* 7 NC AC_VO Voice */
-};
-
/* precedences numbers for wlc queues. These are twice as may levels as
* 802.1D priorities.
* Odd numbers are used for HI priority traffic at same precedence levels
- * These constants are used ONLY by wlc_prio2prec_map. Do not use them elsewhere.
+ * These constants are used ONLY by wlc_prio2prec_map. Do not use them
+ * elsewhere.
*/
#define _BRCMS_PREC_NONE 0 /* None = - */
#define _BRCMS_PREC_BK 2 /* BK - Background */
@@ -226,17 +203,182 @@ const u8 prio2fifo[NUMPRIO] = {
#define _BRCMS_PREC_VO 12 /* Vo - Voice */
#define _BRCMS_PREC_NC 14 /* NC - Network Control */
-#define MAXMACLIST 64 /* max # source MAC matches */
-#define BCN_TEMPLATE_COUNT 2
-
/* The BSS is generating beacons in HW */
#define BRCMS_BSSCFG_HW_BCN 0x20
-#define HWBCN_ENAB(cfg) (((cfg)->flags & BRCMS_BSSCFG_HW_BCN) != 0)
+#define SYNTHPU_DLY_APHY_US 3700 /* a phy synthpu_dly time in us */
+#define SYNTHPU_DLY_BPHY_US 1050 /* b/g phy synthpu_dly time in us */
+#define SYNTHPU_DLY_NPHY_US 2048 /* n phy REV3 synthpu_dly time in us */
+#define SYNTHPU_DLY_LPPHY_US 300 /* lpphy synthpu_dly time in us */
+
+#define SYNTHPU_DLY_PHY_US_QT 100 /* QT synthpu_dly time in us */
+
+#define ANTCNT 10 /* vanilla M_MAX_ANTCNT value */
+
+/* Per-AC retry limit register definitions; uses defs.h bitfield macros */
+#define EDCF_SHORT_S 0
+#define EDCF_SFB_S 4
+#define EDCF_LONG_S 8
+#define EDCF_LFB_S 12
+#define EDCF_SHORT_M BITFIELD_MASK(4)
+#define EDCF_SFB_M BITFIELD_MASK(4)
+#define EDCF_LONG_M BITFIELD_MASK(4)
+#define EDCF_LFB_M BITFIELD_MASK(4)
+
+#define RETRY_SHORT_DEF 7 /* Default Short retry Limit */
+#define RETRY_SHORT_MAX 255 /* Maximum Short retry Limit */
+#define RETRY_LONG_DEF 4 /* Default Long retry count */
+#define RETRY_SHORT_FB 3 /* Short count for fallback rate */
+#define RETRY_LONG_FB 2 /* Long count for fallback rate */
+
+#define APHY_CWMIN 15
+#define PHY_CWMAX 1023
+
+#define EDCF_AIFSN_MIN 1
+
+#define FRAGNUM_MASK 0xF
+
+#define APHY_SLOT_TIME 9
+#define BPHY_SLOT_TIME 20
+
+#define WL_SPURAVOID_OFF 0
+#define WL_SPURAVOID_ON1 1
+#define WL_SPURAVOID_ON2 2
+
+/* invalid core flags, use the saved coreflags */
+#define BRCMS_USE_COREFLAGS 0xffffffff
+
+/* values for PLCPHdr_override */
+#define BRCMS_PLCP_AUTO -1
+#define BRCMS_PLCP_SHORT 0
+#define BRCMS_PLCP_LONG 1
+
+/* values for g_protection_override and n_protection_override */
+#define BRCMS_PROTECTION_AUTO -1
+#define BRCMS_PROTECTION_OFF 0
+#define BRCMS_PROTECTION_ON 1
+#define BRCMS_PROTECTION_MMHDR_ONLY 2
+#define BRCMS_PROTECTION_CTS_ONLY 3
+
+/* values for g_protection_control and n_protection_control */
+#define BRCMS_PROTECTION_CTL_OFF 0
+#define BRCMS_PROTECTION_CTL_LOCAL 1
+#define BRCMS_PROTECTION_CTL_OVERLAP 2
+
+/* values for n_protection */
+#define BRCMS_N_PROTECTION_OFF 0
+#define BRCMS_N_PROTECTION_OPTIONAL 1
+#define BRCMS_N_PROTECTION_20IN40 2
+#define BRCMS_N_PROTECTION_MIXEDMODE 3
+
+/* values for band specific 40MHz capabilities */
+#define BRCMS_N_BW_20ALL 0
+#define BRCMS_N_BW_40ALL 1
+#define BRCMS_N_BW_20IN2G_40IN5G 2
+
+/* bitflags for SGI support (sgi_rx iovar) */
+#define BRCMS_N_SGI_20 0x01
+#define BRCMS_N_SGI_40 0x02
+
+/* defines used by the nrate iovar */
+/* MSC in use,indicates b0-6 holds an mcs */
+#define NRATE_MCS_INUSE 0x00000080
+/* rate/mcs value */
+#define NRATE_RATE_MASK 0x0000007f
+/* stf mode mask: siso, cdd, stbc, sdm */
+#define NRATE_STF_MASK 0x0000ff00
+/* stf mode shift */
+#define NRATE_STF_SHIFT 8
+/* bit indicates override both rate & mode */
+#define NRATE_OVERRIDE 0x80000000
+/* bit indicate to override mcs only */
+#define NRATE_OVERRIDE_MCS_ONLY 0x40000000
+#define NRATE_SGI_MASK 0x00800000 /* sgi mode */
+#define NRATE_SGI_SHIFT 23 /* sgi mode */
+#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */
+#define NRATE_LDPC_SHIFT 22 /* ldpc shift */
+
+#define NRATE_STF_SISO 0 /* stf mode SISO */
+#define NRATE_STF_CDD 1 /* stf mode CDD */
+#define NRATE_STF_STBC 2 /* stf mode STBC */
+#define NRATE_STF_SDM 3 /* stf mode SDM */
+
+#define MAX_DMA_SEGS 4
+
+/* Max # of entries in Tx FIFO based on 4kb page size */
+#define NTXD 256
+/* Max # of entries in Rx FIFO based on 4kb page size */
+#define NRXD 256
+
+/* try to keep this # rbufs posted to the chip */
+#define NRXBUFPOST 32
+
+/* data msg txq hiwat mark */
+#define BRCMS_DATAHIWAT 50
+
+/* bounded rx loops */
+#define RXBND 8 /* max # frames to process in brcms_c_recv() */
+#define TXSBND 8 /* max # tx status to process in wlc_txstatus() */
+
+/*
+ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
+ */
+#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1)
-#define MBSS_BCN_ENAB(cfg) 0
-#define MBSS_PRB_ENAB(cfg) 0
-#define SOFTBCN_ENAB(pub) (0)
+/* brcmu_format_flags() bit description structure */
+struct brcms_c_bit_desc {
+ u32 bit;
+ const char *name;
+};
+
+/*
+ * The following table lists the buffer memory allocated to xmt fifos in HW.
+ * the size is in units of 256bytes(one block), total size is HW dependent
+ * ucode has default fifo partition, sw can overwrite if necessary
+ *
+ * This is documented in twiki under the topic UcodeTxFifo. Please ensure
+ * the twiki is updated before making changes.
+ */
+
+/* Starting corerev for the fifo size table */
+#define XMTFIFOTBL_STARTREV 20
+
+struct d11init {
+ __le16 addr;
+ __le16 size;
+ __le32 value;
+};
+
+struct edcf_acparam {
+ u8 ACI;
+ u8 ECW;
+ u16 TXOP;
+} __packed;
+
+const u8 prio2fifo[NUMPRIO] = {
+ TX_AC_BE_FIFO, /* 0 BE AC_BE Best Effort */
+ TX_AC_BK_FIFO, /* 1 BK AC_BK Background */
+ TX_AC_BK_FIFO, /* 2 -- AC_BK Background */
+ TX_AC_BE_FIFO, /* 3 EE AC_BE Best Effort */
+ TX_AC_VI_FIFO, /* 4 CL AC_VI Video */
+ TX_AC_VI_FIFO, /* 5 VI AC_VI Video */
+ TX_AC_VO_FIFO, /* 6 VO AC_VO Voice */
+ TX_AC_VO_FIFO /* 7 NC AC_VO Voice */
+};
+
+/* debug/trace */
+uint brcm_msg_level =
+#if defined(BCMDBG)
+ LOG_ERROR_VAL;
+#else
+ 0;
+#endif /* BCMDBG */
+
+/* TX FIFO number to WME/802.1E Access Category */
+static const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE };
+
+/* WME/802.1E Access Category to TX FIFO number */
+static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 };
/* 802.1D Priority to precedence queue mapping */
const u8 wlc_prio2prec_map[] = {
@@ -250,26 +392,25 @@ const u8 wlc_prio2prec_map[] = {
_BRCMS_PREC_NC, /* 7 NC - Network Control */
};
-/* Check if a particular BSS config is AP or STA */
-#define BSSCFG_AP(cfg) (0)
-#define BSSCFG_STA(cfg) (1)
-#define BSSCFG_IBSS(cfg) (!(cfg)->BSS)
-
-/* As above for all non-NULL BSS configs */
-#define FOREACH_BSS(wlc, idx, cfg) \
- for (idx = 0; (int) idx < BRCMS_MAXBSSCFG; idx++) \
- if ((cfg = (wlc)->bsscfg[idx]))
-
-/* TX FIFO number to WME/802.1E Access Category */
-const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE };
-
-/* WME/802.1E Access Category to TX FIFO number */
-static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 };
-
-static bool in_send_q;
+static const u16 xmtfifo_sz[][NFIFO] = {
+ /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
+ {20, 192, 192, 21, 17, 5},
+ /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
+ {9, 58, 22, 14, 14, 5},
+ /* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */
+ {20, 192, 192, 21, 17, 5},
+ /* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */
+ {20, 192, 192, 21, 17, 5},
+ /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
+ {9, 58, 22, 14, 14, 5},
+};
-/* Shared memory location index for various AC params */
-#define wme_shmemacindex(ac) wme_ac2fifo[ac]
+static const u8 acbitmap2maxprio[] = {
+ PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK,
+ PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI,
+ PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO,
+ PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO
+};
#ifdef BCMDBG
static const char * const fifo_names[] = {
@@ -278,128 +419,2800 @@ static const char * const fifo_names[] = {
static const char fifo_names[6][0];
#endif
-static const u8 acbitmap2maxprio[] = {
- PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK,
- PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI,
- PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO,
- PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO
-};
+#ifdef BCMDBG
+/* pointer to most recently allocated wl/wlc */
+static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL);
+#endif
/* currently the best mechanism for determining SIFS is the band in use */
-#define SIFS(band) ((band)->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME : \
- BPHY_SIFS_TIME);
-
-/* local prototypes */
-static u16 brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc,
- struct ieee80211_hw *hw,
- struct sk_buff *p,
- struct scb *scb, uint frag,
- uint nfrags, uint queue,
- uint next_frag_len,
- struct wsec_key *key,
- ratespec_t rspec_override);
-static void brcms_c_bss_default_init(struct brcms_c_info *wlc);
-static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc);
-static ratespec_t mac80211_wlc_set_nrate(struct brcms_c_info *wlc,
- struct brcms_band *cur_band,
- u32 int_val);
-static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc);
-static void brcms_c_watchdog(void *arg);
-static void brcms_c_watchdog_by_timer(void *arg);
-static u16 brcms_c_rate_shm_offset(struct brcms_c_info *wlc, u8 rate);
-static int brcms_c_set_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs_arg);
-static u8 brcms_c_local_constraint_qdbm(struct brcms_c_info *wlc);
-
-/* send and receive */
-static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc);
-static void brcms_c_txq_free(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi);
-static void brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi,
- bool on, int prio);
-static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc);
-static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, ratespec_t rate,
- uint length, u8 *plcp);
-static void brcms_c_compute_ofdm_plcp(ratespec_t rate, uint length, u8 *plcp);
-static void brcms_c_compute_mimo_plcp(ratespec_t rate, uint length, u8 *plcp);
-static u16 brcms_c_compute_frame_dur(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type, uint next_frag_len);
-static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc,
- struct brcms_d11rxhdr *rxh);
-static void brcms_c_recvctl(struct brcms_c_info *wlc,
- struct d11rxhdr *rxh, struct sk_buff *p);
-static uint brcms_c_calc_frame_len(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type, uint dur);
-static uint brcms_c_calc_ack_time(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type);
-static uint brcms_c_calc_cts_time(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type);
-/* interrupt, up/down, band */
-static void brcms_c_setband(struct brcms_c_info *wlc, uint bandunit);
-static chanspec_t brcms_c_init_chanspec(struct brcms_c_info *wlc);
-static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
- chanspec_t chanspec);
-static void brcms_c_bsinit(struct brcms_c_info *wlc);
-static int brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle,
- bool isOFDM, bool writeToShm);
-static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc);
-static bool brcms_c_radio_monitor_start(struct brcms_c_info *wlc);
-static void brcms_c_radio_timer(void *arg);
-static void brcms_c_radio_enable(struct brcms_c_info *wlc);
-static void brcms_c_radio_upd(struct brcms_c_info *wlc);
-
-/* scan, association, BSS */
-static uint brcms_c_calc_ba_time(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type);
-static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap);
-static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val);
-static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val);
-static void brcms_c_war16165(struct brcms_c_info *wlc, bool tx);
-
-static void brcms_c_wme_retries_write(struct brcms_c_info *wlc);
-static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc);
-static uint brcms_c_attach_module(struct brcms_c_info *wlc);
-static void brcms_c_detach_module(struct brcms_c_info *wlc);
-static void brcms_c_timers_deinit(struct brcms_c_info *wlc);
-static void brcms_c_down_led_upd(struct brcms_c_info *wlc);
-static uint brcms_c_down_del_timer(struct brcms_c_info *wlc);
-static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc);
-static int _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
- struct brcms_c_if *wlcif);
-
-/* conditions under which the PM bit should be set in outgoing frames and STAY_AWAKE is meaningful
+static u16 get_sifs(struct brcms_band *band)
+{
+ return band->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME :
+ BPHY_SIFS_TIME;
+}
+
+/*
+ * Detect Card removed.
+ * Even checking an sbconfig register read will not false trigger when the core
+ * is in reset it breaks CF address mechanism. Accessing gphy phyversion will
+ * cause SB error if aphy is in reset on 4306B0-DB. Need a simple accessible
+ * reg with fixed 0/1 pattern (some platforms return all 0).
+ * If clocks are present, call the sb routine which will figure out if the
+ * device is removed.
*/
-bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
+static bool brcms_deviceremoved(struct brcms_c_info *wlc)
+{
+ if (!wlc->hw->clk)
+ return ai_deviceremoved(wlc->hw->sih);
+ return (R_REG(&wlc->hw->regs->maccontrol) &
+ (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN;
+}
+
+/* sum the individual fifo tx pending packet counts */
+static s16 brcms_txpktpendtot(struct brcms_c_info *wlc)
+{
+ return wlc->core->txpktpend[0] + wlc->core->txpktpend[1] +
+ wlc->core->txpktpend[2] + wlc->core->txpktpend[3];
+}
+
+static bool brcms_is_mband_unlocked(struct brcms_c_info *wlc)
+{
+ return wlc->pub->_nbands > 1 && !wlc->bandlocked;
+}
+
+static int brcms_chspec_bw(u16 chanspec)
+{
+ if (CHSPEC_IS40(chanspec))
+ return BRCMS_40_MHZ;
+ if (CHSPEC_IS20(chanspec))
+ return BRCMS_20_MHZ;
+
+ return BRCMS_10_MHZ;
+}
+
+/*
+ * return true if Minimum Power Consumption should
+ * be entered, false otherwise
+ */
+static bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc)
+{
+ return false;
+}
+
+static bool brcms_c_ismpc(struct brcms_c_info *wlc)
+{
+ return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc));
+}
+
+static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg)
+{
+ if (cfg == NULL)
+ return;
+
+ kfree(cfg->current_bss);
+ kfree(cfg);
+}
+
+static void brcms_c_detach_mfree(struct brcms_c_info *wlc)
+{
+ if (wlc == NULL)
+ return;
+
+ brcms_c_bsscfg_mfree(wlc->bsscfg);
+ kfree(wlc->pub);
+ kfree(wlc->modulecb);
+ kfree(wlc->default_bss);
+ kfree(wlc->protection);
+ kfree(wlc->stf);
+ kfree(wlc->bandstate[0]);
+ kfree(wlc->corestate->macstat_snapshot);
+ kfree(wlc->corestate);
+ kfree(wlc->hw->bandstate[0]);
+ kfree(wlc->hw);
+
+ /* free the wlc */
+ kfree(wlc);
+ wlc = NULL;
+}
+
+static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit)
{
- int idx;
struct brcms_bss_cfg *cfg;
- /* disallow PS when one of the following global conditions meets */
- if (!wlc->pub->associated)
+ cfg = kzalloc(sizeof(struct brcms_bss_cfg), GFP_ATOMIC);
+ if (cfg == NULL)
+ goto fail;
+
+ cfg->current_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
+ if (cfg->current_bss == NULL)
+ goto fail;
+
+ return cfg;
+
+ fail:
+ brcms_c_bsscfg_mfree(cfg);
+ return NULL;
+}
+
+static struct brcms_c_info *
+brcms_c_attach_malloc(uint unit, uint *err, uint devid)
+{
+ struct brcms_c_info *wlc;
+
+ wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC);
+ if (wlc == NULL) {
+ *err = 1002;
+ goto fail;
+ }
+
+ /* allocate struct brcms_c_pub state structure */
+ wlc->pub = kzalloc(sizeof(struct brcms_pub), GFP_ATOMIC);
+ if (wlc->pub == NULL) {
+ *err = 1003;
+ goto fail;
+ }
+ wlc->pub->wlc = wlc;
+
+ /* allocate struct brcms_hardware state structure */
+
+ wlc->hw = kzalloc(sizeof(struct brcms_hardware), GFP_ATOMIC);
+ if (wlc->hw == NULL) {
+ *err = 1005;
+ goto fail;
+ }
+ wlc->hw->wlc = wlc;
+
+ wlc->hw->bandstate[0] =
+ kzalloc(sizeof(struct brcms_hw_band) * MAXBANDS, GFP_ATOMIC);
+ if (wlc->hw->bandstate[0] == NULL) {
+ *err = 1006;
+ goto fail;
+ } else {
+ int i;
+
+ for (i = 1; i < MAXBANDS; i++)
+ wlc->hw->bandstate[i] = (struct brcms_hw_band *)
+ ((unsigned long)wlc->hw->bandstate[0] +
+ (sizeof(struct brcms_hw_band) * i));
+ }
+
+ wlc->modulecb =
+ kzalloc(sizeof(struct modulecb) * BRCMS_MAXMODULES, GFP_ATOMIC);
+ if (wlc->modulecb == NULL) {
+ *err = 1009;
+ goto fail;
+ }
+
+ wlc->default_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
+ if (wlc->default_bss == NULL) {
+ *err = 1010;
+ goto fail;
+ }
+
+ wlc->bsscfg = brcms_c_bsscfg_malloc(unit);
+ if (wlc->bsscfg == NULL) {
+ *err = 1011;
+ goto fail;
+ }
+
+ wlc->protection = kzalloc(sizeof(struct brcms_protection),
+ GFP_ATOMIC);
+ if (wlc->protection == NULL) {
+ *err = 1016;
+ goto fail;
+ }
+
+ wlc->stf = kzalloc(sizeof(struct brcms_stf), GFP_ATOMIC);
+ if (wlc->stf == NULL) {
+ *err = 1017;
+ goto fail;
+ }
+
+ wlc->bandstate[0] =
+ kzalloc(sizeof(struct brcms_band)*MAXBANDS, GFP_ATOMIC);
+ if (wlc->bandstate[0] == NULL) {
+ *err = 1025;
+ goto fail;
+ } else {
+ int i;
+
+ for (i = 1; i < MAXBANDS; i++)
+ wlc->bandstate[i] = (struct brcms_band *)
+ ((unsigned long)wlc->bandstate[0]
+ + (sizeof(struct brcms_band)*i));
+ }
+
+ wlc->corestate = kzalloc(sizeof(struct brcms_core), GFP_ATOMIC);
+ if (wlc->corestate == NULL) {
+ *err = 1026;
+ goto fail;
+ }
+
+ wlc->corestate->macstat_snapshot =
+ kzalloc(sizeof(struct macstat), GFP_ATOMIC);
+ if (wlc->corestate->macstat_snapshot == NULL) {
+ *err = 1027;
+ goto fail;
+ }
+
+ return wlc;
+
+ fail:
+ brcms_c_detach_mfree(wlc);
+ return NULL;
+}
+
+/*
+ * Update the slot timing for standard 11b/g (20us slots)
+ * or shortslot 11g (9us slots)
+ * The PSM needs to be suspended for this call.
+ */
+static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
+ bool shortslot)
+{
+ struct d11regs __iomem *regs;
+
+ regs = wlc_hw->regs;
+
+ if (shortslot) {
+ /* 11g short slot: 11a timing */
+ W_REG(&regs->ifs_slot, 0x0207); /* APHY_SLOT_TIME */
+ brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
+ } else {
+ /* 11g long slot: 11b timing */
+ W_REG(&regs->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */
+ brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
+ }
+}
+
+/*
+ * calculate frame duration of a given rate and length, return
+ * time in usec unit
+ */
+uint
+brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
+ u8 preamble_type, uint mac_len)
+{
+ uint nsyms, dur = 0, Ndps, kNdps;
+ uint rate = rspec2rate(ratespec);
+
+ if (rate == 0) {
+ wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n",
+ wlc->pub->unit);
+ rate = BRCM_RATE_1M;
+ }
+
+ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n",
+ wlc->pub->unit, ratespec, preamble_type, mac_len);
+
+ if (is_mcs_rate(ratespec)) {
+ uint mcs = ratespec & RSPEC_RATE_MASK;
+ int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec);
+
+ dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
+ if (preamble_type == BRCMS_MM_PREAMBLE)
+ dur += PREN_MM_EXT;
+ /* 1000Ndbps = kbps * 4 */
+ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
+ rspec_issgi(ratespec)) * 4;
+
+ if (rspec_stc(ratespec) == 0)
+ nsyms =
+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+ APHY_TAIL_NBITS) * 1000, kNdps);
+ else
+ /* STBC needs to have even number of symbols */
+ nsyms =
+ 2 *
+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+ APHY_TAIL_NBITS) * 1000, 2 * kNdps);
+
+ dur += APHY_SYMBOL_TIME * nsyms;
+ if (wlc->band->bandtype == BRCM_BAND_2G)
+ dur += DOT11_OFDM_SIGNAL_EXTENSION;
+ } else if (is_ofdm_rate(rate)) {
+ dur = APHY_PREAMBLE_TIME;
+ dur += APHY_SIGNAL_TIME;
+ /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
+ Ndps = rate * 2;
+ /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
+ nsyms =
+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
+ Ndps);
+ dur += APHY_SYMBOL_TIME * nsyms;
+ if (wlc->band->bandtype == BRCM_BAND_2G)
+ dur += DOT11_OFDM_SIGNAL_EXTENSION;
+ } else {
+ /*
+ * calc # bits * 2 so factor of 2 in rate (1/2 mbps)
+ * will divide out
+ */
+ mac_len = mac_len * 8 * 2;
+ /* calc ceiling of bits/rate = microseconds of air time */
+ dur = (mac_len + rate - 1) / rate;
+ if (preamble_type & BRCMS_SHORT_PREAMBLE)
+ dur += BPHY_PLCP_SHORT_TIME;
+ else
+ dur += BPHY_PLCP_TIME;
+ }
+ return dur;
+}
+
+static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
+ const struct d11init *inits)
+{
+ int i;
+ u8 __iomem *base;
+ u8 __iomem *addr;
+ u16 size;
+ u32 value;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ base = (u8 __iomem *)wlc_hw->regs;
+
+ for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) {
+ size = le16_to_cpu(inits[i].size);
+ addr = base + le16_to_cpu(inits[i].addr);
+ value = le32_to_cpu(inits[i].value);
+ if (size == 2)
+ W_REG((u16 __iomem *)addr, value);
+ else if (size == 4)
+ W_REG((u32 __iomem *)addr, value);
+ else
+ break;
+ }
+}
+
+static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs)
+{
+ u8 idx;
+ u16 addr[] = {
+ M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
+ M_HOST_FLAGS5
+ };
+
+ for (idx = 0; idx < MHFMAX; idx++)
+ brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]);
+}
+
+static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
+{
+ struct wiphy *wiphy = wlc_hw->wlc->wiphy;
+ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
+
+ /* init microcode host flags */
+ brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs);
+
+ /* do band-specific ucode IHR, SHM, and SCR inits */
+ if (D11REV_IS(wlc_hw->corerev, 23)) {
+ if (BRCMS_ISNPHY(wlc_hw->band))
+ brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16);
+ else
+ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
+ " %d\n", __func__, wlc_hw->unit,
+ wlc_hw->corerev);
+ } else {
+ if (D11REV_IS(wlc_hw->corerev, 24)) {
+ if (BRCMS_ISLCNPHY(wlc_hw->band))
+ brcms_c_write_inits(wlc_hw,
+ ucode->d11lcn0bsinitvals24);
+ else
+ wiphy_err(wiphy, "%s: wl%d: unsupported phy in"
+ " core rev %d\n", __func__,
+ wlc_hw->unit, wlc_hw->corerev);
+ } else {
+ wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
+ __func__, wlc_hw->unit, wlc_hw->corerev);
+ }
+ }
+}
+
+static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
+{
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk);
+
+ wlc_hw->phyclk = clk;
+
+ if (OFF == clk) { /* clear gmode bit, put phy into reset */
+
+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE),
+ (SICF_PRST | SICF_FGC));
+ udelay(1);
+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST);
+ udelay(1);
+
+ } else { /* take phy out of reset */
+
+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC);
+ udelay(1);
+ ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0);
+ udelay(1);
+
+ }
+}
+
+/* low-level band switch utility routine */
+static void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit)
+{
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
+ bandunit);
+
+ wlc_hw->band = wlc_hw->bandstate[bandunit];
+
+ /*
+ * BMAC_NOTE:
+ * until we eliminate need for wlc->band refs in low level code
+ */
+ wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
+
+ /* set gmode core flag */
+ if (wlc_hw->sbclk && !wlc_hw->noreset)
+ ai_core_cflags(wlc_hw->sih, SICF_GMODE,
+ ((bandunit == 0) ? SICF_GMODE : 0));
+}
+
+/* switch to new band but leave it inactive */
+static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ u32 macintmask;
+
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
+
+ /* disable interrupts */
+ macintmask = brcms_intrsoff(wlc->wl);
+
+ /* radio off */
+ wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
+
+ brcms_b_core_phy_clk(wlc_hw, OFF);
+
+ brcms_c_setxband(wlc_hw, bandunit);
+
+ return macintmask;
+}
+
+/* process an individual struct tx_status */
+static bool
+brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
+{
+ struct sk_buff *p;
+ uint queue;
+ struct d11txh *txh;
+ struct scb *scb = NULL;
+ bool free_pdu;
+ int tx_rts, tx_frame_count, tx_rts_count;
+ uint totlen, supr_status;
+ bool lastframe;
+ struct ieee80211_hdr *h;
+ u16 mcl;
+ struct ieee80211_tx_info *tx_info;
+ struct ieee80211_tx_rate *txrate;
+ int i;
+
+ /* discard intermediate indications for ucode with one legitimate case:
+ * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange,
+ * but the subsequent tx of DATA failed. so it will start rts/cts
+ * from the beginning (resetting the rts transmission count)
+ */
+ if (!(txs->status & TX_STATUS_AMPDU)
+ && (txs->status & TX_STATUS_INTERMEDIATE)) {
+ wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
+ __func__);
return false;
+ }
- /* disallow PS when one of these meets when not scanning */
- if (AP_ACTIVE(wlc) || wlc->monitor)
+ queue = txs->frameid & TXFID_QUEUE_MASK;
+ if (queue >= NFIFO) {
+ p = NULL;
+ goto fatal;
+ }
+
+ p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
+ if (p == NULL)
+ goto fatal;
+
+ txh = (struct d11txh *) (p->data);
+ mcl = le16_to_cpu(txh->MacTxControlLow);
+
+ if (txs->phyerr) {
+ if (brcm_msg_level & LOG_ERROR_VAL) {
+ wiphy_err(wlc->wiphy, "phyerr 0x%x, rate 0x%x\n",
+ txs->phyerr, txh->MainRates);
+ brcms_c_print_txdesc(txh);
+ }
+ brcms_c_print_txstatus(txs);
+ }
+
+ if (txs->frameid != le16_to_cpu(txh->TxFrameID))
+ goto fatal;
+ tx_info = IEEE80211_SKB_CB(p);
+ h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
+
+ if (tx_info->control.sta)
+ scb = &wlc->pri_scb;
+
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+ brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
return false;
+ }
+
+ supr_status = txs->status & TX_STATUS_SUPR_MASK;
+ if (supr_status == TX_STATUS_SUPR_BADCH)
+ BCMMSG(wlc->wiphy,
+ "%s: Pkt tx suppressed, possibly channel %d\n",
+ __func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec));
+
+ tx_rts = le16_to_cpu(txh->MacTxControlLow) & TXC_SENDRTS;
+ tx_frame_count =
+ (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT;
+ tx_rts_count =
+ (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT;
+
+ lastframe = !ieee80211_has_morefrags(h->frame_control);
+
+ if (!lastframe) {
+ wiphy_err(wlc->wiphy, "Not last frame!\n");
+ } else {
+ /*
+ * Set information to be consumed by Minstrel ht.
+ *
+ * The "fallback limit" is the number of tx attempts a given
+ * MPDU is sent at the "primary" rate. Tx attempts beyond that
+ * limit are sent at the "secondary" rate.
+ * A 'short frame' does not exceed RTS treshold.
+ */
+ u16 sfbl, /* Short Frame Rate Fallback Limit */
+ lfbl, /* Long Frame Rate Fallback Limit */
+ fbl;
- for (idx = 0; idx < BRCMS_MAXBSSCFG; idx++) {
- cfg = wlc->bsscfg[idx];
- if (cfg && BSSCFG_STA(cfg) && cfg->associated) {
+ if (queue < AC_COUNT) {
+ sfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]],
+ EDCF_SFB);
+ lfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]],
+ EDCF_LFB);
+ } else {
+ sfbl = wlc->SFBL;
+ lfbl = wlc->LFBL;
+ }
+
+ txrate = tx_info->status.rates;
+ if (txrate[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+ fbl = lfbl;
+ else
+ fbl = sfbl;
+
+ ieee80211_tx_info_clear_status(tx_info);
+
+ if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) {
+ /*
+ * rate selection requested a fallback rate
+ * and we used it
+ */
+ txrate[0].count = fbl;
+ txrate[1].count = tx_frame_count - fbl;
+ } else {
+ /*
+ * rate selection did not request fallback rate, or
+ * we didn't need it
+ */
+ txrate[0].count = tx_frame_count;
/*
- * disallow PS when one of the following
- * bsscfg specific conditions meets
+ * rc80211_minstrel.c:minstrel_tx_status() expects
+ * unused rates to be marked with idx = -1
*/
- if (!cfg->BSS || !BRCMS_PORTOPEN(cfg))
- return false;
+ txrate[1].idx = -1;
+ txrate[1].count = 0;
+ }
+
+ /* clear the rest of the rates */
+ for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
+ txrate[i].idx = -1;
+ txrate[i].count = 0;
+ }
+
+ if (txs->status & TX_STATUS_ACK_RCV)
+ tx_info->flags |= IEEE80211_TX_STAT_ACK;
+ }
- if (!cfg->dtim_programmed)
- return false;
+ totlen = brcmu_pkttotlen(p);
+ free_pdu = true;
+
+ brcms_c_txfifo_complete(wlc, queue, 1);
+
+ if (lastframe) {
+ p->next = NULL;
+ p->prev = NULL;
+ /* remove PLCP & Broadcom tx descriptor header */
+ skb_pull(p, D11_PHY_HDR_LEN);
+ skb_pull(p, D11_TXH_LEN);
+ ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p);
+ } else {
+ wiphy_err(wlc->wiphy, "%s: Not last frame => not calling "
+ "tx_status\n", __func__);
+ }
+
+ return false;
+
+ fatal:
+ if (p)
+ brcmu_pkt_buf_free_skb(p);
+
+ return true;
+
+}
+
+/* process tx completion events in BMAC
+ * Return true if more tx status need to be processed. false otherwise.
+ */
+static bool
+brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
+{
+ bool morepending = false;
+ struct brcms_c_info *wlc = wlc_hw->wlc;
+ struct d11regs __iomem *regs;
+ struct tx_status txstatus, *txs;
+ u32 s1, s2;
+ uint n = 0;
+ /*
+ * Param 'max_tx_num' indicates max. # tx status to process before
+ * break out.
+ */
+ uint max_tx_num = bound ? TXSBND : -1;
+
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ txs = &txstatus;
+ regs = wlc_hw->regs;
+ *fatal = false;
+ while (!(*fatal)
+ && (s1 = R_REG(&regs->frmtxstatus)) & TXS_V) {
+
+ if (s1 == 0xffffffff) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n",
+ wlc_hw->unit, __func__);
+ return morepending;
}
+
+ s2 = R_REG(&regs->frmtxstatus2);
+
+ txs->status = s1 & TXS_STATUS_MASK;
+ txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
+ txs->sequence = s2 & TXS_SEQ_MASK;
+ txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT;
+ txs->lasttxtime = 0;
+
+ *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs);
+
+ /* !give others some time to run! */
+ if (++n >= max_tx_num)
+ break;
}
+ if (*fatal)
+ return 0;
+
+ if (n >= max_tx_num)
+ morepending = true;
+
+ if (!pktq_empty(&wlc->pkt_queue->q))
+ brcms_c_send_q(wlc);
+
+ return morepending;
+}
+
+static void brcms_c_tbtt(struct brcms_c_info *wlc)
+{
+ if (!wlc->bsscfg->BSS)
+ /*
+ * DirFrmQ is now valid...defer setting until end
+ * of ATIM window
+ */
+ wlc->qvalid |= MCMD_DIRFRMQVAL;
+}
+
+/* set initial host flags value */
+static void
+brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+
+ memset(mhfs, 0, MHFMAX * sizeof(u16));
+
+ mhfs[MHF2] |= mhf2_init;
+
+ /* prohibit use of slowclock on multifunction boards */
+ if (wlc_hw->boardflags & BFL_NOPLLDOWN)
+ mhfs[MHF1] |= MHF1_FORCEFASTCLK;
+
+ if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) {
+ mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR;
+ mhfs[MHF1] |= MHF1_IQSWAP_WAR;
+ }
+}
+
+static struct dma64regs __iomem *
+dmareg(struct brcms_hardware *hw, uint direction, uint fifonum)
+{
+ if (direction == DMA_TX)
+ return &(hw->regs->fifo64regs[fifonum].dmaxmt);
+ return &(hw->regs->fifo64regs[fifonum].dmarcv);
+}
+
+static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
+{
+ uint i;
+ char name[8];
+ /*
+ * ucode host flag 2 needed for pio mode, independent of band and fifo
+ */
+ u16 pio_mhf2 = 0;
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ uint unit = wlc_hw->unit;
+ struct wiphy *wiphy = wlc->wiphy;
+
+ /* name and offsets for dma_attach */
+ snprintf(name, sizeof(name), "wl%d", unit);
+
+ if (wlc_hw->di[0] == NULL) { /* Init FIFOs */
+ int dma_attach_err = 0;
+
+ /*
+ * FIFO 0
+ * TX: TX_AC_BK_FIFO (TX AC Background data packets)
+ * RX: RX_FIFO (RX data packets)
+ */
+ wlc_hw->di[0] = dma_attach(name, wlc_hw->sih,
+ (wme ? dmareg(wlc_hw, DMA_TX, 0) :
+ NULL), dmareg(wlc_hw, DMA_RX, 0),
+ (wme ? NTXD : 0), NRXD,
+ RXBUFSZ, -1, NRXBUFPOST,
+ BRCMS_HWRXOFF, &brcm_msg_level);
+ dma_attach_err |= (NULL == wlc_hw->di[0]);
+
+ /*
+ * FIFO 1
+ * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets)
+ * (legacy) TX_DATA_FIFO (TX data packets)
+ * RX: UNUSED
+ */
+ wlc_hw->di[1] = dma_attach(name, wlc_hw->sih,
+ dmareg(wlc_hw, DMA_TX, 1), NULL,
+ NTXD, 0, 0, -1, 0, 0,
+ &brcm_msg_level);
+ dma_attach_err |= (NULL == wlc_hw->di[1]);
+
+ /*
+ * FIFO 2
+ * TX: TX_AC_VI_FIFO (TX AC Video data packets)
+ * RX: UNUSED
+ */
+ wlc_hw->di[2] = dma_attach(name, wlc_hw->sih,
+ dmareg(wlc_hw, DMA_TX, 2), NULL,
+ NTXD, 0, 0, -1, 0, 0,
+ &brcm_msg_level);
+ dma_attach_err |= (NULL == wlc_hw->di[2]);
+ /*
+ * FIFO 3
+ * TX: TX_AC_VO_FIFO (TX AC Voice data packets)
+ * (legacy) TX_CTL_FIFO (TX control & mgmt packets)
+ */
+ wlc_hw->di[3] = dma_attach(name, wlc_hw->sih,
+ dmareg(wlc_hw, DMA_TX, 3),
+ NULL, NTXD, 0, 0, -1,
+ 0, 0, &brcm_msg_level);
+ dma_attach_err |= (NULL == wlc_hw->di[3]);
+/* Cleaner to leave this as if with AP defined */
+
+ if (dma_attach_err) {
+ wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed"
+ "\n", unit);
+ return false;
+ }
+
+ /* get pointer to dma engine tx flow control variable */
+ for (i = 0; i < NFIFO; i++)
+ if (wlc_hw->di[i])
+ wlc_hw->txavail[i] =
+ (uint *) dma_getvar(wlc_hw->di[i],
+ "&txavail");
+ }
+
+ /* initial ucode host flags */
+ brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2);
+
return true;
}
+static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw)
+{
+ uint j;
+
+ for (j = 0; j < NFIFO; j++) {
+ if (wlc_hw->di[j]) {
+ dma_detach(wlc_hw->di[j]);
+ wlc_hw->di[j] = NULL;
+ }
+ }
+}
+
+/*
+ * Initialize brcms_c_info default values ...
+ * may get overrides later in this function
+ * BMAC_NOTES, move low out and resolve the dangling ones
+ */
+static void brcms_b_info_init(struct brcms_hardware *wlc_hw)
+{
+ struct brcms_c_info *wlc = wlc_hw->wlc;
+
+ /* set default sw macintmask value */
+ wlc->defmacintmask = DEF_MACINTMASK;
+
+ /* various 802.11g modes */
+ wlc_hw->shortslot = false;
+
+ wlc_hw->SFBL = RETRY_SHORT_FB;
+ wlc_hw->LFBL = RETRY_LONG_FB;
+
+ /* default mac retry limits */
+ wlc_hw->SRL = RETRY_SHORT_DEF;
+ wlc_hw->LRL = RETRY_LONG_DEF;
+ wlc_hw->chanspec = ch20mhz_chspec(1);
+}
+
+static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw)
+{
+ /* delay before first read of ucode state */
+ udelay(40);
+
+ /* wait until ucode is no longer asleep */
+ SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) ==
+ DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
+}
+
+/* control chip clock to save power, enable dynamic clock or force fast clock */
+static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
+{
+ if (wlc_hw->sih->cccaps & CC_CAP_PMU) {
+ /* new chips with PMU, CCS_FORCEHT will distribute the HT clock
+ * on backplane, but mac core will still run on ALP(not HT) when
+ * it enters powersave mode, which means the FCA bit may not be
+ * set. Should wakeup mac if driver wants it to run on HT.
+ */
+
+ if (wlc_hw->clk) {
+ if (mode == CLK_FAST) {
+ OR_REG(&wlc_hw->regs->clk_ctl_st,
+ CCS_FORCEHT);
+
+ udelay(64);
+
+ SPINWAIT(((R_REG
+ (&wlc_hw->regs->
+ clk_ctl_st) & CCS_HTAVAIL) == 0),
+ PMU_MAX_TRANSITION_DLY);
+ WARN_ON(!(R_REG
+ (&wlc_hw->regs->
+ clk_ctl_st) & CCS_HTAVAIL));
+ } else {
+ if ((wlc_hw->sih->pmurev == 0) &&
+ (R_REG
+ (&wlc_hw->regs->
+ clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ)))
+ SPINWAIT(((R_REG
+ (&wlc_hw->regs->
+ clk_ctl_st) & CCS_HTAVAIL)
+ == 0),
+ PMU_MAX_TRANSITION_DLY);
+ AND_REG(&wlc_hw->regs->clk_ctl_st,
+ ~CCS_FORCEHT);
+ }
+ }
+ wlc_hw->forcefastclk = (mode == CLK_FAST);
+ } else {
+
+ /* old chips w/o PMU, force HT through cc,
+ * then use FCA to verify mac is running fast clock
+ */
+
+ wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode);
+
+ /* check fast clock is available (if core is not in reset) */
+ if (wlc_hw->forcefastclk && wlc_hw->clk)
+ WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) &
+ SISF_FCLKA));
+
+ /*
+ * keep the ucode wake bit on if forcefastclk is on since we
+ * do not want ucode to put us back to slow clock when it dozes
+ * for PM mode. Code below matches the wake override bit with
+ * current forcefastclk state. Only setting bit in wake_override
+ * instead of waking ucode immediately since old code had this
+ * behavior. Older code set wlc->forcefastclk but only had the
+ * wake happen if the wakup_ucode work (protected by an up
+ * check) was executed just below.
+ */
+ if (wlc_hw->forcefastclk)
+ mboolset(wlc_hw->wake_override,
+ BRCMS_WAKE_OVERRIDE_FORCEFAST);
+ else
+ mboolclr(wlc_hw->wake_override,
+ BRCMS_WAKE_OVERRIDE_FORCEFAST);
+ }
+}
+
+/* set or clear ucode host flag bits
+ * it has an optimization for no-change write
+ * it only writes through shared memory when the core has clock;
+ * pre-CLK changes should use wlc_write_mhf to get around the optimization
+ *
+ *
+ * bands values are: BRCM_BAND_AUTO <--- Current band only
+ * BRCM_BAND_5G <--- 5G band only
+ * BRCM_BAND_2G <--- 2G band only
+ * BRCM_BAND_ALL <--- All bands
+ */
+void
+brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val,
+ int bands)
+{
+ u16 save;
+ u16 addr[MHFMAX] = {
+ M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
+ M_HOST_FLAGS5
+ };
+ struct brcms_hw_band *band;
+
+ if ((val & ~mask) || idx >= MHFMAX)
+ return; /* error condition */
+
+ switch (bands) {
+ /* Current band only or all bands,
+ * then set the band to current band
+ */
+ case BRCM_BAND_AUTO:
+ case BRCM_BAND_ALL:
+ band = wlc_hw->band;
+ break;
+ case BRCM_BAND_5G:
+ band = wlc_hw->bandstate[BAND_5G_INDEX];
+ break;
+ case BRCM_BAND_2G:
+ band = wlc_hw->bandstate[BAND_2G_INDEX];
+ break;
+ default:
+ band = NULL; /* error condition */
+ }
+
+ if (band) {
+ save = band->mhfs[idx];
+ band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
+
+ /* optimization: only write through if changed, and
+ * changed band is the current band
+ */
+ if (wlc_hw->clk && (band->mhfs[idx] != save)
+ && (band == wlc_hw->band))
+ brcms_b_write_shm(wlc_hw, addr[idx],
+ (u16) band->mhfs[idx]);
+ }
+
+ if (bands == BRCM_BAND_ALL) {
+ wlc_hw->bandstate[0]->mhfs[idx] =
+ (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val;
+ wlc_hw->bandstate[1]->mhfs[idx] =
+ (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val;
+ }
+}
+
+/* set the maccontrol register to desired reset state and
+ * initialize the sw cache of the register
+ */
+static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw)
+{
+ /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
+ wlc_hw->maccontrol = 0;
+ wlc_hw->suspended_fifos = 0;
+ wlc_hw->wake_override = 0;
+ wlc_hw->mute_override = 0;
+ brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
+}
+
+/*
+ * write the software state of maccontrol and
+ * overrides to the maccontrol register
+ */
+static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw)
+{
+ u32 maccontrol = wlc_hw->maccontrol;
+
+ /* OR in the wake bit if overridden */
+ if (wlc_hw->wake_override)
+ maccontrol |= MCTL_WAKE;
+
+ /* set AP and INFRA bits for mute if needed */
+ if (wlc_hw->mute_override) {
+ maccontrol &= ~(MCTL_AP);
+ maccontrol |= MCTL_INFRA;
+ }
+
+ W_REG(&wlc_hw->regs->maccontrol, maccontrol);
+}
+
+/* set or clear maccontrol bits */
+void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val)
+{
+ u32 maccontrol;
+ u32 new_maccontrol;
+
+ if (val & ~mask)
+ return; /* error condition */
+ maccontrol = wlc_hw->maccontrol;
+ new_maccontrol = (maccontrol & ~mask) | val;
+
+ /* if the new maccontrol value is the same as the old, nothing to do */
+ if (new_maccontrol == maccontrol)
+ return;
+
+ /* something changed, cache the new value */
+ wlc_hw->maccontrol = new_maccontrol;
+
+ /* write the new values with overrides applied */
+ brcms_c_mctrl_write(wlc_hw);
+}
+
+void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
+ u32 override_bit)
+{
+ if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) {
+ mboolset(wlc_hw->wake_override, override_bit);
+ return;
+ }
+
+ mboolset(wlc_hw->wake_override, override_bit);
+
+ brcms_c_mctrl_write(wlc_hw);
+ brcms_b_wait_for_wake(wlc_hw);
+}
+
+void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
+ u32 override_bit)
+{
+ mboolclr(wlc_hw->wake_override, override_bit);
+
+ if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE))
+ return;
+
+ brcms_c_mctrl_write(wlc_hw);
+}
+
+/* When driver needs ucode to stop beaconing, it has to make sure that
+ * MCTL_AP is clear and MCTL_INFRA is set
+ * Mode MCTL_AP MCTL_INFRA
+ * AP 1 1
+ * STA 0 1 <--- This will ensure no beacons
+ * IBSS 0 0
+ */
+static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw)
+{
+ wlc_hw->mute_override = 1;
+
+ /* if maccontrol already has AP == 0 and INFRA == 1 without this
+ * override, then there is no change to write
+ */
+ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
+ return;
+
+ brcms_c_mctrl_write(wlc_hw);
+}
+
+/* Clear the override on AP and INFRA bits */
+static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw)
+{
+ if (wlc_hw->mute_override == 0)
+ return;
+
+ wlc_hw->mute_override = 0;
+
+ /* if maccontrol already has AP == 0 and INFRA == 1 without this
+ * override, then there is no change to write
+ */
+ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
+ return;
+
+ brcms_c_mctrl_write(wlc_hw);
+}
+
+/*
+ * Write a MAC address to the given match reg offset in the RXE match engine.
+ */
+static void
+brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset,
+ const u8 *addr)
+{
+ struct d11regs __iomem *regs;
+ u16 mac_l;
+ u16 mac_m;
+ u16 mac_h;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n",
+ wlc_hw->unit);
+
+ regs = wlc_hw->regs;
+ mac_l = addr[0] | (addr[1] << 8);
+ mac_m = addr[2] | (addr[3] << 8);
+ mac_h = addr[4] | (addr[5] << 8);
+
+ /* enter the MAC addr into the RXE match registers */
+ W_REG(&regs->rcm_ctl, RCM_INC_DATA | match_reg_offset);
+ W_REG(&regs->rcm_mat_data, mac_l);
+ W_REG(&regs->rcm_mat_data, mac_m);
+ W_REG(&regs->rcm_mat_data, mac_h);
+
+}
+
+void
+brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len,
+ void *buf)
+{
+ struct d11regs __iomem *regs;
+ u32 word;
+ __le32 word_le;
+ __be32 word_be;
+ bool be_bit;
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ regs = wlc_hw->regs;
+ W_REG(&regs->tplatewrptr, offset);
+
+ /* if MCTL_BIGEND bit set in mac control register,
+ * the chip swaps data in fifo, as well as data in
+ * template ram
+ */
+ be_bit = (R_REG(&regs->maccontrol) & MCTL_BIGEND) != 0;
+
+ while (len > 0) {
+ memcpy(&word, buf, sizeof(u32));
+
+ if (be_bit) {
+ word_be = cpu_to_be32(word);
+ word = *(u32 *)&word_be;
+ } else {
+ word_le = cpu_to_le32(word);
+ word = *(u32 *)&word_le;
+ }
+
+ W_REG(&regs->tplatewrdata, word);
+
+ buf = (u8 *) buf + sizeof(u32);
+ len -= sizeof(u32);
+ }
+}
+
+static void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin)
+{
+ wlc_hw->band->CWmin = newmin;
+
+ W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN);
+ (void)R_REG(&wlc_hw->regs->objaddr);
+ W_REG(&wlc_hw->regs->objdata, newmin);
+}
+
+static void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax)
+{
+ wlc_hw->band->CWmax = newmax;
+
+ W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX);
+ (void)R_REG(&wlc_hw->regs->objaddr);
+ W_REG(&wlc_hw->regs->objdata, newmax);
+}
+
+void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw)
+{
+ bool fastclk;
+
+ /* request FAST clock if not on */
+ fastclk = wlc_hw->forcefastclk;
+ if (!fastclk)
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+ wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
+
+ brcms_b_phy_reset(wlc_hw);
+ wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi));
+
+ /* restore the clk */
+ if (!fastclk)
+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw)
+{
+ u16 v;
+ struct brcms_c_info *wlc = wlc_hw->wlc;
+ /* update SYNTHPU_DLY */
+
+ if (BRCMS_ISLCNPHY(wlc->band))
+ v = SYNTHPU_DLY_LPPHY_US;
+ else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3)))
+ v = SYNTHPU_DLY_NPHY_US;
+ else
+ v = SYNTHPU_DLY_BPHY_US;
+
+ brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v);
+}
+
+static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw)
+{
+ u16 phyctl;
+ u16 phytxant = wlc_hw->bmac_phytxant;
+ u16 mask = PHY_TXC_ANT_MASK;
+
+ /* set the Probe Response frame phy control word */
+ phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS);
+ phyctl = (phyctl & ~mask) | phytxant;
+ brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl);
+
+ /* set the Response (ACK/CTS) frame phy control word */
+ phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD);
+ phyctl = (phyctl & ~mask) | phytxant;
+ brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl);
+}
+
+static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw,
+ u8 rate)
+{
+ uint i;
+ u8 plcp_rate = 0;
+ struct plcp_signal_rate_lookup {
+ u8 rate;
+ u8 signal_rate;
+ };
+ /* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */
+ const struct plcp_signal_rate_lookup rate_lookup[] = {
+ {BRCM_RATE_6M, 0xB},
+ {BRCM_RATE_9M, 0xF},
+ {BRCM_RATE_12M, 0xA},
+ {BRCM_RATE_18M, 0xE},
+ {BRCM_RATE_24M, 0x9},
+ {BRCM_RATE_36M, 0xD},
+ {BRCM_RATE_48M, 0x8},
+ {BRCM_RATE_54M, 0xC}
+ };
+
+ for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) {
+ if (rate == rate_lookup[i].rate) {
+ plcp_rate = rate_lookup[i].signal_rate;
+ break;
+ }
+ }
+
+ /* Find the SHM pointer to the rate table entry by looking in the
+ * Direct-map Table
+ */
+ return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
+}
+
+static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw)
+{
+ u8 rate;
+ u8 rates[8] = {
+ BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M,
+ BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M
+ };
+ u16 entry_ptr;
+ u16 pctl1;
+ uint i;
+
+ if (!BRCMS_PHY_11N_CAP(wlc_hw->band))
+ return;
+
+ /* walk the phy rate table and update the entries */
+ for (i = 0; i < ARRAY_SIZE(rates); i++) {
+ rate = rates[i];
+
+ entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate);
+
+ /* read the SHM Rate Table entry OFDM PCTL1 values */
+ pctl1 =
+ brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS);
+
+ /* modify the value */
+ pctl1 &= ~PHY_TXC1_MODE_MASK;
+ pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT);
+
+ /* Update the SHM Rate Table entry OFDM PCTL1 values */
+ brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS,
+ pctl1);
+ }
+}
+
+/* band-specific init */
+static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+
+ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
+ wlc_hw->band->bandunit);
+
+ brcms_c_ucode_bsinit(wlc_hw);
+
+ wlc_phy_init(wlc_hw->band->pi, chanspec);
+
+ brcms_c_ucode_txant_set(wlc_hw);
+
+ /*
+ * cwmin is band-specific, update hardware
+ * with value for current band
+ */
+ brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
+ brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
+
+ brcms_b_update_slot_timing(wlc_hw,
+ wlc_hw->band->bandtype == BRCM_BAND_5G ?
+ true : wlc_hw->shortslot);
+
+ /* write phytype and phyvers */
+ brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype);
+ brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev);
+
+ /*
+ * initialize the txphyctl1 rate table since
+ * shmem is shared between bands
+ */
+ brcms_upd_ofdm_pctl1_table(wlc_hw);
+
+ brcms_b_upd_synthpu(wlc_hw);
+}
+
+/* Perform a soft reset of the PHY PLL */
+void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw)
+{
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ ai_corereg(wlc_hw->sih, SI_CC_IDX,
+ offsetof(struct chipcregs, chipcontrol_addr), ~0, 0);
+ udelay(1);
+ ai_corereg(wlc_hw->sih, SI_CC_IDX,
+ offsetof(struct chipcregs, chipcontrol_data), 0x4, 0);
+ udelay(1);
+ ai_corereg(wlc_hw->sih, SI_CC_IDX,
+ offsetof(struct chipcregs, chipcontrol_data), 0x4, 4);
+ udelay(1);
+ ai_corereg(wlc_hw->sih, SI_CC_IDX,
+ offsetof(struct chipcregs, chipcontrol_data), 0x4, 0);
+ udelay(1);
+}
+
+/* light way to turn on phy clock without reset for NPHY only
+ * refer to brcms_b_core_phy_clk for full version
+ */
+void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk)
+{
+ /* support(necessary for NPHY and HYPHY) only */
+ if (!BRCMS_ISNPHY(wlc_hw->band))
+ return;
+
+ if (ON == clk)
+ ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC);
+ else
+ ai_core_cflags(wlc_hw->sih, SICF_FGC, 0);
+
+}
+
+void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk)
+{
+ if (ON == clk)
+ ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE);
+ else
+ ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0);
+}
+
+void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
+{
+ struct brcms_phy_pub *pih = wlc_hw->band->pi;
+ u32 phy_bw_clkbits;
+ bool phy_in_reset = false;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ if (pih == NULL)
+ return;
+
+ phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi);
+
+ /* Specific reset sequence required for NPHY rev 3 and 4 */
+ if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
+ NREV_LE(wlc_hw->band->phyrev, 4)) {
+ /* Set the PHY bandwidth */
+ ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits);
+
+ udelay(1);
+
+ /* Perform a soft reset of the PHY PLL */
+ brcms_b_core_phypll_reset(wlc_hw);
+
+ /* reset the PHY */
+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE),
+ (SICF_PRST | SICF_PCLKE));
+ phy_in_reset = true;
+ } else {
+ ai_core_cflags(wlc_hw->sih,
+ (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
+ (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
+ }
+
+ udelay(2);
+ brcms_b_core_phy_clk(wlc_hw, ON);
+
+ if (pih)
+ wlc_phy_anacore(pih, ON);
+}
+
+/* switch to and initialize new band */
+static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
+ u16 chanspec) {
+ struct brcms_c_info *wlc = wlc_hw->wlc;
+ u32 macintmask;
+
+ /* Enable the d11 core before accessing it */
+ if (!ai_iscoreup(wlc_hw->sih)) {
+ ai_core_reset(wlc_hw->sih, 0, 0);
+ brcms_c_mctrl_reset(wlc_hw);
+ }
+
+ macintmask = brcms_c_setband_inact(wlc, bandunit);
+
+ if (!wlc_hw->up)
+ return;
+
+ brcms_b_core_phy_clk(wlc_hw, ON);
+
+ /* band-specific initializations */
+ brcms_b_bsinit(wlc, chanspec);
+
+ /*
+ * If there are any pending software interrupt bits,
+ * then replace these with a harmless nonzero value
+ * so brcms_c_dpc() will re-enable interrupts when done.
+ */
+ if (wlc->macintstatus)
+ wlc->macintstatus = MI_DMAINT;
+
+ /* restore macintmask */
+ brcms_intrsrestore(wlc->wl, macintmask);
+
+ /* ucode should still be suspended.. */
+ WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
+}
+
+static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw)
+{
+
+ /* reject unsupported corerev */
+ if (!CONF_HAS(D11CONF, wlc_hw->corerev)) {
+ wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n",
+ wlc_hw->corerev);
+ return false;
+ }
+
+ return true;
+}
+
+/* Validate some board info parameters */
+static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw)
+{
+ uint boardrev = wlc_hw->boardrev;
+
+ /* 4 bits each for board type, major, minor, and tiny version */
+ uint brt = (boardrev & 0xf000) >> 12;
+ uint b0 = (boardrev & 0xf00) >> 8;
+ uint b1 = (boardrev & 0xf0) >> 4;
+ uint b2 = boardrev & 0xf;
+
+ /* voards from other vendors are always considered valid */
+ if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM)
+ return true;
+
+ /* do some boardrev sanity checks when boardvendor is Broadcom */
+ if (boardrev == 0)
+ return false;
+
+ if (boardrev <= 0xff)
+ return true;
+
+ if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9)
+ || (b2 > 9))
+ return false;
+
+ return true;
+}
+
+static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw)
+{
+ enum brcms_srom_id var_id = BRCMS_SROM_MACADDR;
+ char *macaddr;
+
+ /* If macaddr exists, use it (Sromrev4, CIS, ...). */
+ macaddr = getvar(wlc_hw->sih, var_id);
+ if (macaddr != NULL)
+ return macaddr;
+
+ if (wlc_hw->_nbands > 1)
+ var_id = BRCMS_SROM_ET1MACADDR;
+ else
+ var_id = BRCMS_SROM_IL0MACADDR;
+
+ macaddr = getvar(wlc_hw->sih, var_id);
+ if (macaddr == NULL)
+ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr "
+ "getvar(%d) not found\n", wlc_hw->unit, var_id);
+
+ return macaddr;
+}
+
+/* power both the pll and external oscillator on/off */
+static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want)
+{
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want);
+
+ /*
+ * dont power down if plldown is false or
+ * we must poll hw radio disable
+ */
+ if (!want && wlc_hw->pllreq)
+ return;
+
+ if (wlc_hw->sih)
+ ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want);
+
+ wlc_hw->sbclk = want;
+ if (!wlc_hw->sbclk) {
+ wlc_hw->clk = false;
+ if (wlc_hw->band && wlc_hw->band->pi)
+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+ }
+}
+
+/*
+ * Return true if radio is disabled, otherwise false.
+ * hw radio disable signal is an external pin, users activate it asynchronously
+ * this function could be called when driver is down and w/o clock
+ * it operates on different registers depending on corerev and boardflag.
+ */
+static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
+{
+ bool v, clk, xtal;
+ u32 resetbits = 0, flags = 0;
+
+ xtal = wlc_hw->sbclk;
+ if (!xtal)
+ brcms_b_xtal(wlc_hw, ON);
+
+ /* may need to take core out of reset first */
+ clk = wlc_hw->clk;
+ if (!clk) {
+ /*
+ * mac no longer enables phyclk automatically when driver
+ * accesses phyreg throughput mac. This can be skipped since
+ * only mac reg is accessed below
+ */
+ flags |= SICF_PCLKE;
+
+ /*
+ * AI chip doesn't restore bar0win2 on
+ * hibernation/resume, need sw fixup
+ */
+ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+ (wlc_hw->sih->chip == BCM43225_CHIP_ID))
+ wlc_hw->regs = (struct d11regs __iomem *)
+ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
+ ai_core_reset(wlc_hw->sih, flags, resetbits);
+ brcms_c_mctrl_reset(wlc_hw);
+ }
+
+ v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0);
+
+ /* put core back into reset */
+ if (!clk)
+ ai_core_disable(wlc_hw->sih, 0);
+
+ if (!xtal)
+ brcms_b_xtal(wlc_hw, OFF);
+
+ return v;
+}
+
+static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo)
+{
+ struct dma_pub *di = wlc_hw->di[fifo];
+ return dma_rxreset(di);
+}
+
+/* d11 core reset
+ * ensure fask clock during reset
+ * reset dma
+ * reset d11(out of reset)
+ * reset phy(out of reset)
+ * clear software macintstatus for fresh new start
+ * one testing hack wlc_hw->noreset will bypass the d11/phy reset
+ */
+void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
+{
+ struct d11regs __iomem *regs;
+ uint i;
+ bool fastclk;
+ u32 resetbits = 0;
+
+ if (flags == BRCMS_USE_COREFLAGS)
+ flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ regs = wlc_hw->regs;
+
+ /* request FAST clock if not on */
+ fastclk = wlc_hw->forcefastclk;
+ if (!fastclk)
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+ /* reset the dma engines except first time thru */
+ if (ai_iscoreup(wlc_hw->sih)) {
+ for (i = 0; i < NFIFO; i++)
+ if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i])))
+ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: "
+ "dma_txreset[%d]: cannot stop dma\n",
+ wlc_hw->unit, __func__, i);
+
+ if ((wlc_hw->di[RX_FIFO])
+ && (!wlc_dma_rxreset(wlc_hw, RX_FIFO)))
+ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset"
+ "[%d]: cannot stop dma\n",
+ wlc_hw->unit, __func__, RX_FIFO);
+ }
+ /* if noreset, just stop the psm and return */
+ if (wlc_hw->noreset) {
+ wlc_hw->wlc->macintstatus = 0; /* skip wl_dpc after down */
+ brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0);
+ return;
+ }
+
+ /*
+ * mac no longer enables phyclk automatically when driver accesses
+ * phyreg throughput mac, AND phy_reset is skipped at early stage when
+ * band->pi is invalid. need to enable PHY CLK
+ */
+ flags |= SICF_PCLKE;
+
+ /*
+ * reset the core
+ * In chips with PMU, the fastclk request goes through d11 core
+ * reg 0x1e0, which is cleared by the core_reset. have to re-request it.
+ *
+ * This adds some delay and we can optimize it by also requesting
+ * fastclk through chipcommon during this period if necessary. But
+ * that has to work coordinate with other driver like mips/arm since
+ * they may touch chipcommon as well.
+ */
+ wlc_hw->clk = false;
+ ai_core_reset(wlc_hw->sih, flags, resetbits);
+ wlc_hw->clk = true;
+ if (wlc_hw->band && wlc_hw->band->pi)
+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
+
+ brcms_c_mctrl_reset(wlc_hw);
+
+ if (wlc_hw->sih->cccaps & CC_CAP_PMU)
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+ brcms_b_phy_reset(wlc_hw);
+
+ /* turn on PHY_PLL */
+ brcms_b_core_phypll_ctl(wlc_hw, true);
+
+ /* clear sw intstatus */
+ wlc_hw->wlc->macintstatus = 0;
+
+ /* restore the clk setting */
+ if (!fastclk)
+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+/* txfifo sizes needs to be modified(increased) since the newer cores
+ * have more memory.
+ */
+static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u16 fifo_nu;
+ u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
+ u16 txfifo_def, txfifo_def1;
+ u16 txfifo_cmd;
+
+ /* tx fifos start at TXFIFO_START_BLK from the Base address */
+ txfifo_startblk = TXFIFO_START_BLK;
+
+ /* sequence of operations: reset fifo, set fifo size, reset fifo */
+ for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) {
+
+ txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu];
+ txfifo_def = (txfifo_startblk & 0xff) |
+ (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT);
+ txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) |
+ ((((txfifo_endblk -
+ 1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT);
+ txfifo_cmd =
+ TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
+
+ W_REG(&regs->xmtfifocmd, txfifo_cmd);
+ W_REG(&regs->xmtfifodef, txfifo_def);
+ W_REG(&regs->xmtfifodef1, txfifo_def1);
+
+ W_REG(&regs->xmtfifocmd, txfifo_cmd);
+
+ txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
+ }
+ /*
+ * need to propagate to shm location to be in sync since ucode/hw won't
+ * do this
+ */
+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE0,
+ wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE1,
+ wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE2,
+ ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
+ xmtfifo_sz[TX_AC_BK_FIFO]));
+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE3,
+ ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
+ xmtfifo_sz[TX_BCMC_FIFO]));
+}
+
+/* This function is used for changing the tsf frac register
+ * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz
+ * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz
+ * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz
+ * HTPHY Formula is 2^26/freq(MHz) e.g.
+ * For spuron2 - 126MHz -> 2^26/126 = 532610.0
+ * - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082
+ * For spuron: 123MHz -> 2^26/123 = 545600.5
+ * - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341
+ * For spur off: 120MHz -> 2^26/120 = 559240.5
+ * - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
+ */
+
+void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+
+ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+ (wlc_hw->sih->chip == BCM43225_CHIP_ID)) {
+ if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */
+ W_REG(&regs->tsf_clk_frac_l, 0x2082);
+ W_REG(&regs->tsf_clk_frac_h, 0x8);
+ } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */
+ W_REG(&regs->tsf_clk_frac_l, 0x5341);
+ W_REG(&regs->tsf_clk_frac_h, 0x8);
+ } else { /* 120Mhz */
+ W_REG(&regs->tsf_clk_frac_l, 0x8889);
+ W_REG(&regs->tsf_clk_frac_h, 0x8);
+ }
+ } else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+ if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */
+ W_REG(&regs->tsf_clk_frac_l, 0x7CE0);
+ W_REG(&regs->tsf_clk_frac_h, 0xC);
+ } else { /* 80Mhz */
+ W_REG(&regs->tsf_clk_frac_l, 0xCCCD);
+ W_REG(&regs->tsf_clk_frac_h, 0xC);
+ }
+ }
+}
+
+/* Initialize GPIOs that are controlled by D11 core */
+static void brcms_c_gpio_init(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs;
+ u32 gc, gm;
+
+ regs = wlc_hw->regs;
+
+ /* use GPIO select 0 to get all gpio signals from the gpio out reg */
+ brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
+
+ /*
+ * Common GPIO setup:
+ * G0 = LED 0 = WLAN Activity
+ * G1 = LED 1 = WLAN 2.4 GHz Radio State
+ * G2 = LED 2 = WLAN 5 GHz Radio State
+ * G4 = radio disable input (HI enabled, LO disabled)
+ */
+
+ gc = gm = 0;
+
+ /* Allocate GPIOs for mimo antenna diversity feature */
+ if (wlc_hw->antsel_type == ANTSEL_2x3) {
+ /* Enable antenna diversity, use 2x3 mode */
+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
+ MHF3_ANTSEL_EN, BRCM_BAND_ALL);
+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
+ MHF3_ANTSEL_MODE, BRCM_BAND_ALL);
+
+ /* init superswitch control */
+ wlc_phy_antsel_init(wlc_hw->band->pi, false);
+
+ } else if (wlc_hw->antsel_type == ANTSEL_2x4) {
+ gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13);
+ /*
+ * The board itself is powered by these GPIOs
+ * (when not sending pattern) so set them high
+ */
+ OR_REG(&regs->psm_gpio_oe,
+ (BOARD_GPIO_12 | BOARD_GPIO_13));
+ OR_REG(&regs->psm_gpio_out,
+ (BOARD_GPIO_12 | BOARD_GPIO_13));
+
+ /* Enable antenna diversity, use 2x4 mode */
+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
+ MHF3_ANTSEL_EN, BRCM_BAND_ALL);
+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0,
+ BRCM_BAND_ALL);
+
+ /* Configure the desired clock to be 4Mhz */
+ brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV,
+ ANTSEL_CLKDIV_4MHZ);
+ }
+
+ /*
+ * gpio 9 controls the PA. ucode is responsible
+ * for wiggling out and oe
+ */
+ if (wlc_hw->boardflags & BFL_PACTRL)
+ gm |= gc |= BOARD_GPIO_PACTRL;
+
+ /* apply to gpiocontrol register */
+ ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY);
+}
+
+static void brcms_ucode_write(struct brcms_hardware *wlc_hw,
+ const __le32 ucode[], const size_t nbytes)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ uint i;
+ uint count;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ count = (nbytes / sizeof(u32));
+
+ W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
+ (void)R_REG(&regs->objaddr);
+ for (i = 0; i < count; i++)
+ W_REG(&regs->objdata, le32_to_cpu(ucode[i]));
+
+}
+
+static void brcms_ucode_download(struct brcms_hardware *wlc_hw)
+{
+ struct brcms_c_info *wlc;
+ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
+
+ wlc = wlc_hw->wlc;
+
+ if (wlc_hw->ucode_loaded)
+ return;
+
+ if (D11REV_IS(wlc_hw->corerev, 23)) {
+ if (BRCMS_ISNPHY(wlc_hw->band)) {
+ brcms_ucode_write(wlc_hw, ucode->bcm43xx_16_mimo,
+ ucode->bcm43xx_16_mimosz);
+ wlc_hw->ucode_loaded = true;
+ } else
+ wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
+ "corerev %d\n",
+ __func__, wlc_hw->unit, wlc_hw->corerev);
+ } else if (D11REV_IS(wlc_hw->corerev, 24)) {
+ if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+ brcms_ucode_write(wlc_hw, ucode->bcm43xx_24_lcn,
+ ucode->bcm43xx_24_lcnsz);
+ wlc_hw->ucode_loaded = true;
+ } else {
+ wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
+ "corerev %d\n",
+ __func__, wlc_hw->unit, wlc_hw->corerev);
+ }
+ }
+}
+
+void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant)
+{
+ /* update sw state */
+ wlc_hw->bmac_phytxant = phytxant;
+
+ /* push to ucode if up */
+ if (!wlc_hw->up)
+ return;
+ brcms_c_ucode_txant_set(wlc_hw);
+
+}
+
+u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw)
+{
+ return (u16) wlc_hw->wlc->stf->txant;
+}
+
+void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type)
+{
+ wlc_hw->antsel_type = antsel_type;
+
+ /* Update the antsel type for phy module to use */
+ wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
+}
+
+static void brcms_c_fatal_error(struct brcms_c_info *wlc)
+{
+ wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n",
+ wlc->pub->unit);
+ brcms_init(wlc->wl);
+}
+
+static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
+{
+ bool fatal = false;
+ uint unit;
+ uint intstatus, idx;
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ struct wiphy *wiphy = wlc_hw->wlc->wiphy;
+
+ unit = wlc_hw->unit;
+
+ for (idx = 0; idx < NFIFO; idx++) {
+ /* read intstatus register and ignore any non-error bits */
+ intstatus =
+ R_REG(&regs->intctrlregs[idx].intstatus) & I_ERRORS;
+ if (!intstatus)
+ continue;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n",
+ unit, idx, intstatus);
+
+ if (intstatus & I_RO) {
+ wiphy_err(wiphy, "wl%d: fifo %d: receive fifo "
+ "overflow\n", unit, idx);
+ fatal = true;
+ }
+
+ if (intstatus & I_PC) {
+ wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n",
+ unit, idx);
+ fatal = true;
+ }
+
+ if (intstatus & I_PD) {
+ wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit,
+ idx);
+ fatal = true;
+ }
+
+ if (intstatus & I_DE) {
+ wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol "
+ "error\n", unit, idx);
+ fatal = true;
+ }
+
+ if (intstatus & I_RU)
+ wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor "
+ "underflow\n", idx, unit);
+
+ if (intstatus & I_XU) {
+ wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo "
+ "underflow\n", idx, unit);
+ fatal = true;
+ }
+
+ if (fatal) {
+ brcms_c_fatal_error(wlc_hw->wlc); /* big hammer */
+ break;
+ } else
+ W_REG(&regs->intctrlregs[idx].intstatus,
+ intstatus);
+ }
+}
+
+void brcms_c_intrson(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ wlc->macintmask = wlc->defmacintmask;
+ W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
+}
+
+/*
+ * callback for siutils.c, which has only wlc handler, no wl they both check
+ * up, not only because there is no need to off/restore d11 interrupt but also
+ * because per-port code may require sync with valid interrupt.
+ */
+static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc)
+{
+ if (!wlc->hw->up)
+ return 0;
+
+ return brcms_intrsoff(wlc->wl);
+}
+
+static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask)
+{
+ if (!wlc->hw->up)
+ return;
+
+ brcms_intrsrestore(wlc->wl, macintmask);
+}
+
+u32 brcms_c_intrsoff(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ u32 macintmask;
+
+ if (!wlc_hw->clk)
+ return 0;
+
+ macintmask = wlc->macintmask; /* isr can still happen */
+
+ W_REG(&wlc_hw->regs->macintmask, 0);
+ (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */
+ udelay(1); /* ensure int line is no longer driven */
+ wlc->macintmask = 0;
+
+ /* return previous macintmask; resolve race between us and our isr */
+ return wlc->macintstatus ? 0 : macintmask;
+}
+
+void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ if (!wlc_hw->clk)
+ return;
+
+ wlc->macintmask = macintmask;
+ W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
+}
+
+static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
+ uint tx_fifo)
+{
+ u8 fifo = 1 << tx_fifo;
+
+ /* Two clients of this code, 11h Quiet period and scanning. */
+
+ /* only suspend if not already suspended */
+ if ((wlc_hw->suspended_fifos & fifo) == fifo)
+ return;
+
+ /* force the core awake only if not already */
+ if (wlc_hw->suspended_fifos == 0)
+ brcms_c_ucode_wake_override_set(wlc_hw,
+ BRCMS_WAKE_OVERRIDE_TXFIFO);
+
+ wlc_hw->suspended_fifos |= fifo;
+
+ if (wlc_hw->di[tx_fifo]) {
+ /*
+ * Suspending AMPDU transmissions in the middle can cause
+ * underflow which may result in mismatch between ucode and
+ * driver so suspend the mac before suspending the FIFO
+ */
+ if (BRCMS_PHY_11N_CAP(wlc_hw->band))
+ brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+
+ dma_txsuspend(wlc_hw->di[tx_fifo]);
+
+ if (BRCMS_PHY_11N_CAP(wlc_hw->band))
+ brcms_c_enable_mac(wlc_hw->wlc);
+ }
+}
+
+static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
+ uint tx_fifo)
+{
+ /* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case
+ * but need to be done here for PIO otherwise the watchdog will catch
+ * the inconsistency and fire
+ */
+ /* Two clients of this code, 11h Quiet period and scanning. */
+ if (wlc_hw->di[tx_fifo])
+ dma_txresume(wlc_hw->di[tx_fifo]);
+
+ /* allow core to sleep again */
+ if (wlc_hw->suspended_fifos == 0)
+ return;
+ else {
+ wlc_hw->suspended_fifos &= ~(1 << tx_fifo);
+ if (wlc_hw->suspended_fifos == 0)
+ brcms_c_ucode_wake_override_clear(wlc_hw,
+ BRCMS_WAKE_OVERRIDE_TXFIFO);
+ }
+}
+
+static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, u32 flags)
+{
+ static const u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
+
+ if (on) {
+ /* suspend tx fifos */
+ brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
+ brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
+ brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO);
+ brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
+
+ /* zero the address match register so we do not send ACKs */
+ brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
+ null_ether_addr);
+ } else {
+ /* resume tx fifos */
+ brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
+ brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO);
+ brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO);
+ brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
+
+ /* Restore address */
+ brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
+ wlc_hw->etheraddr);
+ }
+
+ wlc_phy_mute_upd(wlc_hw->band->pi, on, flags);
+
+ if (on)
+ brcms_c_ucode_mute_override_set(wlc_hw);
+ else
+ brcms_c_ucode_mute_override_clear(wlc_hw);
+}
+
+/*
+ * Read and clear macintmask and macintstatus and intstatus registers.
+ * This routine should be called with interrupts off
+ * Return:
+ * -1 if brcms_deviceremoved(wlc) evaluates to true;
+ * 0 if the interrupt is not for us, or we are in some special cases;
+ * device interrupt status bits otherwise.
+ */
+static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u32 macintstatus;
+
+ /* macintstatus includes a DMA interrupt summary bit */
+ macintstatus = R_REG(&regs->macintstatus);
+
+ BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit,
+ macintstatus);
+
+ /* detect cardbus removed, in power down(suspend) and in reset */
+ if (brcms_deviceremoved(wlc))
+ return -1;
+
+ /* brcms_deviceremoved() succeeds even when the core is still resetting,
+ * handle that case here.
+ */
+ if (macintstatus == 0xffffffff)
+ return 0;
+
+ /* defer unsolicited interrupts */
+ macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
+
+ /* if not for us */
+ if (macintstatus == 0)
+ return 0;
+
+ /* interrupts are already turned off for CFE build
+ * Caution: For CFE Turning off the interrupts again has some undesired
+ * consequences
+ */
+ /* turn off the interrupts */
+ W_REG(&regs->macintmask, 0);
+ (void)R_REG(&regs->macintmask); /* sync readback */
+ wlc->macintmask = 0;
+
+ /* clear device interrupts */
+ W_REG(&regs->macintstatus, macintstatus);
+
+ /* MI_DMAINT is indication of non-zero intstatus */
+ if (macintstatus & MI_DMAINT)
+ /*
+ * only fifo interrupt enabled is I_RI in
+ * RX_FIFO. If MI_DMAINT is set, assume it
+ * is set and clear the interrupt.
+ */
+ W_REG(&regs->intctrlregs[RX_FIFO].intstatus,
+ DEF_RXINTMASK);
+
+ return macintstatus;
+}
+
+/* Update wlc->macintstatus and wlc->intstatus[]. */
+/* Return true if they are updated successfully. false otherwise */
+bool brcms_c_intrsupd(struct brcms_c_info *wlc)
+{
+ u32 macintstatus;
+
+ /* read and clear macintstatus and intstatus registers */
+ macintstatus = wlc_intstatus(wlc, false);
+
+ /* device is removed */
+ if (macintstatus == 0xffffffff)
+ return false;
+
+ /* update interrupt status in software */
+ wlc->macintstatus |= macintstatus;
+
+ return true;
+}
+
+/*
+ * First-level interrupt processing.
+ * Return true if this was our interrupt, false otherwise.
+ * *wantdpc will be set to true if further brcms_c_dpc() processing is required,
+ * false otherwise.
+ */
+bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ u32 macintstatus;
+
+ *wantdpc = false;
+
+ if (!wlc_hw->up || !wlc->macintmask)
+ return false;
+
+ /* read and clear macintstatus and intstatus registers */
+ macintstatus = wlc_intstatus(wlc, true);
+
+ if (macintstatus == 0xffffffff)
+ wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code"
+ " path\n");
+
+ /* it is not for us */
+ if (macintstatus == 0)
+ return false;
+
+ *wantdpc = true;
+
+ /* save interrupt status bits */
+ wlc->macintstatus = macintstatus;
+
+ return true;
+
+}
+
+void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u32 mc, mi;
+ struct wiphy *wiphy = wlc->wiphy;
+
+ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
+ wlc_hw->band->bandunit);
+
+ /*
+ * Track overlapping suspend requests
+ */
+ wlc_hw->mac_suspend_depth++;
+ if (wlc_hw->mac_suspend_depth > 1)
+ return;
+
+ /* force the core awake */
+ brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
+
+ mc = R_REG(&regs->maccontrol);
+
+ if (mc == 0xffffffff) {
+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ __func__);
+ brcms_down(wlc->wl);
+ return;
+ }
+ WARN_ON(mc & MCTL_PSM_JMP_0);
+ WARN_ON(!(mc & MCTL_PSM_RUN));
+ WARN_ON(!(mc & MCTL_EN_MAC));
+
+ mi = R_REG(&regs->macintstatus);
+ if (mi == 0xffffffff) {
+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ __func__);
+ brcms_down(wlc->wl);
+ return;
+ }
+ WARN_ON(mi & MI_MACSSPNDD);
+
+ brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0);
+
+ SPINWAIT(!(R_REG(&regs->macintstatus) & MI_MACSSPNDD),
+ BRCMS_MAX_MAC_SUSPEND);
+
+ if (!(R_REG(&regs->macintstatus) & MI_MACSSPNDD)) {
+ wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
+ " and MI_MACSSPNDD is still not on.\n",
+ wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND);
+ wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
+ "psm_brc 0x%04x\n", wlc_hw->unit,
+ R_REG(&regs->psmdebug),
+ R_REG(&regs->phydebug),
+ R_REG(&regs->psm_brc));
+ }
+
+ mc = R_REG(&regs->maccontrol);
+ if (mc == 0xffffffff) {
+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ __func__);
+ brcms_down(wlc->wl);
+ return;
+ }
+ WARN_ON(mc & MCTL_PSM_JMP_0);
+ WARN_ON(!(mc & MCTL_PSM_RUN));
+ WARN_ON(mc & MCTL_EN_MAC);
+}
+
+void brcms_c_enable_mac(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u32 mc, mi;
+
+ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
+ wlc->band->bandunit);
+
+ /*
+ * Track overlapping suspend requests
+ */
+ wlc_hw->mac_suspend_depth--;
+ if (wlc_hw->mac_suspend_depth > 0)
+ return;
+
+ mc = R_REG(&regs->maccontrol);
+ WARN_ON(mc & MCTL_PSM_JMP_0);
+ WARN_ON(mc & MCTL_EN_MAC);
+ WARN_ON(!(mc & MCTL_PSM_RUN));
+
+ brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
+ W_REG(&regs->macintstatus, MI_MACSSPNDD);
+
+ mc = R_REG(&regs->maccontrol);
+ WARN_ON(mc & MCTL_PSM_JMP_0);
+ WARN_ON(!(mc & MCTL_EN_MAC));
+ WARN_ON(!(mc & MCTL_PSM_RUN));
+
+ mi = R_REG(&regs->macintstatus);
+ WARN_ON(mi & MI_MACSSPNDD);
+
+ brcms_c_ucode_wake_override_clear(wlc_hw,
+ BRCMS_WAKE_OVERRIDE_MACSUSPEND);
+}
+
+void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode)
+{
+ wlc_hw->hw_stf_ss_opmode = stf_mode;
+
+ if (wlc_hw->clk)
+ brcms_upd_ofdm_pctl1_table(wlc_hw);
+}
+
+static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw)
+{
+ struct d11regs __iomem *regs;
+ u32 w, val;
+ struct wiphy *wiphy = wlc_hw->wlc->wiphy;
+
+ BCMMSG(wiphy, "wl%d\n", wlc_hw->unit);
+
+ regs = wlc_hw->regs;
+
+ /* Validate dchip register access */
+
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ w = R_REG(&regs->objdata);
+
+ /* Can we write and read back a 32bit register? */
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ W_REG(&regs->objdata, (u32) 0xaa5555aa);
+
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ val = R_REG(&regs->objdata);
+ if (val != (u32) 0xaa5555aa) {
+ wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
+ "expected 0xaa5555aa\n", wlc_hw->unit, val);
+ return false;
+ }
+
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ W_REG(&regs->objdata, (u32) 0x55aaaa55);
+
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ val = R_REG(&regs->objdata);
+ if (val != (u32) 0x55aaaa55) {
+ wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
+ "expected 0x55aaaa55\n", wlc_hw->unit, val);
+ return false;
+ }
+
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ W_REG(&regs->objdata, w);
+
+ /* clear CFPStart */
+ W_REG(&regs->tsf_cfpstart, 0);
+
+ w = R_REG(&regs->maccontrol);
+ if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
+ (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
+ wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = "
+ "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w,
+ (MCTL_IHR_EN | MCTL_WAKE),
+ (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE));
+ return false;
+ }
+
+ return true;
+}
+
+#define PHYPLL_WAIT_US 100000
+
+void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
+{
+ struct d11regs __iomem *regs;
+ u32 tmp;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ tmp = 0;
+ regs = wlc_hw->regs;
+
+ if (on) {
+ if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
+ OR_REG(&regs->clk_ctl_st,
+ (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL |
+ CCS_ERSRC_REQ_PHYPLL));
+ SPINWAIT((R_REG(&regs->clk_ctl_st) &
+ (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT),
+ PHYPLL_WAIT_US);
+
+ tmp = R_REG(&regs->clk_ctl_st);
+ if ((tmp & (CCS_ERSRC_AVAIL_HT)) !=
+ (CCS_ERSRC_AVAIL_HT))
+ wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY"
+ " PLL failed\n", __func__);
+ } else {
+ OR_REG(&regs->clk_ctl_st,
+ (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL));
+ SPINWAIT((R_REG(&regs->clk_ctl_st) &
+ (CCS_ERSRC_AVAIL_D11PLL |
+ CCS_ERSRC_AVAIL_PHYPLL)) !=
+ (CCS_ERSRC_AVAIL_D11PLL |
+ CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
+
+ tmp = R_REG(&regs->clk_ctl_st);
+ if ((tmp &
+ (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
+ !=
+ (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
+ wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on "
+ "PHY PLL failed\n", __func__);
+ }
+ } else {
+ /*
+ * Since the PLL may be shared, other cores can still
+ * be requesting it; so we'll deassert the request but
+ * not wait for status to comply.
+ */
+ AND_REG(&regs->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL);
+ tmp = R_REG(&regs->clk_ctl_st);
+ }
+}
+
+static void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
+{
+ bool dev_gone;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ dev_gone = brcms_deviceremoved(wlc_hw->wlc);
+
+ if (dev_gone)
+ return;
+
+ if (wlc_hw->noreset)
+ return;
+
+ /* radio off */
+ wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
+
+ /* turn off analog core */
+ wlc_phy_anacore(wlc_hw->band->pi, OFF);
+
+ /* turn off PHYPLL to save power */
+ brcms_b_core_phypll_ctl(wlc_hw, false);
+
+ wlc_hw->clk = false;
+ ai_core_disable(wlc_hw->sih, 0);
+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+}
+
+static void brcms_c_flushqueues(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ uint i;
+
+ /* free any posted tx packets */
+ for (i = 0; i < NFIFO; i++)
+ if (wlc_hw->di[i]) {
+ dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL);
+ wlc->core->txpktpend[i] = 0;
+ BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i);
+ }
+
+ /* free any posted rx packets */
+ dma_rxreclaim(wlc_hw->di[RX_FIFO]);
+}
+
+static u16
+brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u16 __iomem *objdata_lo = (u16 __iomem *)&regs->objdata;
+ u16 __iomem *objdata_hi = objdata_lo + 1;
+ u16 v;
+
+ W_REG(&regs->objaddr, sel | (offset >> 2));
+ (void)R_REG(&regs->objaddr);
+ if (offset & 2)
+ v = R_REG(objdata_hi);
+ else
+ v = R_REG(objdata_lo);
+
+ return v;
+}
+
+static void
+brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v,
+ u32 sel)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u16 __iomem *objdata_lo = (u16 __iomem *)&regs->objdata;
+ u16 __iomem *objdata_hi = objdata_lo + 1;
+
+ W_REG(&regs->objaddr, sel | (offset >> 2));
+ (void)R_REG(&regs->objaddr);
+ if (offset & 2)
+ W_REG(objdata_hi, v);
+ else
+ W_REG(objdata_lo, v);
+}
+
+/*
+ * Read a single u16 from shared memory.
+ * SHM 'offset' needs to be an even address
+ */
+u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset)
+{
+ return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL);
+}
+
+/*
+ * Write a single u16 to shared memory.
+ * SHM 'offset' needs to be an even address
+ */
+void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v)
+{
+ brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL);
+}
+
+/*
+ * Copy a buffer to shared memory of specified type .
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ * 'sel' selects the type of memory
+ */
+void
+brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset,
+ const void *buf, int len, u32 sel)
+{
+ u16 v;
+ const u8 *p = (const u8 *)buf;
+ int i;
+
+ if (len <= 0 || (offset & 1) || (len & 1))
+ return;
+
+ for (i = 0; i < len; i += 2) {
+ v = p[i] | (p[i + 1] << 8);
+ brcms_b_write_objmem(wlc_hw, offset + i, v, sel);
+ }
+}
+
+/*
+ * Copy a piece of shared memory of specified type to a buffer .
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ * 'sel' selects the type of memory
+ */
+void
+brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf,
+ int len, u32 sel)
+{
+ u16 v;
+ u8 *p = (u8 *) buf;
+ int i;
+
+ if (len <= 0 || (offset & 1) || (len & 1))
+ return;
+
+ for (i = 0; i < len; i += 2) {
+ v = brcms_b_read_objmem(wlc_hw, offset + i, sel);
+ p[i] = v & 0xFF;
+ p[i + 1] = (v >> 8) & 0xFF;
+ }
+}
+
+/* Copy a buffer to shared memory.
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ */
+static void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset,
+ const void *buf, int len)
+{
+ brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
+}
+
+static void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw,
+ u16 SRL, u16 LRL)
+{
+ wlc_hw->SRL = SRL;
+ wlc_hw->LRL = LRL;
+
+ /* write retry limit to SCR, shouldn't need to suspend */
+ if (wlc_hw->up) {
+ W_REG(&wlc_hw->regs->objaddr,
+ OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+ (void)R_REG(&wlc_hw->regs->objaddr);
+ W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL);
+ W_REG(&wlc_hw->regs->objaddr,
+ OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+ (void)R_REG(&wlc_hw->regs->objaddr);
+ W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL);
+ }
+}
+
+static void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, u32 req_bit)
+{
+ if (set) {
+ if (mboolisset(wlc_hw->pllreq, req_bit))
+ return;
+
+ mboolset(wlc_hw->pllreq, req_bit);
+
+ if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
+ if (!wlc_hw->sbclk)
+ brcms_b_xtal(wlc_hw, ON);
+ }
+ } else {
+ if (!mboolisset(wlc_hw->pllreq, req_bit))
+ return;
+
+ mboolclr(wlc_hw->pllreq, req_bit);
+
+ if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
+ if (wlc_hw->sbclk)
+ brcms_b_xtal(wlc_hw, OFF);
+ }
+ }
+}
+
+static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
+{
+ wlc_hw->antsel_avail = antsel_avail;
+}
+
+/*
+ * conditions under which the PM bit should be set in outgoing frames
+ * and STAY_AWAKE is meaningful
+ */
+static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
+{
+ struct brcms_bss_cfg *cfg = wlc->bsscfg;
+
+ /* disallow PS when one of the following global conditions meets */
+ if (!wlc->pub->associated)
+ return false;
+
+ /* disallow PS when one of these meets when not scanning */
+ if (wlc->monitor)
+ return false;
+
+ if (cfg->associated) {
+ /*
+ * disallow PS when one of the following
+ * bsscfg specific conditions meets
+ */
+ if (!cfg->BSS)
+ return false;
+
+ return false;
+ }
+
+ return true;
+}
+
+static void brcms_c_statsupd(struct brcms_c_info *wlc)
+{
+ int i;
+ struct macstat macstats;
+#ifdef BCMDBG
+ u16 delta;
+ u16 rxf0ovfl;
+ u16 txfunfl[NFIFO];
+#endif /* BCMDBG */
+
+ /* if driver down, make no sense to update stats */
+ if (!wlc->pub->up)
+ return;
+
+#ifdef BCMDBG
+ /* save last rx fifo 0 overflow count */
+ rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
+
+ /* save last tx fifo underflow count */
+ for (i = 0; i < NFIFO; i++)
+ txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
+#endif /* BCMDBG */
+
+ /* Read mac stats from contiguous shared memory */
+ brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats,
+ sizeof(struct macstat), OBJADDR_SHM_SEL);
+
+#ifdef BCMDBG
+ /* check for rx fifo 0 overflow */
+ delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
+ if (delta)
+ wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n",
+ wlc->pub->unit, delta);
+
+ /* check for tx fifo underflows */
+ for (i = 0; i < NFIFO; i++) {
+ delta =
+ (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
+ txfunfl[i]);
+ if (delta)
+ wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!"
+ "\n", wlc->pub->unit, delta, i);
+ }
+#endif /* BCMDBG */
+
+ /* merge counters from dma module */
+ for (i = 0; i < NFIFO; i++) {
+ if (wlc->hw->di[i])
+ dma_counterreset(wlc->hw->di[i]);
+ }
+}
+
+static void brcms_b_reset(struct brcms_hardware *wlc_hw)
+{
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ /* reset the core */
+ if (!brcms_deviceremoved(wlc_hw->wlc))
+ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
+
+ /* purge the dma rings */
+ brcms_c_flushqueues(wlc_hw->wlc);
+}
+
void brcms_c_reset(struct brcms_c_info *wlc)
{
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
@@ -414,207 +3227,675 @@ void brcms_c_reset(struct brcms_c_info *wlc)
brcms_b_reset(wlc->hw);
}
-void brcms_c_fatal_error(struct brcms_c_info *wlc)
-{
- wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n",
- wlc->pub->unit);
- brcms_init(wlc->wl);
-}
-
/* Return the channel the driver should initialize during brcms_c_init.
* the channel may have to be changed from the currently configured channel
* if other configurations are in conflict (bandlocked, 11n mode disabled,
* invalid channel for current country, etc.)
*/
-static chanspec_t brcms_c_init_chanspec(struct brcms_c_info *wlc)
+static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc)
{
- chanspec_t chanspec =
+ u16 chanspec =
1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
WL_CHANSPEC_BAND_2G;
return chanspec;
}
-struct scb global_scb;
-
-static void brcms_c_init_scb(struct brcms_c_info *wlc, struct scb *scb)
+void brcms_c_init_scb(struct scb *scb)
{
int i;
+
+ memset(scb, 0, sizeof(struct scb));
scb->flags = SCB_WMECAP | SCB_HTCAP;
- for (i = 0; i < NUMPRIO; i++)
+ for (i = 0; i < NUMPRIO; i++) {
scb->seqnum[i] = 0;
+ scb->seqctl[i] = 0xFFFF;
+ }
+
+ scb->seqctl_nonqos = 0xFFFF;
+ scb->magic = SCB_MAGIC;
}
-void brcms_c_init(struct brcms_c_info *wlc)
-{
- d11regs_t *regs;
- chanspec_t chanspec;
- int i;
- struct brcms_bss_cfg *bsscfg;
- bool mute = false;
+/* d11 core init
+ * reset PSM
+ * download ucode/PCM
+ * let ucode run to suspended
+ * download ucode inits
+ * config other core registers
+ * init dma
+ */
+static void brcms_b_coreinit(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs;
+ u32 sflags;
+ uint bcnint_us;
+ uint i = 0;
+ bool fifosz_fixup = false;
+ int err = 0;
+ u16 buf[NFIFO];
+ struct wiphy *wiphy = wlc->wiphy;
+ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+ regs = wlc_hw->regs;
- regs = wlc->regs;
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ /* reset PSM */
+ brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
- /* This will happen if a big-hammer was executed. In that case, we want to go back
- * to the channel that we were on and not new channel
+ brcms_ucode_download(wlc_hw);
+ /*
+ * FIFOSZ fixup. driver wants to controls the fifo allocation.
*/
- if (wlc->pub->associated)
- chanspec = wlc->home_chanspec;
- else
- chanspec = brcms_c_init_chanspec(wlc);
+ fifosz_fixup = true;
- brcms_b_init(wlc->hw, chanspec, mute);
+ /* let the PSM run to the suspended state, set mode to BSS STA */
+ W_REG(&regs->macintstatus, -1);
+ brcms_b_mctrl(wlc_hw, ~0,
+ (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
- /* update beacon listen interval */
- brcms_c_bcn_li_upd(wlc);
+ /* wait for ucode to self-suspend after auto-init */
+ SPINWAIT(((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0),
+ 1000 * 1000);
+ if ((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0)
+ wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-"
+ "suspend!\n", wlc_hw->unit);
- /* the world is new again, so is our reported rate */
- brcms_c_reprate_init(wlc);
+ brcms_c_gpio_init(wlc);
- /* write ethernet address to core */
- FOREACH_BSS(wlc, i, bsscfg) {
- brcms_c_set_mac(bsscfg);
- brcms_c_set_bssid(bsscfg);
+ sflags = ai_core_sflags(wlc_hw->sih, 0, 0);
+
+ if (D11REV_IS(wlc_hw->corerev, 23)) {
+ if (BRCMS_ISNPHY(wlc_hw->band))
+ brcms_c_write_inits(wlc_hw, ucode->d11n0initvals16);
+ else
+ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
+ " %d\n", __func__, wlc_hw->unit,
+ wlc_hw->corerev);
+ } else if (D11REV_IS(wlc_hw->corerev, 24)) {
+ if (BRCMS_ISLCNPHY(wlc_hw->band))
+ brcms_c_write_inits(wlc_hw, ucode->d11lcn0initvals24);
+ else
+ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
+ " %d\n", __func__, wlc_hw->unit,
+ wlc_hw->corerev);
+ } else {
+ wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
+ __func__, wlc_hw->unit, wlc_hw->corerev);
+ }
+
+ /* For old ucode, txfifo sizes needs to be modified(increased) */
+ if (fifosz_fixup == true)
+ brcms_b_corerev_fifofixup(wlc_hw);
+
+ /* check txfifo allocations match between ucode and driver */
+ buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0);
+ if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) {
+ i = TX_AC_BE_FIFO;
+ err = -1;
+ }
+ buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1);
+ if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) {
+ i = TX_AC_VI_FIFO;
+ err = -1;
+ }
+ buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2);
+ buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff;
+ buf[TX_AC_BK_FIFO] &= 0xff;
+ if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) {
+ i = TX_AC_BK_FIFO;
+ err = -1;
+ }
+ if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) {
+ i = TX_AC_VO_FIFO;
+ err = -1;
+ }
+ buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3);
+ buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff;
+ buf[TX_BCMC_FIFO] &= 0xff;
+ if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) {
+ i = TX_BCMC_FIFO;
+ err = -1;
+ }
+ if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) {
+ i = TX_ATIM_FIFO;
+ err = -1;
}
+ if (err != 0)
+ wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d"
+ " driver size %d index %d\n", buf[i],
+ wlc_hw->xmtfifo_sz[i], i);
- /* Update tsf_cfprep if associated and up */
- if (wlc->pub->associated) {
- FOREACH_BSS(wlc, i, bsscfg) {
- if (bsscfg->up) {
- u32 bi;
+ /* make sure we can still talk to the mac */
+ WARN_ON(R_REG(&regs->maccontrol) == 0xffffffff);
- /* get beacon period and convert to uS */
- bi = bsscfg->current_bss->beacon_period << 10;
- /*
- * update since init path would reset
- * to default value
- */
- W_REG(&regs->tsf_cfprep,
- (bi << CFPREP_CBI_SHIFT));
+ /* band-specific inits done by wlc_bsinit() */
- /* Update maccontrol PM related bits */
- brcms_c_set_ps_ctrl(wlc);
+ /* Set up frame burst size and antenna swap threshold init values */
+ brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST);
+ brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
- break;
- }
- }
- }
+ /* enable one rx interrupt per received frame */
+ W_REG(&regs->intrcvlazy[0], (1 << IRL_FC_SHIFT));
- brcms_c_bandinit_ordered(wlc, chanspec);
+ /* set the station mode (BSS STA) */
+ brcms_b_mctrl(wlc_hw,
+ (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP),
+ (MCTL_INFRA | MCTL_DISCARD_PMQ));
- brcms_c_init_scb(wlc, &global_scb);
+ /* set up Beacon interval */
+ bcnint_us = 0x8000 << 10;
+ W_REG(&regs->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT));
+ W_REG(&regs->tsf_cfpstart, bcnint_us);
+ W_REG(&regs->macintstatus, MI_GP1);
- /* init probe response timeout */
- brcms_c_write_shm(wlc, M_PRS_MAXTIME, wlc->prb_resp_timeout);
+ /* write interrupt mask */
+ W_REG(&regs->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK);
- /* init max burst txop (framebursting) */
- brcms_c_write_shm(wlc, M_MBURST_TXOP,
- (wlc->
- _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
+ /* allow the MAC to control the PHY clock (dynamic on/off) */
+ brcms_b_macphyclk_set(wlc_hw, ON);
- /* initialize maximum allowed duty cycle */
- brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
- brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
+ /* program dynamic clock control fast powerup delay register */
+ wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih);
+ W_REG(&regs->scc_fastpwrup_dly, wlc->fastpwrup_dly);
- /* Update some shared memory locations related to max AMPDU size allowed to received */
- brcms_c_ampdu_shm_upd(wlc->ampdu);
+ /* tell the ucode the corerev */
+ brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
- /* band-specific inits */
- brcms_c_bsinit(wlc);
+ /* tell the ucode MAC capabilities */
+ brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L,
+ (u16) (wlc_hw->machwcap & 0xffff));
+ brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H,
+ (u16) ((wlc_hw->
+ machwcap >> 16) & 0xffff));
- /* Enable EDCF mode (while the MAC is suspended) */
- if (EDCF_ENAB(wlc->pub)) {
- OR_REG(&regs->ifs_ctl, IFS_USEEDCF);
- brcms_c_edcf_setparams(wlc, false);
- }
+ /* write retry limits to SCR, this done after PSM init */
+ W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+ (void)R_REG(&regs->objaddr);
+ W_REG(&regs->objdata, wlc_hw->SRL);
+ W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+ (void)R_REG(&regs->objaddr);
+ W_REG(&regs->objdata, wlc_hw->LRL);
- /* Init precedence maps for empty FIFOs */
- brcms_c_tx_prec_map_init(wlc);
+ /* write rate fallback retry limits */
+ brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
+ brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
- /* read the ucode version if we have not yet done so */
- if (wlc->ucode_rev == 0) {
- wlc->ucode_rev =
- brcms_c_read_shm(wlc, M_BOM_REV_MAJOR) << NBITS(u16);
- wlc->ucode_rev |= brcms_c_read_shm(wlc, M_BOM_REV_MINOR);
+ AND_REG(&regs->ifs_ctl, 0x0FFF);
+ W_REG(&regs->ifs_aifsn, EDCF_AIFSN_MIN);
+
+ /* init the tx dma engines */
+ for (i = 0; i < NFIFO; i++) {
+ if (wlc_hw->di[i])
+ dma_txinit(wlc_hw->di[i]);
}
- /* ..now really unleash hell (allow the MAC out of suspend) */
- brcms_c_enable_mac(wlc);
+ /* init the rx dma engine(s) and post receive buffers */
+ dma_rxinit(wlc_hw->di[RX_FIFO]);
+ dma_rxfill(wlc_hw->di[RX_FIFO]);
+}
- /* clear tx flow control */
- brcms_c_txflowcontrol_reset(wlc);
+void
+static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec,
+ bool mute) {
+ u32 macintmask;
+ bool fastclk;
+ struct brcms_c_info *wlc = wlc_hw->wlc;
- /* clear tx data fifo suspends */
- wlc->tx_suspended = false;
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
- /* enable the RF Disable Delay timer */
- W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
+ /* request FAST clock if not on */
+ fastclk = wlc_hw->forcefastclk;
+ if (!fastclk)
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
- /* initialize mpc delay */
- wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
+ /* disable interrupts */
+ macintmask = brcms_intrsoff(wlc->wl);
+
+ /* set up the specified band and chanspec */
+ brcms_c_setxband(wlc_hw, chspec_bandunit(chanspec));
+ wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
+
+ /* do one-time phy inits and calibration */
+ wlc_phy_cal_init(wlc_hw->band->pi);
+
+ /* core-specific initialization */
+ brcms_b_coreinit(wlc);
+
+ /* suspend the tx fifos and mute the phy for preism cac time */
+ if (mute)
+ brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM);
+
+ /* band-specific inits */
+ brcms_b_bsinit(wlc, chanspec);
+
+ /* restore macintmask */
+ brcms_intrsrestore(wlc->wl, macintmask);
+
+ /* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac
+ * is suspended and brcms_c_enable_mac() will clear this override bit.
+ */
+ mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
/*
- * Initialize WME parameters; if they haven't been set by some other
- * mechanism (IOVar, etc) then read them from the hardware.
+ * initialize mac_suspend_depth to 1 to match ucode
+ * initial suspended state
*/
- if (BRCMS_WME_RETRY_SHORT_GET(wlc, 0) == 0) {
- /* Uninitialized; read from HW */
- int ac;
+ wlc_hw->mac_suspend_depth = 1;
- for (ac = 0; ac < AC_COUNT; ac++) {
- wlc->wme_retries[ac] =
- brcms_c_read_shm(wlc, M_AC_TXLMT_ADDR(ac));
+ /* restore the clk */
+ if (!fastclk)
+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc,
+ u16 chanspec)
+{
+ /* Save our copy of the chanspec */
+ wlc->chanspec = chanspec;
+
+ /* Set the chanspec and power limits for this locale */
+ brcms_c_channel_set_chanspec(wlc->cmi, chanspec, BRCMS_TXPWR_MAX);
+
+ if (wlc->stf->ss_algosel_auto)
+ brcms_c_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel,
+ chanspec);
+
+ brcms_c_stf_ss_update(wlc, wlc->band);
+}
+
+static void
+brcms_default_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs)
+{
+ brcms_c_rateset_default(rs, NULL, wlc->band->phytype,
+ wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL,
+ (bool) (wlc->pub->_n_enab & SUPPORT_11N),
+ brcms_chspec_bw(wlc->default_bss->chanspec),
+ wlc->stf->txstreams);
+}
+
+/* derive wlc->band->basic_rate[] table from 'rateset' */
+static void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
+ struct brcms_c_rateset *rateset)
+{
+ u8 rate;
+ u8 mandatory;
+ u8 cck_basic = 0;
+ u8 ofdm_basic = 0;
+ u8 *br = wlc->band->basic_rate;
+ uint i;
+
+ /* incoming rates are in 500kbps units as in 802.11 Supported Rates */
+ memset(br, 0, BRCM_MAXRATE + 1);
+
+ /* For each basic rate in the rates list, make an entry in the
+ * best basic lookup.
+ */
+ for (i = 0; i < rateset->count; i++) {
+ /* only make an entry for a basic rate */
+ if (!(rateset->rates[i] & BRCMS_RATE_FLAG))
+ continue;
+
+ /* mask off basic bit */
+ rate = (rateset->rates[i] & BRCMS_RATE_MASK);
+
+ if (rate > BRCM_MAXRATE) {
+ wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: "
+ "invalid rate 0x%X in rate set\n",
+ rateset->rates[i]);
+ continue;
+ }
+
+ br[rate] = rate;
+ }
+
+ /* The rate lookup table now has non-zero entries for each
+ * basic rate, equal to the basic rate: br[basicN] = basicN
+ *
+ * To look up the best basic rate corresponding to any
+ * particular rate, code can use the basic_rate table
+ * like this
+ *
+ * basic_rate = wlc->band->basic_rate[tx_rate]
+ *
+ * Make sure there is a best basic rate entry for
+ * every rate by walking up the table from low rates
+ * to high, filling in holes in the lookup table
+ */
+
+ for (i = 0; i < wlc->band->hw_rateset.count; i++) {
+ rate = wlc->band->hw_rateset.rates[i];
+
+ if (br[rate] != 0) {
+ /* This rate is a basic rate.
+ * Keep track of the best basic rate so far by
+ * modulation type.
+ */
+ if (is_ofdm_rate(rate))
+ ofdm_basic = rate;
+ else
+ cck_basic = rate;
+
+ continue;
}
+
+ /* This rate is not a basic rate so figure out the
+ * best basic rate less than this rate and fill in
+ * the hole in the table
+ */
+
+ br[rate] = is_ofdm_rate(rate) ? ofdm_basic : cck_basic;
+
+ if (br[rate] != 0)
+ continue;
+
+ if (is_ofdm_rate(rate)) {
+ /*
+ * In 11g and 11a, the OFDM mandatory rates
+ * are 6, 12, and 24 Mbps
+ */
+ if (rate >= BRCM_RATE_24M)
+ mandatory = BRCM_RATE_24M;
+ else if (rate >= BRCM_RATE_12M)
+ mandatory = BRCM_RATE_12M;
+ else
+ mandatory = BRCM_RATE_6M;
+ } else {
+ /* In 11b, all CCK rates are mandatory 1 - 11 Mbps */
+ mandatory = rate;
+ }
+
+ br[rate] = mandatory;
}
}
-void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc)
+static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
+ u16 chanspec)
{
- wlc->bcnmisc_monitor = promisc;
- brcms_c_mac_bcn_promisc(wlc);
+ struct brcms_c_rateset default_rateset;
+ uint parkband;
+ uint i, band_order[2];
+
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+ /*
+ * We might have been bandlocked during down and the chip
+ * power-cycled (hibernate). Figure out the right band to park on
+ */
+ if (wlc->bandlocked || wlc->pub->_nbands == 1) {
+ /* updated in brcms_c_bandlock() */
+ parkband = wlc->band->bandunit;
+ band_order[0] = band_order[1] = parkband;
+ } else {
+ /* park on the band of the specified chanspec */
+ parkband = chspec_bandunit(chanspec);
+
+ /* order so that parkband initialize last */
+ band_order[0] = parkband ^ 1;
+ band_order[1] = parkband;
+ }
+
+ /* make each band operational, software state init */
+ for (i = 0; i < wlc->pub->_nbands; i++) {
+ uint j = band_order[i];
+
+ wlc->band = wlc->bandstate[j];
+
+ brcms_default_rateset(wlc, &default_rateset);
+
+ /* fill in hw_rate */
+ brcms_c_rateset_filter(&default_rateset, &wlc->band->hw_rateset,
+ false, BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
+ (bool) (wlc->pub->_n_enab & SUPPORT_11N));
+
+ /* init basic rate lookup */
+ brcms_c_rate_lookup_init(wlc, &default_rateset);
+ }
+
+ /* sync up phy/radio chanspec */
+ brcms_c_set_phy_chanspec(wlc, chanspec);
}
-void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc)
+static void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc)
{
- if ((AP_ENAB(wlc->pub) && (N_ENAB(wlc->pub) || wlc->band->gmode)) ||
- wlc->bcnmisc_ibss || wlc->bcnmisc_scan || wlc->bcnmisc_monitor)
- brcms_c_mctrl(wlc, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC);
+ if (wlc->bcnmisc_monitor)
+ brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC);
else
- brcms_c_mctrl(wlc, MCTL_BCNS_PROMISC, 0);
+ brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, 0);
+}
+
+void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc)
+{
+ wlc->bcnmisc_monitor = promisc;
+ brcms_c_mac_bcn_promisc(wlc);
}
/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */
-void brcms_c_mac_promisc(struct brcms_c_info *wlc)
+static void brcms_c_mac_promisc(struct brcms_c_info *wlc)
{
u32 promisc_bits = 0;
- /* promiscuous mode just sets MCTL_PROMISC
- * Note: APs get all BSS traffic without the need to set the MCTL_PROMISC bit
- * since all BSS data traffic is directed at the AP
+ /*
+ * promiscuous mode just sets MCTL_PROMISC
+ * Note: APs get all BSS traffic without the need to set
+ * the MCTL_PROMISC bit since all BSS data traffic is
+ * directed at the AP
*/
- if (PROMISC_ENAB(wlc->pub) && !AP_ENAB(wlc->pub))
+ if (wlc->pub->promisc)
promisc_bits |= MCTL_PROMISC;
/* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL
* Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is
* handled in brcms_c_mac_bcn_promisc()
*/
- if (MONITOR_ENAB(wlc))
+ if (wlc->monitor)
promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL;
- brcms_c_mctrl(wlc, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits);
+ brcms_b_mctrl(wlc->hw, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits);
+}
+
+/*
+ * ucode, hwmac update
+ * Channel dependent updates for ucode and hw
+ */
+static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc)
+{
+ /* enable or disable any active IBSSs depending on whether or not
+ * we are on the home channel
+ */
+ if (wlc->home_chanspec == wlc_phy_chanspec_get(wlc->band->pi)) {
+ if (wlc->pub->associated) {
+ /*
+ * BMAC_NOTE: This is something that should be fixed
+ * in ucode inits. I think that the ucode inits set
+ * up the bcn templates and shm values with a bogus
+ * beacon. This should not be done in the inits. If
+ * ucode needs to set up a beacon for testing, the
+ * test routines should write it down, not expect the
+ * inits to populate a bogus beacon.
+ */
+ if (BRCMS_PHY_11N_CAP(wlc->band))
+ brcms_b_write_shm(wlc->hw,
+ M_BCN_TXTSF_OFFSET, 0);
+ }
+ } else {
+ /* disable an active IBSS if we are not on the home channel */
+ }
+
+ /* update the various promisc bits */
+ brcms_c_mac_bcn_promisc(wlc);
+ brcms_c_mac_promisc(wlc);
+}
+
+static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate,
+ u8 basic_rate)
+{
+ u8 phy_rate, index;
+ u8 basic_phy_rate, basic_index;
+ u16 dir_table, basic_table;
+ u16 basic_ptr;
+
+ /* Shared memory address for the table we are reading */
+ dir_table = is_ofdm_rate(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
+
+ /* Shared memory address for the table we are writing */
+ basic_table = is_ofdm_rate(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
+
+ /*
+ * for a given rate, the LS-nibble of the PLCP SIGNAL field is
+ * the index into the rate table.
+ */
+ phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
+ basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK;
+ index = phy_rate & 0xf;
+ basic_index = basic_phy_rate & 0xf;
+
+ /* Find the SHM pointer to the ACK rate entry by looking in the
+ * Direct-map Table
+ */
+ basic_ptr = brcms_b_read_shm(wlc->hw, (dir_table + basic_index * 2));
+
+ /* Update the SHM BSS-basic-rate-set mapping table with the pointer
+ * to the correct basic rate for the given incoming rate
+ */
+ brcms_b_write_shm(wlc->hw, (basic_table + index * 2), basic_ptr);
+}
+
+static const struct brcms_c_rateset *
+brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc)
+{
+ const struct brcms_c_rateset *rs_dflt;
+
+ if (BRCMS_PHY_11N_CAP(wlc->band)) {
+ if (wlc->band->bandtype == BRCM_BAND_5G)
+ rs_dflt = &ofdm_mimo_rates;
+ else
+ rs_dflt = &cck_ofdm_mimo_rates;
+ } else if (wlc->band->gmode)
+ rs_dflt = &cck_ofdm_rates;
+ else
+ rs_dflt = &cck_rates;
+
+ return rs_dflt;
+}
+
+static void brcms_c_set_ratetable(struct brcms_c_info *wlc)
+{
+ const struct brcms_c_rateset *rs_dflt;
+ struct brcms_c_rateset rs;
+ u8 rate, basic_rate;
+ uint i;
+
+ rs_dflt = brcms_c_rateset_get_hwrs(wlc);
+
+ brcms_c_rateset_copy(rs_dflt, &rs);
+ brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+
+ /* walk the phy rate table and update SHM basic rate lookup table */
+ for (i = 0; i < rs.count; i++) {
+ rate = rs.rates[i] & BRCMS_RATE_MASK;
+
+ /* for a given rate brcms_basic_rate returns the rate at
+ * which a response ACK/CTS should be sent.
+ */
+ basic_rate = brcms_basic_rate(wlc, rate);
+ if (basic_rate == 0)
+ /* This should only happen if we are using a
+ * restricted rateset.
+ */
+ basic_rate = rs.rates[0] & BRCMS_RATE_MASK;
+
+ brcms_c_write_rate_shm(wlc, rate, basic_rate);
+ }
+}
+
+/* band-specific init */
+static void brcms_c_bsinit(struct brcms_c_info *wlc)
+{
+ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n",
+ wlc->pub->unit, wlc->band->bandunit);
+
+ /* write ucode ACK/CTS rate table */
+ brcms_c_set_ratetable(wlc);
+
+ /* update some band specific mac configuration */
+ brcms_c_ucode_mac_upd(wlc);
+
+ /* init antenna selection */
+ brcms_c_antsel_init(wlc->asi);
+
+}
+
+/* formula: IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */
+static int
+brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM,
+ bool writeToShm)
+{
+ int idle_busy_ratio_x_16 = 0;
+ uint offset =
+ isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM :
+ M_TX_IDLE_BUSY_RATIO_X_16_CCK;
+ if (duty_cycle > 100 || duty_cycle < 0) {
+ wiphy_err(wlc->wiphy, "wl%d: duty cycle value off limit\n",
+ wlc->pub->unit);
+ return -EINVAL;
+ }
+ if (duty_cycle)
+ idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle;
+ /* Only write to shared memory when wl is up */
+ if (writeToShm)
+ brcms_b_write_shm(wlc->hw, offset, (u16) idle_busy_ratio_x_16);
+
+ if (isOFDM)
+ wlc->tx_duty_cycle_ofdm = (u16) duty_cycle;
+ else
+ wlc->tx_duty_cycle_cck = (u16) duty_cycle;
+
+ return 0;
+}
+
+/*
+ * Initialize the base precedence map for dequeueing
+ * from txq based on WME settings
+ */
+static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc)
+{
+ wlc->tx_prec_map = BRCMS_PREC_BMP_ALL;
+ memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16));
+
+ wlc->fifo2prec_map[TX_AC_BK_FIFO] = BRCMS_PREC_BMP_AC_BK;
+ wlc->fifo2prec_map[TX_AC_BE_FIFO] = BRCMS_PREC_BMP_AC_BE;
+ wlc->fifo2prec_map[TX_AC_VI_FIFO] = BRCMS_PREC_BMP_AC_VI;
+ wlc->fifo2prec_map[TX_AC_VO_FIFO] = BRCMS_PREC_BMP_AC_VO;
+}
+
+static void
+brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc,
+ struct brcms_txq_info *qi, bool on, int prio)
+{
+ /* transmit flowcontrol is not yet implemented */
+}
+
+static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc)
+{
+ struct brcms_txq_info *qi;
+
+ for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
+ if (qi->stopped) {
+ brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
+ qi->stopped = 0;
+ }
+ }
}
/* push sw hps and wake state through hardware */
-void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
+static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
{
u32 v1, v2;
bool hps;
bool awake_before;
- hps = PS_ALLOWED(wlc);
+ hps = brcms_c_ps_allowed(wlc);
BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps);
@@ -623,28 +3904,25 @@ void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
if (hps)
v2 |= MCTL_HPS;
- brcms_c_mctrl(wlc, MCTL_WAKE | MCTL_HPS, v2);
+ brcms_b_mctrl(wlc->hw, MCTL_WAKE | MCTL_HPS, v2);
awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0));
if (!awake_before)
brcms_b_wait_for_wake(wlc->hw);
-
}
/*
* Write this BSS config's MAC address to core.
* Updates RXE match engine.
*/
-int brcms_c_set_mac(struct brcms_bss_cfg *cfg)
+static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg)
{
int err = 0;
- struct brcms_c_info *wlc = cfg->wlc;
+ struct brcms_c_info *wlc = bsscfg->wlc;
- if (cfg == wlc->cfg) {
- /* enter the MAC addr into the RXE match registers */
- brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, cfg->cur_etheraddr);
- }
+ /* enter the MAC addr into the RXE match registers */
+ brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, bsscfg->cur_etheraddr);
brcms_c_ampdu_macaddr_upd(wlc);
@@ -654,30 +3932,29 @@ int brcms_c_set_mac(struct brcms_bss_cfg *cfg)
/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl).
* Updates RXE match engine.
*/
-void brcms_c_set_bssid(struct brcms_bss_cfg *cfg)
+static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg)
{
- struct brcms_c_info *wlc = cfg->wlc;
+ /* we need to update BSSID in RXE match registers */
+ brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID);
+}
- /* if primary config, we need to update BSSID in RXE match registers */
- if (cfg == wlc->cfg) {
- brcms_c_set_addrmatch(wlc, RCM_BSSID_OFFSET, cfg->BSSID);
- }
-#ifdef SUPPORT_HWKEYS
- else if (BSSCFG_STA(cfg) && cfg->BSS) {
- brcms_c_rcmta_add_bssid(wlc, cfg);
+static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
+{
+ wlc_hw->shortslot = shortslot;
+
+ if (wlc_hw->band->bandtype == BRCM_BAND_2G && wlc_hw->up) {
+ brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+ brcms_b_update_slot_timing(wlc_hw, shortslot);
+ brcms_c_enable_mac(wlc_hw->wlc);
}
-#endif
}
/*
* Suspend the the MAC and update the slot timing
* for standard 11b/g (20us slots) or shortslot 11g (9us slots).
*/
-void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)
+static void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)
{
- int idx;
- struct brcms_bss_cfg *cfg;
-
/* use the override if it is set */
if (wlc->shortslot_override != BRCMS_SHORTSLOT_AUTO)
shortslot = (wlc->shortslot_override == BRCMS_SHORTSLOT_ON);
@@ -687,91 +3964,84 @@ void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)
wlc->shortslot = shortslot;
- /* update the capability based on current shortslot mode */
- FOREACH_BSS(wlc, idx, cfg) {
- if (!cfg->associated)
- continue;
- cfg->current_bss->capability &=
- ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
- if (wlc->shortslot)
- cfg->current_bss->capability |=
- WLAN_CAPABILITY_SHORT_SLOT_TIME;
- }
-
brcms_b_set_shortslot(wlc->hw, shortslot);
}
-static u8 brcms_c_local_constraint_qdbm(struct brcms_c_info *wlc)
+static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec)
{
- u8 local;
- s16 local_max;
-
- local = BRCMS_TXPWR_MAX;
- if (wlc->pub->associated &&
- (brcmu_chspec_ctlchan(wlc->chanspec) ==
- brcmu_chspec_ctlchan(wlc->home_chanspec))) {
+ if (wlc->home_chanspec != chanspec) {
+ wlc->home_chanspec = chanspec;
- /* get the local power constraint if we are on the AP's
- * channel [802.11h, 7.3.2.13]
- */
- /* Clamp the value between 0 and BRCMS_TXPWR_MAX w/o
- * overflowing the target */
- local_max =
- (wlc->txpwr_local_max -
- wlc->txpwr_local_constraint) * BRCMS_TXPWR_DB_FACTOR;
- if (local_max > 0 && local_max < BRCMS_TXPWR_MAX)
- return (u8) local_max;
- if (local_max < 0)
- return 0;
+ if (wlc->bsscfg->associated)
+ wlc->bsscfg->current_bss->chanspec = chanspec;
}
-
- return local;
}
-/* propagate home chanspec to all bsscfgs in case bsscfg->current_bss->chanspec is referenced */
-void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, chanspec_t chanspec)
+void
+brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
+ bool mute, struct txpwr_limits *txpwr)
{
- if (wlc->home_chanspec != chanspec) {
- int idx;
- struct brcms_bss_cfg *cfg;
+ uint bandunit;
- wlc->home_chanspec = chanspec;
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec);
- FOREACH_BSS(wlc, idx, cfg) {
- if (!cfg->associated)
- continue;
+ wlc_hw->chanspec = chanspec;
- cfg->current_bss->chanspec = chanspec;
+ /* Switch bands if necessary */
+ if (wlc_hw->_nbands > 1) {
+ bandunit = chspec_bandunit(chanspec);
+ if (wlc_hw->band->bandunit != bandunit) {
+ /* brcms_b_setband disables other bandunit,
+ * use light band switch if not up yet
+ */
+ if (wlc_hw->up) {
+ wlc_phy_chanspec_radio_set(wlc_hw->
+ bandstate[bandunit]->
+ pi, chanspec);
+ brcms_b_setband(wlc_hw, bandunit, chanspec);
+ } else {
+ brcms_c_setxband(wlc_hw, bandunit);
+ }
}
+ }
+ wlc_phy_initcal_enable(wlc_hw->band->pi, !mute);
+
+ if (!wlc_hw->up) {
+ if (wlc_hw->clk)
+ wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr,
+ chanspec);
+ wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
+ } else {
+ wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec);
+ wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
+
+ /* Update muting of the channel */
+ brcms_b_mute(wlc_hw, mute, 0);
}
}
-static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc,
- chanspec_t chanspec)
+/* switch to and initialize new band */
+static void brcms_c_setband(struct brcms_c_info *wlc,
+ uint bandunit)
{
- /* Save our copy of the chanspec */
- wlc->chanspec = chanspec;
-
- /* Set the chanspec and power limits for this locale after computing
- * any 11h local tx power constraints.
- */
- brcms_c_channel_set_chanspec(wlc->cmi, chanspec,
- brcms_c_local_constraint_qdbm(wlc));
+ wlc->band = wlc->bandstate[bandunit];
- if (wlc->stf->ss_algosel_auto)
- brcms_c_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel,
- chanspec);
+ if (!wlc->pub->up)
+ return;
- brcms_c_stf_ss_update(wlc, wlc->band);
+ /* wait for at least one beacon before entering sleeping state */
+ brcms_c_set_ps_ctrl(wlc);
+ /* band-specific initializations */
+ brcms_c_bsinit(wlc);
}
-void brcms_c_set_chanspec(struct brcms_c_info *wlc, chanspec_t chanspec)
+static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec)
{
uint bandunit;
bool switchband = false;
- chanspec_t old_chanspec = wlc->chanspec;
+ u16 old_chanspec = wlc->chanspec;
if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) {
wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n",
@@ -780,8 +4050,8 @@ void brcms_c_set_chanspec(struct brcms_c_info *wlc, chanspec_t chanspec)
}
/* Switch bands if necessary */
- if (NBANDS(wlc) > 1) {
- bandunit = CHSPEC_BANDUNIT(chanspec);
+ if (wlc->pub->_nbands > 1) {
+ bandunit = chspec_bandunit(chanspec);
if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) {
switchband = true;
if (wlc->bandlocked) {
@@ -807,53 +4077,28 @@ void brcms_c_set_chanspec(struct brcms_c_info *wlc, chanspec_t chanspec)
brcms_c_set_phy_chanspec(wlc, chanspec);
/* init antenna selection */
- if (CHSPEC_WLC_BW(old_chanspec) != CHSPEC_WLC_BW(chanspec)) {
+ if (brcms_chspec_bw(old_chanspec) != brcms_chspec_bw(chanspec)) {
brcms_c_antsel_init(wlc->asi);
/* Fix the hardware rateset based on bw.
* Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz
*/
brcms_c_rateset_bw_mcs_filter(&wlc->band->hw_rateset,
- wlc->band->
- mimo_cap_40 ? CHSPEC_WLC_BW(chanspec)
- : 0);
+ wlc->band->mimo_cap_40 ? brcms_chspec_bw(chanspec) : 0);
}
/* update some mac configuration since chanspec changed */
brcms_c_ucode_mac_upd(wlc);
}
-ratespec_t brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc,
- wlc_rateset_t *rs)
-{
- ratespec_t lowest_basic_rspec;
- uint i;
-
- /* Use the lowest basic rate */
- lowest_basic_rspec = rs->rates[0] & BRCMS_RATE_MASK;
- for (i = 0; i < rs->count; i++) {
- if (rs->rates[i] & BRCMS_RATE_FLAG) {
- lowest_basic_rspec = rs->rates[i] & BRCMS_RATE_MASK;
- break;
- }
- }
-#if NCONF
- /* pick siso/cdd as default for OFDM (note no basic rate MCSs are supported yet) */
- if (IS_OFDM(lowest_basic_rspec)) {
- lowest_basic_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
- }
-#endif
-
- return lowest_basic_rspec;
-}
-
-/* This function changes the phytxctl for beacon based on current beacon ratespec AND txant
- * setting as per this table:
+/*
+ * This function changes the phytxctl for beacon based on current
+ * beacon ratespec AND txant setting as per this table:
* ratespec CCK ant = wlc->stf->txant
* OFDM ant = 3
*/
void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
- ratespec_t bcn_rspec)
+ u32 bcn_rspec)
{
u16 phyctl;
u16 phytxant = wlc->stf->phytxant;
@@ -863,14 +4108,16 @@ void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
if (BRCMS_PHY_11N_CAP(wlc->band))
phytxant = brcms_c_stf_phytxchain_sel(wlc, bcn_rspec);
- phyctl = brcms_c_read_shm(wlc, M_BCN_PCTLWD);
+ phyctl = brcms_b_read_shm(wlc->hw, M_BCN_PCTLWD);
phyctl = (phyctl & ~mask) | phytxant;
- brcms_c_write_shm(wlc, M_BCN_PCTLWD, phyctl);
+ brcms_b_write_shm(wlc->hw, M_BCN_PCTLWD, phyctl);
}
-/* centralized protection config change function to simplify debugging, no consistency checking
- * this should be called only on changes to avoid overhead in periodic function
-*/
+/*
+ * centralized protection config change function to simplify debugging, no
+ * consistency checking this should be called only on changes to avoid overhead
+ * in periodic function
+ */
void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val)
{
BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val);
@@ -918,13 +4165,6 @@ void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val)
static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val)
{
- wlc->ht_cap.cap_info &= ~(IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40);
- wlc->ht_cap.cap_info |= (val & BRCMS_N_SGI_20) ?
- IEEE80211_HT_CAP_SGI_20 : 0;
- wlc->ht_cap.cap_info |= (val & BRCMS_N_SGI_40) ?
- IEEE80211_HT_CAP_SGI_40 : 0;
-
if (wlc->pub->up) {
brcms_c_update_beacon(wlc);
brcms_c_update_probe_resp(wlc, true);
@@ -935,10 +4175,6 @@ static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val)
{
wlc->stf->ldpc = val;
- wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_LDPC_CODING;
- if (wlc->stf->ldpc != OFF)
- wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_LDPC_CODING;
-
if (wlc->pub->up) {
brcms_c_update_beacon(wlc);
brcms_c_update_probe_resp(wlc, true);
@@ -946,262 +4182,347 @@ static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val)
}
}
-/*
- * ucode, hwmac update
- * Channel dependent updates for ucode and hw
- */
-static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc)
+void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
+ const struct ieee80211_tx_queue_params *params,
+ bool suspend)
{
- /* enable or disable any active IBSSs depending on whether or not
- * we are on the home channel
- */
- if (wlc->home_chanspec == BRCMS_BAND_PI_RADIO_CHANSPEC) {
- if (wlc->pub->associated) {
- /* BMAC_NOTE: This is something that should be fixed in ucode inits.
- * I think that the ucode inits set up the bcn templates and shm values
- * with a bogus beacon. This should not be done in the inits. If ucode needs
- * to set up a beacon for testing, the test routines should write it down,
- * not expect the inits to populate a bogus beacon.
- */
- if (BRCMS_PHY_11N_CAP(wlc->band)) {
- brcms_c_write_shm(wlc, M_BCN_TXTSF_OFFSET,
- wlc->band->bcntsfoff);
- }
- }
- } else {
- /* disable an active IBSS if we are not on the home channel */
+ int i;
+ struct shm_acparams acp_shm;
+ u16 *shm_entry;
+
+ /* Only apply params if the core is out of reset and has clocks */
+ if (!wlc->clk) {
+ wiphy_err(wlc->wiphy, "wl%d: %s : no-clock\n", wlc->pub->unit,
+ __func__);
+ return;
}
- /* update the various promisc bits */
- brcms_c_mac_bcn_promisc(wlc);
- brcms_c_mac_promisc(wlc);
-}
+ memset((char *)&acp_shm, 0, sizeof(struct shm_acparams));
+ /* fill in shm ac params struct */
+ acp_shm.txop = params->txop;
+ /* convert from units of 32us to us for ucode */
+ wlc->edcf_txop[aci & 0x3] = acp_shm.txop =
+ EDCF_TXOP2USEC(acp_shm.txop);
+ acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK);
-static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
- chanspec_t chanspec)
-{
- wlc_rateset_t default_rateset;
- uint parkband;
- uint i, band_order[2];
+ if (aci == AC_VI && acp_shm.txop == 0
+ && acp_shm.aifs < EDCF_AIFSN_MAX)
+ acp_shm.aifs++;
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
- /*
- * We might have been bandlocked during down and the chip power-cycled (hibernate).
- * figure out the right band to park on
- */
- if (wlc->bandlocked || NBANDS(wlc) == 1) {
- /* updated in brcms_c_bandlock() */
- parkband = wlc->band->bandunit;
- band_order[0] = band_order[1] = parkband;
+ if (acp_shm.aifs < EDCF_AIFSN_MIN
+ || acp_shm.aifs > EDCF_AIFSN_MAX) {
+ wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad "
+ "aifs %d\n", wlc->pub->unit, acp_shm.aifs);
} else {
- /* park on the band of the specified chanspec */
- parkband = CHSPEC_BANDUNIT(chanspec);
+ acp_shm.cwmin = params->cw_min;
+ acp_shm.cwmax = params->cw_max;
+ acp_shm.cwcur = acp_shm.cwmin;
+ acp_shm.bslots =
+ R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur;
+ acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
+ /* Indicate the new params to the ucode */
+ acp_shm.status = brcms_b_read_shm(wlc->hw, (M_EDCF_QINFO +
+ wme_ac2fifo[aci] *
+ M_EDCF_QLEN +
+ M_EDCF_STATUS_OFF));
+ acp_shm.status |= WME_STATUS_NEWAC;
- /* order so that parkband initialize last */
- band_order[0] = parkband ^ 1;
- band_order[1] = parkband;
+ /* Fill in shm acparam table */
+ shm_entry = (u16 *) &acp_shm;
+ for (i = 0; i < (int)sizeof(struct shm_acparams); i += 2)
+ brcms_b_write_shm(wlc->hw,
+ M_EDCF_QINFO +
+ wme_ac2fifo[aci] * M_EDCF_QLEN + i,
+ *shm_entry++);
}
- /* make each band operational, software state init */
- for (i = 0; i < NBANDS(wlc); i++) {
- uint j = band_order[i];
+ if (suspend) {
+ brcms_c_suspend_mac_and_wait(wlc);
+ brcms_c_enable_mac(wlc);
+ }
+}
- wlc->band = wlc->bandstate[j];
+void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
+{
+ u16 aci;
+ int i_ac;
+ struct ieee80211_tx_queue_params txq_pars;
+ static const struct edcf_acparam default_edcf_acparams[] = {
+ {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA, EDCF_AC_BE_TXOP_STA},
+ {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA, EDCF_AC_BK_TXOP_STA},
+ {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA, EDCF_AC_VI_TXOP_STA},
+ {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA, EDCF_AC_VO_TXOP_STA}
+ }; /* ucode needs these parameters during its initialization */
+ const struct edcf_acparam *edcf_acp = &default_edcf_acparams[0];
- brcms_default_rateset(wlc, &default_rateset);
+ for (i_ac = 0; i_ac < AC_COUNT; i_ac++, edcf_acp++) {
+ /* find out which ac this set of params applies to */
+ aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT;
- /* fill in hw_rate */
- brcms_c_rateset_filter(&default_rateset, &wlc->band->hw_rateset,
- false, BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
- (bool) N_ENAB(wlc->pub));
+ /* fill in shm ac params struct */
+ txq_pars.txop = edcf_acp->TXOP;
+ txq_pars.aifs = edcf_acp->ACI;
- /* init basic rate lookup */
- brcms_c_rate_lookup_init(wlc, &default_rateset);
+ /* CWmin = 2^(ECWmin) - 1 */
+ txq_pars.cw_min = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK);
+ /* CWmax = 2^(ECWmax) - 1 */
+ txq_pars.cw_max = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK)
+ >> EDCF_ECWMAX_SHIFT);
+ brcms_c_wme_setparams(wlc, aci, &txq_pars, suspend);
}
- /* sync up phy/radio chanspec */
- brcms_c_set_phy_chanspec(wlc, chanspec);
+ if (suspend) {
+ brcms_c_suspend_mac_and_wait(wlc);
+ brcms_c_enable_mac(wlc);
+ }
}
-/* band-specific init */
-static void brcms_c_bsinit(struct brcms_c_info *wlc)
+/* maintain LED behavior in down state */
+static void brcms_c_down_led_upd(struct brcms_c_info *wlc)
{
- BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n",
- wlc->pub->unit, wlc->band->bandunit);
+ /*
+ * maintain LEDs while in down state, turn on sbclk if
+ * not available yet. Turn on sbclk if necessary
+ */
+ brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_FLIP);
+ brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_FLIP);
+}
- /* write ucode ACK/CTS rate table */
- brcms_c_set_ratetable(wlc);
+static void brcms_c_radio_monitor_start(struct brcms_c_info *wlc)
+{
+ /* Don't start the timer if HWRADIO feature is disabled */
+ if (wlc->radio_monitor)
+ return;
- /* update some band specific mac configuration */
- brcms_c_ucode_mac_upd(wlc);
+ wlc->radio_monitor = true;
+ brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_RADIO_MON);
+ brcms_add_timer(wlc->radio_timer, TIMER_INTERVAL_RADIOCHK, true);
+}
- /* init antenna selection */
- brcms_c_antsel_init(wlc->asi);
+static void brcms_c_radio_disable(struct brcms_c_info *wlc)
+{
+ if (!wlc->pub->up) {
+ brcms_c_down_led_upd(wlc);
+ return;
+ }
+ brcms_c_radio_monitor_start(wlc);
+ brcms_down(wlc->wl);
}
-/* switch to and initialize new band */
-static void brcms_c_setband(struct brcms_c_info *wlc,
- uint bandunit)
+static void brcms_c_radio_enable(struct brcms_c_info *wlc)
{
- int idx;
- struct brcms_bss_cfg *cfg;
+ if (wlc->pub->up)
+ return;
- wlc->band = wlc->bandstate[bandunit];
+ if (brcms_deviceremoved(wlc))
+ return;
- if (!wlc->pub->up)
+ brcms_up(wlc->wl);
+}
+
+static bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc)
+{
+ if (!wlc->radio_monitor)
+ return true;
+
+ wlc->radio_monitor = false;
+ brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_RADIO_MON);
+ return brcms_del_timer(wlc->radio_timer);
+}
+
+/* read hwdisable state and propagate to wlc flag */
+static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc)
+{
+ if (wlc->pub->hw_off)
return;
- /* wait for at least one beacon before entering sleeping state */
- for (idx = 0; idx < BRCMS_MAXBSSCFG; idx++) {
- cfg = wlc->bsscfg[idx];
- if (cfg && BSSCFG_STA(cfg) && cfg->associated)
- cfg->PMawakebcn = true;
- }
- brcms_c_set_ps_ctrl(wlc);
+ if (brcms_b_radio_read_hwdisabled(wlc->hw))
+ mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
+ else
+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
+}
- /* band-specific initializations */
- brcms_c_bsinit(wlc);
+/*
+ * centralized radio disable/enable function,
+ * invoke radio enable/disable after updating hwradio status
+ */
+static void brcms_c_radio_upd(struct brcms_c_info *wlc)
+{
+ if (wlc->pub->radio_disabled)
+ brcms_c_radio_disable(wlc);
+ else
+ brcms_c_radio_enable(wlc);
}
-/* Initialize a WME Parameter Info Element with default STA parameters from WMM Spec, Table 12 */
-void
-brcms_c_wme_initparams_sta(struct brcms_c_info *wlc, struct wme_param_ie *pe)
-{
- static const struct wme_param_ie stadef = {
- WME_OUI,
- WME_TYPE,
- WME_SUBTYPE_PARAM_IE,
- WME_VER,
- 0,
- 0,
- {
- {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA,
- cpu_to_le16(EDCF_AC_BE_TXOP_STA)},
- {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA,
- cpu_to_le16(EDCF_AC_BK_TXOP_STA)},
- {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA,
- cpu_to_le16(EDCF_AC_VI_TXOP_STA)},
- {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA,
- cpu_to_le16(EDCF_AC_VO_TXOP_STA)}
- }
- };
- memcpy(pe, &stadef, sizeof(*pe));
+/* update hwradio status and return it */
+bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc)
+{
+ brcms_c_radio_hwdisable_upd(wlc);
+
+ return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ?
+ true : false;
}
-void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
- const struct ieee80211_tx_queue_params *params,
- bool suspend)
+/* periodical query hw radio button while driver is "down" */
+static void brcms_c_radio_timer(void *arg)
{
- int i;
- struct shm_acparams acp_shm;
- u16 *shm_entry;
+ struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
- /* Only apply params if the core is out of reset and has clocks */
- if (!wlc->clk) {
- wiphy_err(wlc->wiphy, "wl%d: %s : no-clock\n", wlc->pub->unit,
- __func__);
+ if (brcms_deviceremoved(wlc)) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
+ __func__);
+ brcms_down(wlc->wl);
return;
}
- do {
- memset((char *)&acp_shm, 0, sizeof(struct shm_acparams));
- /* fill in shm ac params struct */
- acp_shm.txop = le16_to_cpu(params->txop);
- /* convert from units of 32us to us for ucode */
- wlc->edcf_txop[aci & 0x3] = acp_shm.txop =
- EDCF_TXOP2USEC(acp_shm.txop);
- acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK);
-
- if (aci == AC_VI && acp_shm.txop == 0
- && acp_shm.aifs < EDCF_AIFSN_MAX)
- acp_shm.aifs++;
-
- if (acp_shm.aifs < EDCF_AIFSN_MIN
- || acp_shm.aifs > EDCF_AIFSN_MAX) {
- wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad "
- "aifs %d\n", wlc->pub->unit, acp_shm.aifs);
- continue;
- }
+ /* cap mpc off count */
+ if (wlc->mpc_offcnt < BRCMS_MPC_MAX_DELAYCNT)
+ wlc->mpc_offcnt++;
- acp_shm.cwmin = params->cw_min;
- acp_shm.cwmax = params->cw_max;
- acp_shm.cwcur = acp_shm.cwmin;
- acp_shm.bslots =
- R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur;
- acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
- /* Indicate the new params to the ucode */
- acp_shm.status = brcms_c_read_shm(wlc, (M_EDCF_QINFO +
- wme_shmemacindex(aci) *
- M_EDCF_QLEN +
- M_EDCF_STATUS_OFF));
- acp_shm.status |= WME_STATUS_NEWAC;
+ brcms_c_radio_hwdisable_upd(wlc);
+ brcms_c_radio_upd(wlc);
+}
- /* Fill in shm acparam table */
- shm_entry = (u16 *) &acp_shm;
- for (i = 0; i < (int)sizeof(struct shm_acparams); i += 2)
- brcms_c_write_shm(wlc,
- M_EDCF_QINFO +
- wme_shmemacindex(aci) * M_EDCF_QLEN + i,
- *shm_entry++);
+/* common low-level watchdog code */
+static void brcms_b_watchdog(void *arg)
+{
+ struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
+ struct brcms_hardware *wlc_hw = wlc->hw;
- } while (0);
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
- if (suspend)
- brcms_c_suspend_mac_and_wait(wlc);
+ if (!wlc_hw->up)
+ return;
- if (suspend)
- brcms_c_enable_mac(wlc);
+ /* increment second count */
+ wlc_hw->now++;
+
+ /* Check for FIFO error interrupts */
+ brcms_b_fifoerrors(wlc_hw);
+ /* make sure RX dma has buffers */
+ dma_rxfill(wlc->hw->di[RX_FIFO]);
+
+ wlc_phy_watchdog(wlc_hw->band->pi);
}
-void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
+static void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc)
{
- u16 aci;
- int i_ac;
- struct edcf_acparam *edcf_acp;
+ bool mpc_radio, radio_state;
- struct ieee80211_tx_queue_params txq_pars;
- struct ieee80211_tx_queue_params *params = &txq_pars;
+ /*
+ * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
+ * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
+ * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
+ * the radio is going down.
+ */
+ if (!wlc->mpc) {
+ if (!wlc->pub->radio_disabled)
+ return;
+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
+ brcms_c_radio_upd(wlc);
+ if (!wlc->pub->radio_disabled)
+ brcms_c_radio_monitor_stop(wlc);
+ return;
+ }
/*
- * AP uses AC params from wme_param_ie_ap.
- * AP advertises AC params from wme_param_ie.
- * STA uses AC params from wme_param_ie.
+ * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in
+ * wlc->pub->radio_disabled to go ON, always call radio_upd
+ * synchronously to go OFF, postpone radio_upd to later when
+ * context is safe(e.g. watchdog)
*/
+ radio_state =
+ (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
+ ON);
+ mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON;
- edcf_acp = (struct edcf_acparam *) &wlc->wme_param_ie.acparam[0];
+ if (radio_state == ON && mpc_radio == OFF)
+ wlc->mpc_delay_off = wlc->mpc_dlycnt;
+ else if (radio_state == OFF && mpc_radio == ON) {
+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
+ brcms_c_radio_upd(wlc);
+ if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD)
+ wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT;
+ else
+ wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
+ }
+ /*
+ * Below logic is meant to capture the transition from mpc off
+ * to mpc on for reasons other than wlc->mpc_delay_off keeping
+ * the mpc off. In that case reset wlc->mpc_delay_off to
+ * wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
+ */
+ if ((wlc->prev_non_delay_mpc == false) &&
+ (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off)
+ wlc->mpc_delay_off = wlc->mpc_dlycnt;
- for (i_ac = 0; i_ac < AC_COUNT; i_ac++, edcf_acp++) {
- /* find out which ac this set of params applies to */
- aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT;
+ wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc);
+}
- /* fill in shm ac params struct */
- params->txop = edcf_acp->TXOP;
- params->aifs = edcf_acp->ACI;
+/* common watchdog code */
+static void brcms_c_watchdog(void *arg)
+{
+ struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
- /* CWmin = 2^(ECWmin) - 1 */
- params->cw_min = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK);
- /* CWmax = 2^(ECWmax) - 1 */
- params->cw_max = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK)
- >> EDCF_ECWMAX_SHIFT);
- brcms_c_wme_setparams(wlc, aci, params, suspend);
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+ if (!wlc->pub->up)
+ return;
+
+ if (brcms_deviceremoved(wlc)) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
+ __func__);
+ brcms_down(wlc->wl);
+ return;
}
- if (suspend)
- brcms_c_suspend_mac_and_wait(wlc);
+ /* increment second count */
+ wlc->pub->now++;
- if (AP_ENAB(wlc->pub) && WME_ENAB(wlc->pub)) {
- brcms_c_update_beacon(wlc);
- brcms_c_update_probe_resp(wlc, false);
+ /* delay radio disable */
+ if (wlc->mpc_delay_off) {
+ if (--wlc->mpc_delay_off == 0) {
+ mboolset(wlc->pub->radio_disabled,
+ WL_RADIO_MPC_DISABLE);
+ if (wlc->mpc && brcms_c_ismpc(wlc))
+ wlc->mpc_offcnt = 0;
+ }
}
- if (suspend)
- brcms_c_enable_mac(wlc);
+ /* mpc sync */
+ brcms_c_radio_mpc_upd(wlc);
+ /* radio sync: sw/hw/mpc --> radio_disable/radio_enable */
+ brcms_c_radio_hwdisable_upd(wlc);
+ brcms_c_radio_upd(wlc);
+ /* if radio is disable, driver may be down, quit here */
+ if (wlc->pub->radio_disabled)
+ return;
+
+ brcms_b_watchdog(wlc);
+
+ /*
+ * occasionally sample mac stat counters to
+ * detect 16-bit counter wrap
+ */
+ if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0)
+ brcms_c_statsupd(wlc);
+ if (BRCMS_ISNPHY(wlc->band) &&
+ ((wlc->pub->now - wlc->tempsense_lasttime) >=
+ BRCMS_TEMPSENSE_PERIOD)) {
+ wlc->tempsense_lasttime = wlc->pub->now;
+ brcms_c_tempsense_upd(wlc);
+ }
+}
+
+static void brcms_c_watchdog_by_timer(void *arg)
+{
+ brcms_c_watchdog(arg);
}
-bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
+static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
{
wlc->wdtimer = brcms_init_timer(wlc->wl, brcms_c_watchdog_by_timer,
wlc, "watchdog");
@@ -1229,14 +4550,12 @@ bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
* Initialize brcms_c_info default values ...
* may get overrides later in this function
*/
-void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
+static void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
{
int i;
- /* Assume the device is there until proven otherwise */
- wlc->device_present = true;
/* Save our copy of the chanspec */
- wlc->chanspec = CH20MHZ_CHSPEC(1);
+ wlc->chanspec = ch20mhz_chspec(1);
/* various 802.11g modes */
wlc->shortslot = false;
@@ -1277,44 +4596,14 @@ void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
wlc->SRL = RETRY_SHORT_DEF;
wlc->LRL = RETRY_LONG_DEF;
- /* Set flag to indicate that hw keys should be used when available. */
- wlc->wsec_swkeys = false;
-
- /* init the 4 static WEP default keys */
- for (i = 0; i < WSEC_MAX_DEFAULT_KEYS; i++) {
- wlc->wsec_keys[i] = wlc->wsec_def_keys[i];
- wlc->wsec_keys[i]->idx = (u8) i;
- }
-
/* WME QoS mode is Auto by default */
- wlc->pub->_wme = AUTO;
-
-#ifdef BCMSDIODEV_ENABLED
- wlc->pub->_priofc = true; /* enable priority flow control for sdio dongle */
-#endif
-
wlc->pub->_ampdu = AMPDU_AGG_HOST;
wlc->pub->bcmerror = 0;
- wlc->pub->_coex = ON;
/* initialize mpc delay */
wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
}
-static bool brcms_c_state_bmac_sync(struct brcms_c_info *wlc)
-{
- struct brcms_b_state state_bmac;
-
- if (brcms_b_state_get(wlc->hw, &state_bmac) != 0)
- return false;
-
- wlc->machwcap = state_bmac.machwcap;
- brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR,
- (s8) state_bmac.preamble_ovr);
-
- return true;
-}
-
static uint brcms_c_attach_module(struct brcms_c_info *wlc)
{
uint err = 0;
@@ -1347,262 +4636,325 @@ static uint brcms_c_attach_module(struct brcms_c_info *wlc)
return err;
}
-struct brcms_pub *brcms_c_pub(void *wlc)
+struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc)
{
- return ((struct brcms_c_info *) wlc)->pub;
+ return wlc->pub;
}
-#define CHIP_SUPPORTS_11N(wlc) 1
-
-/*
- * The common driver entry routine. Error codes should be unique
+/* low level attach
+ * run backplane attach, init nvram
+ * run phy attach
+ * initialize software state for each core and band
+ * put the whole chip in reset(driver down state), no clock
*/
-void *brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
- bool piomode, void *regsva, uint bustype, void *btparam,
- uint *perr)
+static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
+ uint unit, bool piomode, void __iomem *regsva,
+ struct pci_dev *btparam)
{
- struct brcms_c_info *wlc;
+ struct brcms_hardware *wlc_hw;
+ struct d11regs __iomem *regs;
+ char *macaddr = NULL;
uint err = 0;
uint j;
- struct brcms_pub *pub;
- uint n_disabled;
+ bool wme = false;
+ struct shared_phy_params sha_params;
+ struct wiphy *wiphy = wlc->wiphy;
- /* allocate struct brcms_c_info state and its substructures */
- wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device);
- if (wlc == NULL)
- goto fail;
- wlc->wiphy = wl->wiphy;
- pub = wlc->pub;
+ BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor,
+ device);
-#if defined(BCMDBG)
- wlc_info_dbg = wlc;
-#endif
+ wme = true;
- wlc->band = wlc->bandstate[0];
- wlc->core = wlc->corestate;
- wlc->wl = wl;
- pub->unit = unit;
- pub->_piomode = piomode;
- wlc->bandinit_pending = false;
+ wlc_hw = wlc->hw;
+ wlc_hw->wlc = wlc;
+ wlc_hw->unit = unit;
+ wlc_hw->band = wlc_hw->bandstate[0];
+ wlc_hw->_piomode = piomode;
- /* populate struct brcms_c_info with default values */
- brcms_c_info_init(wlc, unit);
-
- /* update sta/ap related parameters */
- brcms_c_ap_upd(wlc);
-
- /* 11n_disable nvram */
- n_disabled = getintvar(pub->vars, "11n_disable");
+ /* populate struct brcms_hardware with default values */
+ brcms_b_info_init(wlc_hw);
/*
- * low level attach steps(all hw accesses go
- * inside, no more in rest of the attach)
- */
- err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva,
- bustype, btparam);
- if (err)
- goto fail;
-
- /* for some states, due to different info pointer(e,g, wlc, wlc_hw) or master/slave split,
- * HIGH driver(both monolithic and HIGH_ONLY) needs to sync states FROM BMAC portion driver
+ * Do the hardware portion of the attach. Also initialize software
+ * state that depends on the particular hardware we are running.
*/
- if (!brcms_c_state_bmac_sync(wlc)) {
- err = 20;
+ wlc_hw->sih = ai_attach(regsva, btparam);
+ if (wlc_hw->sih == NULL) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n",
+ unit);
+ err = 11;
goto fail;
}
- pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band);
-
- /* propagate *vars* from BMAC driver to high driver */
- brcms_b_copyfrom_vars(wlc->hw, &pub->vars, &wlc->vars_size);
-
-
- /* set maximum allowed duty cycle */
- wlc->tx_duty_cycle_ofdm =
- (u16) getintvar(pub->vars, "tx_duty_cycle_ofdm");
- wlc->tx_duty_cycle_cck =
- (u16) getintvar(pub->vars, "tx_duty_cycle_cck");
-
- brcms_c_stf_phy_chain_calc(wlc);
-
- /* txchain 1: txant 0, txchain 2: txant 1 */
- if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
- wlc->stf->txant = wlc->stf->hw_txchain - 1;
-
- /* push to BMAC driver */
- wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
- wlc->stf->hw_rxchain);
-
- /* pull up some info resulting from the low attach */
- {
- int i;
- for (i = 0; i < NFIFO; i++)
- wlc->core->txavail[i] = wlc->hw->txavail[i];
+ /* verify again the device is supported */
+ if (!brcms_c_chipmatch(vendor, device)) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported "
+ "vendor/device (0x%x/0x%x)\n",
+ unit, vendor, device);
+ err = 12;
+ goto fail;
}
- brcms_b_hw_etheraddr(wlc->hw, wlc->perm_etheraddr);
-
- memcpy(&pub->cur_etheraddr, &wlc->perm_etheraddr, ETH_ALEN);
-
- for (j = 0; j < NBANDS(wlc); j++) {
- /* Use band 1 for single band 11a */
- if (IS_SINGLEBAND_5G(wlc->deviceid))
- j = BAND_5G_INDEX;
-
- wlc->band = wlc->bandstate[j];
-
- if (!brcms_c_attach_stf_ant_init(wlc)) {
- err = 24;
- goto fail;
- }
+ wlc_hw->vendorid = vendor;
+ wlc_hw->deviceid = device;
- /* default contention windows size limits */
- wlc->band->CWmin = APHY_CWMIN;
- wlc->band->CWmax = PHY_CWMAX;
+ /* set bar0 window to point at D11 core */
+ wlc_hw->regs = (struct d11regs __iomem *)
+ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
+ wlc_hw->corerev = ai_corerev(wlc_hw->sih);
- /* init gmode value */
- if (BAND_2G(wlc->band->bandtype)) {
- wlc->band->gmode = GMODE_AUTO;
- brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER,
- wlc->band->gmode);
- }
+ regs = wlc_hw->regs;
- /* init _n_enab supported mode */
- if (BRCMS_PHY_11N_CAP(wlc->band) && CHIP_SUPPORTS_11N(wlc)) {
- if (n_disabled & WLFEATURE_DISABLE_11N) {
- pub->_n_enab = OFF;
- brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
- OFF);
- } else {
- pub->_n_enab = SUPPORT_11N;
- brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
- ((pub->_n_enab ==
- SUPPORT_11N) ? WL_11N_2x2 :
- WL_11N_3x3));
- }
- }
+ wlc->regs = wlc_hw->regs;
- /* init per-band default rateset, depend on band->gmode */
- brcms_default_rateset(wlc, &wlc->band->defrateset);
-
- /* fill in hw_rateset (used early by BRCM_SET_RATESET) */
- brcms_c_rateset_filter(&wlc->band->defrateset,
- &wlc->band->hw_rateset, false,
- BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
- (bool) N_ENAB(wlc->pub));
+ /* validate chip, chiprev and corerev */
+ if (!brcms_c_isgoodchip(wlc_hw)) {
+ err = 13;
+ goto fail;
}
- /* update antenna config due to wlc->stf->txant/txchain/ant_rx_ovr change */
- brcms_c_stf_phy_txant_upd(wlc);
+ /* initialize power control registers */
+ ai_clkctl_init(wlc_hw->sih);
- /* attach each modules */
- err = brcms_c_attach_module(wlc);
- if (err != 0)
- goto fail;
+ /* request fastclock and force fastclock for the rest of attach
+ * bring the d11 core out of reset.
+ * For PMU chips, the first wlc_clkctl_clk is no-op since core-clk
+ * is still false; But it will be called again inside wlc_corereset,
+ * after d11 is out of reset.
+ */
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
- if (!brcms_c_timers_init(wlc, unit)) {
- wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit,
- __func__);
- err = 32;
+ if (!brcms_b_validate_chip_access(wlc_hw)) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access "
+ "failed\n", unit);
+ err = 14;
goto fail;
}
- /* depend on rateset, gmode */
- wlc->cmi = brcms_c_channel_mgr_attach(wlc);
- if (!wlc->cmi) {
- wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed"
- "\n", unit, __func__);
- err = 33;
+ /* get the board rev, used just below */
+ j = getintvar(wlc_hw->sih, BRCMS_SROM_BOARDREV);
+ /* promote srom boardrev of 0xFF to 1 */
+ if (j == BOARDREV_PROMOTABLE)
+ j = BOARDREV_PROMOTED;
+ wlc_hw->boardrev = (u16) j;
+ if (!brcms_c_validboardtype(wlc_hw)) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom "
+ "board type (0x%x)" " or revision level (0x%x)\n",
+ unit, wlc_hw->sih->boardtype, wlc_hw->boardrev);
+ err = 15;
goto fail;
}
+ wlc_hw->sromrev = (u8) getintvar(wlc_hw->sih, BRCMS_SROM_REV);
+ wlc_hw->boardflags = (u32) getintvar(wlc_hw->sih,
+ BRCMS_SROM_BOARDFLAGS);
+ wlc_hw->boardflags2 = (u32) getintvar(wlc_hw->sih,
+ BRCMS_SROM_BOARDFLAGS2);
- /* init default when all parameters are ready, i.e. ->rateset */
- brcms_c_bss_default_init(wlc);
+ if (wlc_hw->boardflags & BFL_NOPLLDOWN)
+ brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED);
- /*
- * Complete the wlc default state initializations..
+ /* check device id(srom, nvram etc.) to set bands */
+ if (wlc_hw->deviceid == BCM43224_D11N_ID ||
+ wlc_hw->deviceid == BCM43224_D11N_ID_VEN1)
+ /* Dualband boards */
+ wlc_hw->_nbands = 2;
+ else
+ wlc_hw->_nbands = 1;
+
+ if ((wlc_hw->sih->chip == BCM43225_CHIP_ID))
+ wlc_hw->_nbands = 1;
+
+ /* BMAC_NOTE: remove init of pub values when brcms_c_attach()
+ * unconditionally does the init of these values
*/
+ wlc->vendorid = wlc_hw->vendorid;
+ wlc->deviceid = wlc_hw->deviceid;
+ wlc->pub->sih = wlc_hw->sih;
+ wlc->pub->corerev = wlc_hw->corerev;
+ wlc->pub->sromrev = wlc_hw->sromrev;
+ wlc->pub->boardrev = wlc_hw->boardrev;
+ wlc->pub->boardflags = wlc_hw->boardflags;
+ wlc->pub->boardflags2 = wlc_hw->boardflags2;
+ wlc->pub->_nbands = wlc_hw->_nbands;
+
+ wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc);
+
+ if (wlc_hw->physhim == NULL) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach "
+ "failed\n", unit);
+ err = 25;
+ goto fail;
+ }
- /* allocate our initial queue */
- wlc->pkt_queue = brcms_c_txq_alloc(wlc);
- if (wlc->pkt_queue == NULL) {
- wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n",
- unit, __func__);
- err = 100;
+ /* pass all the parameters to wlc_phy_shared_attach in one struct */
+ sha_params.sih = wlc_hw->sih;
+ sha_params.physhim = wlc_hw->physhim;
+ sha_params.unit = unit;
+ sha_params.corerev = wlc_hw->corerev;
+ sha_params.vid = wlc_hw->vendorid;
+ sha_params.did = wlc_hw->deviceid;
+ sha_params.chip = wlc_hw->sih->chip;
+ sha_params.chiprev = wlc_hw->sih->chiprev;
+ sha_params.chippkg = wlc_hw->sih->chippkg;
+ sha_params.sromrev = wlc_hw->sromrev;
+ sha_params.boardtype = wlc_hw->sih->boardtype;
+ sha_params.boardrev = wlc_hw->boardrev;
+ sha_params.boardvendor = wlc_hw->sih->boardvendor;
+ sha_params.boardflags = wlc_hw->boardflags;
+ sha_params.boardflags2 = wlc_hw->boardflags2;
+ sha_params.buscorerev = wlc_hw->sih->buscorerev;
+
+ /* alloc and save pointer to shared phy state area */
+ wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
+ if (!wlc_hw->phy_sh) {
+ err = 16;
goto fail;
}
- wlc->bsscfg[0] = wlc->cfg;
- wlc->cfg->_idx = 0;
- wlc->cfg->wlc = wlc;
- pub->txmaxpkts = MAXTXPKTS;
+ /* initialize software state for each core and band */
+ for (j = 0; j < wlc_hw->_nbands; j++) {
+ /*
+ * band0 is always 2.4Ghz
+ * band1, if present, is 5Ghz
+ */
- brcms_c_wme_initparams_sta(wlc, &wlc->wme_param_ie);
+ brcms_c_setxband(wlc_hw, j);
+
+ wlc_hw->band->bandunit = j;
+ wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
+ wlc->band->bandunit = j;
+ wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
+ wlc->core->coreidx = ai_coreidx(wlc_hw->sih);
+
+ wlc_hw->machwcap = R_REG(&regs->machwcap);
+ wlc_hw->machwcap_backup = wlc_hw->machwcap;
+
+ /* init tx fifo size */
+ wlc_hw->xmtfifo_sz =
+ xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
+
+ /* Get a phy for this band */
+ wlc_hw->band->pi =
+ wlc_phy_attach(wlc_hw->phy_sh, regs,
+ wlc_hw->band->bandtype,
+ wlc->wiphy);
+ if (wlc_hw->band->pi == NULL) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_"
+ "attach failed\n", unit);
+ err = 17;
+ goto fail;
+ }
- wlc->mimoft = FT_HT;
- wlc->ht_cap.cap_info = HT_CAP;
- if (HT_ENAB(wlc->pub))
- wlc->stf->ldpc = AUTO;
+ wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap);
+
+ wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype,
+ &wlc_hw->band->phyrev,
+ &wlc_hw->band->radioid,
+ &wlc_hw->band->radiorev);
+ wlc_hw->band->abgphy_encore =
+ wlc_phy_get_encore(wlc_hw->band->pi);
+ wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi);
+ wlc_hw->band->core_flags =
+ wlc_phy_get_coreflags(wlc_hw->band->pi);
+
+ /* verify good phy_type & supported phy revision */
+ if (BRCMS_ISNPHY(wlc_hw->band)) {
+ if (NCONF_HAS(wlc_hw->band->phyrev))
+ goto good_phy;
+ else
+ goto bad_phy;
+ } else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+ if (LCNCONF_HAS(wlc_hw->band->phyrev))
+ goto good_phy;
+ else
+ goto bad_phy;
+ } else {
+ bad_phy:
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported "
+ "phy type/rev (%d/%d)\n", unit,
+ wlc_hw->band->phytype, wlc_hw->band->phyrev);
+ err = 18;
+ goto fail;
+ }
- wlc->mimo_40txbw = AUTO;
- wlc->ofdm_40txbw = AUTO;
- wlc->cck_40txbw = AUTO;
- brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G);
+ good_phy:
+ /*
+ * BMAC_NOTE: wlc->band->pi should not be set below and should
+ * be done in the high level attach. However we can not make
+ * that change until all low level access is changed to
+ * wlc_hw->band->pi. Instead do the wlc->band->pi init below,
+ * keeping wlc_hw->band->pi as well for incremental update of
+ * low level fns, and cut over low only init when all fns
+ * updated.
+ */
+ wlc->band->pi = wlc_hw->band->pi;
+ wlc->band->phytype = wlc_hw->band->phytype;
+ wlc->band->phyrev = wlc_hw->band->phyrev;
+ wlc->band->radioid = wlc_hw->band->radioid;
+ wlc->band->radiorev = wlc_hw->band->radiorev;
- /* Set default values of SGI */
- if (BRCMS_SGI_CAP_PHY(wlc)) {
- brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
- BRCMS_N_SGI_40));
- wlc->sgi_tx = AUTO;
- } else if (BRCMS_ISSSLPNPHY(wlc->band)) {
- brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
- BRCMS_N_SGI_40));
- wlc->sgi_tx = AUTO;
- } else {
- brcms_c_ht_update_sgi_rx(wlc, 0);
- wlc->sgi_tx = OFF;
+ /* default contention windows size limits */
+ wlc_hw->band->CWmin = APHY_CWMIN;
+ wlc_hw->band->CWmax = PHY_CWMAX;
+
+ if (!brcms_b_attach_dmapio(wlc, j, wme)) {
+ err = 19;
+ goto fail;
+ }
}
- /* *******nvram 11n config overrides Start ********* */
+ /* disable core to match driver "down" state */
+ brcms_c_coredisable(wlc_hw);
- /* apply the sgi override from nvram conf */
- if (n_disabled & WLFEATURE_DISABLE_11N_SGI_TX)
- wlc->sgi_tx = OFF;
+ /* Match driver "down" state */
+ ai_pci_down(wlc_hw->sih);
- if (n_disabled & WLFEATURE_DISABLE_11N_SGI_RX)
- brcms_c_ht_update_sgi_rx(wlc, 0);
+ /* register sb interrupt callback functions */
+ ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff,
+ (void *)brcms_c_wlintrsrestore, NULL, wlc);
- /* apply the stbc override from nvram conf */
- if (n_disabled & WLFEATURE_DISABLE_11N_STBC_TX) {
- wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
- wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
- wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
- }
- if (n_disabled & WLFEATURE_DISABLE_11N_STBC_RX)
- brcms_c_stf_stbc_rx_set(wlc, HT_CAP_RX_STBC_NO);
+ /* turn off pll and xtal to match driver "down" state */
+ brcms_b_xtal(wlc_hw, OFF);
- /* apply the GF override from nvram conf */
- if (n_disabled & WLFEATURE_DISABLE_11N_GF)
- wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_GRN_FLD;
+ /* *******************************************************************
+ * The hardware is in the DOWN state at this point. D11 core
+ * or cores are in reset with clocks off, and the board PLLs
+ * are off if possible.
+ *
+ * Beyond this point, wlc->sbclk == false and chip registers
+ * should not be touched.
+ *********************************************************************
+ */
- /* initialize radio_mpc_disable according to wlc->mpc */
- brcms_c_radio_mpc_upd(wlc);
- brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail);
+ /* init etheraddr state variables */
+ macaddr = brcms_c_get_macaddr(wlc_hw);
+ if (macaddr == NULL) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n",
+ unit);
+ err = 21;
+ goto fail;
+ }
+ if (!mac_pton(macaddr, wlc_hw->etheraddr) ||
+ is_broadcast_ether_addr(wlc_hw->etheraddr) ||
+ is_zero_ether_addr(wlc_hw->etheraddr)) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n",
+ unit, macaddr);
+ err = 22;
+ goto fail;
+ }
- if (perr)
- *perr = 0;
+ BCMMSG(wlc->wiphy,
+ "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
+ wlc_hw->deviceid, wlc_hw->_nbands,
+ wlc_hw->sih->boardtype, macaddr);
- return (void *)wlc;
+ return err;
fail:
- wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n",
- unit, __func__, err);
- if (wlc)
- brcms_c_detach(wlc);
-
- if (perr)
- *perr = err;
- return NULL;
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit,
+ err);
+ return err;
}
static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc)
@@ -1620,14 +4972,17 @@ static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc)
} else {
s8 gain, fract;
/* Older sroms specified gain in whole dbm only. In order
- * be able to specify qdbm granularity and remain backward compatible
- * the whole dbms are now encoded in only low 6 bits and remaining qdbms
- * are encoded in the hi 2 bits. 6 bit signed number ranges from
- * -32 - 31. Examples: 0x1 = 1 db,
+ * be able to specify qdbm granularity and remain backward
+ * compatible the whole dbms are now encoded in only
+ * low 6 bits and remaining qdbms are encoded in the hi 2 bits.
+ * 6 bit signed number ranges from -32 - 31.
+ *
+ * Examples:
+ * 0x1 = 1 db,
* 0xc1 = 1.75 db (1 + 3 quarters),
* 0x3f = -1 (-1 + 0 quarters),
- * 0x7f = -.75 (-1 in low 6 bits + 1 quarters in hi 2 bits) = -3 qdbm.
- * 0xbf = -.50 (-1 in low 6 bits + 2 quarters in hi 2 bits) = -2 qdbm.
+ * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm.
+ * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm.
*/
gain = wlc->band->antgain & 0x3f;
gain <<= 2; /* Sign extend */
@@ -1641,18 +4996,18 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
{
int aa;
uint unit;
- char *vars;
int bandtype;
+ struct si_pub *sih = wlc->hw->sih;
unit = wlc->pub->unit;
- vars = wlc->pub->vars;
bandtype = wlc->band->bandtype;
/* get antennas available */
- aa = (s8) getintvar(vars, (BAND_5G(bandtype) ? "aa5g" : "aa2g"));
- if (aa == 0)
- aa = (s8) getintvar(vars,
- (BAND_5G(bandtype) ? "aa1" : "aa0"));
+ if (bandtype == BRCM_BAND_5G)
+ aa = (s8) getintvar(sih, BRCMS_SROM_AA5G);
+ else
+ aa = (s8) getintvar(sih, BRCMS_SROM_AA2G);
+
if ((aa < 1) || (aa > 15)) {
wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
" srom (0x%x), using 3\n", unit, __func__, aa);
@@ -1670,23 +5025,129 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
}
/* Compute Antenna Gain */
- wlc->band->antgain =
- (s8) getintvar(vars, (BAND_5G(bandtype) ? "ag1" : "ag0"));
+ if (bandtype == BRCM_BAND_5G)
+ wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG1);
+ else
+ wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG0);
+
brcms_c_attach_antgain_init(wlc);
return true;
}
+static void brcms_c_bss_default_init(struct brcms_c_info *wlc)
+{
+ u16 chanspec;
+ struct brcms_band *band;
+ struct brcms_bss_info *bi = wlc->default_bss;
+
+ /* init default and target BSS with some sane initial values */
+ memset((char *)(bi), 0, sizeof(struct brcms_bss_info));
+ bi->beacon_period = BEACON_INTERVAL_DEFAULT;
+
+ /* fill the default channel as the first valid channel
+ * starting from the 2G channels
+ */
+ chanspec = ch20mhz_chspec(1);
+ wlc->home_chanspec = bi->chanspec = chanspec;
+
+ /* find the band of our default channel */
+ band = wlc->band;
+ if (wlc->pub->_nbands > 1 &&
+ band->bandunit != chspec_bandunit(chanspec))
+ band = wlc->bandstate[OTHERBANDUNIT(wlc)];
+
+ /* init bss rates to the band specific default rate set */
+ brcms_c_rateset_default(&bi->rateset, NULL, band->phytype,
+ band->bandtype, false, BRCMS_RATE_MASK_FULL,
+ (bool) (wlc->pub->_n_enab & SUPPORT_11N),
+ brcms_chspec_bw(chanspec), wlc->stf->txstreams);
+
+ if (wlc->pub->_n_enab & SUPPORT_11N)
+ bi->flags |= BRCMS_BSS_HT;
+}
+
+static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc)
+{
+ struct brcms_txq_info *qi, *p;
+
+ qi = kzalloc(sizeof(struct brcms_txq_info), GFP_ATOMIC);
+ if (qi != NULL) {
+ /*
+ * Have enough room for control packets along with HI watermark
+ * Also, add room to txq for total psq packets if all the SCBs
+ * leave PS mode. The watermark for flowcontrol to OS packets
+ * will remain the same
+ */
+ brcmu_pktq_init(&qi->q, BRCMS_PREC_COUNT,
+ 2 * BRCMS_DATAHIWAT + PKTQ_LEN_DEFAULT);
+
+ /* add this queue to the the global list */
+ p = wlc->tx_queues;
+ if (p == NULL) {
+ wlc->tx_queues = qi;
+ } else {
+ while (p->next != NULL)
+ p = p->next;
+ p->next = qi;
+ }
+ }
+ return qi;
+}
+
+static void brcms_c_txq_free(struct brcms_c_info *wlc,
+ struct brcms_txq_info *qi)
+{
+ struct brcms_txq_info *p;
+
+ if (qi == NULL)
+ return;
+
+ /* remove the queue from the linked list */
+ p = wlc->tx_queues;
+ if (p == qi)
+ wlc->tx_queues = p->next;
+ else {
+ while (p != NULL && p->next != qi)
+ p = p->next;
+ if (p != NULL)
+ p->next = p->next->next;
+ }
+
+ kfree(qi);
+}
+
+static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap)
+{
+ uint i;
+ struct brcms_band *band;
+
+ for (i = 0; i < wlc->pub->_nbands; i++) {
+ band = wlc->bandstate[i];
+ if (band->bandtype == BRCM_BAND_5G) {
+ if ((bwcap == BRCMS_N_BW_40ALL)
+ || (bwcap == BRCMS_N_BW_20IN2G_40IN5G))
+ band->mimo_cap_40 = true;
+ else
+ band->mimo_cap_40 = false;
+ } else {
+ if (bwcap == BRCMS_N_BW_40ALL)
+ band->mimo_cap_40 = true;
+ else
+ band->mimo_cap_40 = false;
+ }
+ }
+}
static void brcms_c_timers_deinit(struct brcms_c_info *wlc)
{
/* free timer state */
if (wlc->wdtimer) {
- brcms_free_timer(wlc->wl, wlc->wdtimer);
+ brcms_free_timer(wlc->wdtimer);
wlc->wdtimer = NULL;
}
if (wlc->radio_timer) {
- brcms_free_timer(wlc->wl, wlc->radio_timer);
+ brcms_free_timer(wlc->radio_timer);
wlc->radio_timer = NULL;
}
}
@@ -1707,6 +5168,54 @@ static void brcms_c_detach_module(struct brcms_c_info *wlc)
}
/*
+ * low level detach
+ */
+static int brcms_b_detach(struct brcms_c_info *wlc)
+{
+ uint i;
+ struct brcms_hw_band *band;
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ int callbacks;
+
+ callbacks = 0;
+
+ if (wlc_hw->sih) {
+ /*
+ * detach interrupt sync mechanism since interrupt is disabled
+ * and per-port interrupt object may has been freed. this must
+ * be done before sb core switch
+ */
+ ai_deregister_intr_callback(wlc_hw->sih);
+ ai_pci_sleep(wlc_hw->sih);
+ }
+
+ brcms_b_detach_dmapio(wlc_hw);
+
+ band = wlc_hw->band;
+ for (i = 0; i < wlc_hw->_nbands; i++) {
+ if (band->pi) {
+ /* Detach this band's phy */
+ wlc_phy_detach(band->pi);
+ band->pi = NULL;
+ }
+ band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)];
+ }
+
+ /* Free shared phy state */
+ kfree(wlc_hw->phy_sh);
+
+ wlc_phy_shim_detach(wlc_hw->physhim);
+
+ if (wlc_hw->sih) {
+ ai_detach(wlc_hw->sih);
+ wlc_hw->sih = NULL;
+ }
+
+ return callbacks;
+
+}
+
+/*
* Return a count of the number of driver callbacks still pending.
*
* General policy is that brcms_c_detach can only dealloc/free software states.
@@ -1746,268 +5255,130 @@ uint brcms_c_detach(struct brcms_c_info *wlc)
}
/* update state that depends on the current value of "ap" */
-void brcms_c_ap_upd(struct brcms_c_info *wlc)
+static void brcms_c_ap_upd(struct brcms_c_info *wlc)
{
- if (AP_ENAB(wlc->pub))
- /* AP: short not allowed, but not enforced */
- wlc->PLCPHdr_override = BRCMS_PLCP_AUTO;
- else
- /* STA-BSS; short capable */
- wlc->PLCPHdr_override = BRCMS_PLCP_SHORT;
+ /* STA-BSS; short capable */
+ wlc->PLCPHdr_override = BRCMS_PLCP_SHORT;
/* fixup mpc */
wlc->mpc = true;
}
-/* read hwdisable state and propagate to wlc flag */
-static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc)
+/* Initialize just the hardware when coming out of POR or S3/S5 system states */
+static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
{
- if (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO || wlc->pub->hw_off)
+ if (wlc_hw->wlc->pub->hw_up)
return;
- if (brcms_b_radio_read_hwdisabled(wlc->hw)) {
- mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
- } else {
- mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
- }
-}
-
-/* return true if Minimum Power Consumption should be entered, false otherwise */
-bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc)
-{
- return false;
-}
-
-bool brcms_c_ismpc(struct brcms_c_info *wlc)
-{
- return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc));
-}
-
-void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc)
-{
- bool mpc_radio, radio_state;
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
/*
- * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
- * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
- * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
- * the radio is going down.
+ * Enable pll and xtal, initialize the power control registers,
+ * and force fastclock for the remainder of brcms_c_up().
*/
- if (!wlc->mpc) {
- if (!wlc->pub->radio_disabled)
- return;
- mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
- brcms_c_radio_upd(wlc);
- if (!wlc->pub->radio_disabled)
- brcms_c_radio_monitor_stop(wlc);
- return;
- }
+ brcms_b_xtal(wlc_hw, ON);
+ ai_clkctl_init(wlc_hw->sih);
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+ ai_pci_fixcfg(wlc_hw->sih);
/*
- * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in wlc->pub->radio_disabled
- * to go ON, always call radio_upd synchronously
- * to go OFF, postpone radio_upd to later when context is safe(e.g. watchdog)
+ * AI chip doesn't restore bar0win2 on
+ * hibernation/resume, need sw fixup
*/
- radio_state =
- (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
- ON);
- mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON;
+ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+ (wlc_hw->sih->chip == BCM43225_CHIP_ID))
+ wlc_hw->regs = (struct d11regs __iomem *)
+ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
- if (radio_state == ON && mpc_radio == OFF)
- wlc->mpc_delay_off = wlc->mpc_dlycnt;
- else if (radio_state == OFF && mpc_radio == ON) {
- mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
- brcms_c_radio_upd(wlc);
- if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD)
- wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT;
- else
- wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
- wlc->mpc_dur += OSL_SYSUPTIME() - wlc->mpc_laston_ts;
- }
- /* Below logic is meant to capture the transition from mpc off to mpc on for reasons
- * other than wlc->mpc_delay_off keeping the mpc off. In that case reset
- * wlc->mpc_delay_off to wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
+ /*
+ * Inform phy that a POR reset has occurred so
+ * it does a complete phy init
*/
- if ((wlc->prev_non_delay_mpc == false) &&
- (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off) {
- wlc->mpc_delay_off = wlc->mpc_dlycnt;
- }
- wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc);
-}
-
-/*
- * centralized radio disable/enable function,
- * invoke radio enable/disable after updating hwradio status
- */
-static void brcms_c_radio_upd(struct brcms_c_info *wlc)
-{
- if (wlc->pub->radio_disabled) {
- brcms_c_radio_disable(wlc);
- } else {
- brcms_c_radio_enable(wlc);
- }
-}
+ wlc_phy_por_inform(wlc_hw->band->pi);
-/* maintain LED behavior in down state */
-static void brcms_c_down_led_upd(struct brcms_c_info *wlc)
-{
- /* maintain LEDs while in down state, turn on sbclk if not available yet */
- /* turn on sbclk if necessary */
- if (!AP_ENAB(wlc->pub)) {
- brcms_c_pllreq(wlc, true, BRCMS_PLLREQ_FLIP);
+ wlc_hw->ucode_loaded = false;
+ wlc_hw->wlc->pub->hw_up = true;
- brcms_c_pllreq(wlc, false, BRCMS_PLLREQ_FLIP);
+ if ((wlc_hw->boardflags & BFL_FEM)
+ && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
+ if (!
+ (wlc_hw->boardrev >= 0x1250
+ && (wlc_hw->boardflags & BFL_FEM_BT)))
+ ai_epa_4313war(wlc_hw->sih);
}
}
-/* update hwradio status and return it */
-bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc)
-{
- brcms_c_radio_hwdisable_upd(wlc);
-
- return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ? true : false;
-}
-
-void brcms_c_radio_disable(struct brcms_c_info *wlc)
+static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
{
- if (!wlc->pub->up) {
- brcms_c_down_led_upd(wlc);
- return;
- }
-
- brcms_c_radio_monitor_start(wlc);
- brcms_down(wlc->wl);
-}
+ uint coremask;
-static void brcms_c_radio_enable(struct brcms_c_info *wlc)
-{
- if (wlc->pub->up)
- return;
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
- if (DEVICEREMOVED(wlc))
- return;
+ /*
+ * Enable pll and xtal, initialize the power control registers,
+ * and force fastclock for the remainder of brcms_c_up().
+ */
+ brcms_b_xtal(wlc_hw, ON);
+ ai_clkctl_init(wlc_hw->sih);
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
- brcms_up(wlc->wl);
-}
+ /*
+ * Configure pci/pcmcia here instead of in brcms_c_attach()
+ * to allow mfg hotswap: down, hotswap (chip power cycle), up.
+ */
+ coremask = (1 << wlc_hw->wlc->core->coreidx);
-/* periodical query hw radio button while driver is "down" */
-static void brcms_c_radio_timer(void *arg)
-{
- struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
+ ai_pci_setup(wlc_hw->sih, coremask);
- if (DEVICEREMOVED(wlc)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
- __func__);
- brcms_down(wlc->wl);
- return;
+ /*
+ * Need to read the hwradio status here to cover the case where the
+ * system is loaded with the hw radio disabled. We do not want to
+ * bring the driver up in this case.
+ */
+ if (brcms_b_radio_read_hwdisabled(wlc_hw)) {
+ /* put SB PCI in down state again */
+ ai_pci_down(wlc_hw->sih);
+ brcms_b_xtal(wlc_hw, OFF);
+ return -ENOMEDIUM;
}
- /* cap mpc off count */
- if (wlc->mpc_offcnt < BRCMS_MPC_MAX_DELAYCNT)
- wlc->mpc_offcnt++;
-
- brcms_c_radio_hwdisable_upd(wlc);
- brcms_c_radio_upd(wlc);
-}
+ ai_pci_up(wlc_hw->sih);
-static bool brcms_c_radio_monitor_start(struct brcms_c_info *wlc)
-{
- /* Don't start the timer if HWRADIO feature is disabled */
- if (wlc->radio_monitor || (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO))
- return true;
+ /* reset the d11 core */
+ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
- wlc->radio_monitor = true;
- brcms_c_pllreq(wlc, true, BRCMS_PLLREQ_RADIO_MON);
- brcms_add_timer(wlc->wl, wlc->radio_timer, TIMER_INTERVAL_RADIOCHK,
- true);
- return true;
+ return 0;
}
-bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc)
+static int brcms_b_up_finish(struct brcms_hardware *wlc_hw)
{
- if (!wlc->radio_monitor)
- return true;
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
- wlc->radio_monitor = false;
- brcms_c_pllreq(wlc, false, BRCMS_PLLREQ_RADIO_MON);
- return brcms_del_timer(wlc->wl, wlc->radio_timer);
-}
+ wlc_hw->up = true;
+ wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
-static void brcms_c_watchdog_by_timer(void *arg)
-{
- brcms_c_watchdog(arg);
+ /* FULLY enable dynamic power control and d11 core interrupt */
+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+ brcms_intrson(wlc_hw->wlc->wl);
+ return 0;
}
-/* common watchdog code */
-static void brcms_c_watchdog(void *arg)
+/*
+ * Write WME tunable parameters for retransmit/max rate
+ * from wlc struct to ucode
+ */
+static void brcms_c_wme_retries_write(struct brcms_c_info *wlc)
{
- struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
- int i;
- struct brcms_bss_cfg *cfg;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
- if (!wlc->pub->up)
- return;
-
- if (DEVICEREMOVED(wlc)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
- __func__);
- brcms_down(wlc->wl);
- return;
- }
-
- /* increment second count */
- wlc->pub->now++;
-
- /* delay radio disable */
- if (wlc->mpc_delay_off) {
- if (--wlc->mpc_delay_off == 0) {
- mboolset(wlc->pub->radio_disabled,
- WL_RADIO_MPC_DISABLE);
- if (wlc->mpc && brcms_c_ismpc(wlc))
- wlc->mpc_offcnt = 0;
- wlc->mpc_laston_ts = OSL_SYSUPTIME();
- }
- }
+ int ac;
- /* mpc sync */
- brcms_c_radio_mpc_upd(wlc);
- /* radio sync: sw/hw/mpc --> radio_disable/radio_enable */
- brcms_c_radio_hwdisable_upd(wlc);
- brcms_c_radio_upd(wlc);
- /* if radio is disable, driver may be down, quit here */
- if (wlc->pub->radio_disabled)
+ /* Need clock to do this */
+ if (!wlc->clk)
return;
- brcms_b_watchdog(wlc);
-
- /* occasionally sample mac stat counters to detect 16-bit counter wrap */
- if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0)
- brcms_c_statsupd(wlc);
-
- /* Manage TKIP countermeasures timers */
- FOREACH_BSS(wlc, i, cfg) {
- if (cfg->tk_cm_dt) {
- cfg->tk_cm_dt--;
- }
- if (cfg->tk_cm_bt) {
- cfg->tk_cm_bt--;
- }
- }
-
- /* Call any registered watchdog handlers */
- for (i = 0; i < BRCMS_MAXMODULES; i++) {
- if (wlc->modulecb[i].watchdog_fn)
- wlc->modulecb[i].watchdog_fn(wlc->modulecb[i].hdl);
- }
-
- if (BRCMS_ISNPHY(wlc->band) && !wlc->pub->tempsense_disable &&
- ((wlc->pub->now - wlc->tempsense_lasttime) >=
- BRCMS_TEMPSENSE_PERIOD)) {
- wlc->tempsense_lasttime = wlc->pub->now;
- brcms_c_tempsense_upd(wlc);
- }
+ for (ac = 0; ac < AC_COUNT; ac++)
+ brcms_b_write_shm(wlc->hw, M_AC_TXLMT_ADDR(ac),
+ wlc->wme_retries[ac]);
}
/* make interface operational */
@@ -2016,7 +5387,7 @@ int brcms_c_up(struct brcms_c_info *wlc)
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
/* HW is turned off so don't try to access it */
- if (wlc->pub->hw_off || DEVICEREMOVED(wlc))
+ if (wlc->pub->hw_off || brcms_deviceremoved(wlc))
return -ENOMEDIUM;
if (!wlc->pub->hw_up) {
@@ -2027,20 +5398,20 @@ int brcms_c_up(struct brcms_c_info *wlc)
if ((wlc->pub->boardflags & BFL_FEM)
&& (wlc->pub->sih->chip == BCM4313_CHIP_ID)) {
if (wlc->pub->boardrev >= 0x1250
- && (wlc->pub->boardflags & BFL_FEM_BT)) {
- brcms_c_mhf(wlc, MHF5, MHF5_4313_GPIOCTRL,
+ && (wlc->pub->boardflags & BFL_FEM_BT))
+ brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL,
MHF5_4313_GPIOCTRL, BRCM_BAND_ALL);
- } else {
- brcms_c_mhf(wlc, MHF4, MHF4_EXTPA_ENABLE,
+ else
+ brcms_b_mhf(wlc->hw, MHF4, MHF4_EXTPA_ENABLE,
MHF4_EXTPA_ENABLE, BRCM_BAND_ALL);
- }
}
/*
- * Need to read the hwradio status here to cover the case where the system
- * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
- * if radio is disabled, abort up, lower power, start radio timer and return 0(for NDIS)
- * don't call radio_update to avoid looping brcms_c_up.
+ * Need to read the hwradio status here to cover the case where the
+ * system is loaded with the hw radio disabled. We do not want to bring
+ * the driver up in this case. If radio is disabled, abort up, lower
+ * power, start radio timer and return 0(for NDIS) don't call
+ * radio_update to avoid looping brcms_c_up.
*
* brcms_b_up_prep() returns either 0 or -BCME_RADIOOFF only
*/
@@ -2049,20 +5420,15 @@ int brcms_c_up(struct brcms_c_info *wlc)
if (status == -ENOMEDIUM) {
if (!mboolisset
(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) {
- int idx;
- struct brcms_bss_cfg *bsscfg;
+ struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
mboolset(wlc->pub->radio_disabled,
WL_RADIO_HW_DISABLE);
- FOREACH_BSS(wlc, idx, bsscfg) {
- if (!BSSCFG_STA(bsscfg)
- || !bsscfg->enable || !bsscfg->BSS)
- continue;
- wiphy_err(wlc->wiphy, "wl%d.%d: up"
+ if (bsscfg->enable && bsscfg->BSS)
+ wiphy_err(wlc->wiphy, "wl%d: up"
": rfdisable -> "
"bsscfg_disable()\n",
- wlc->pub->unit, idx);
- }
+ wlc->pub->unit);
}
}
}
@@ -2078,15 +5444,7 @@ int brcms_c_up(struct brcms_c_info *wlc)
brcms_c_radio_monitor_stop(wlc);
/* Set EDCF hostflags */
- if (EDCF_ENAB(wlc->pub)) {
- brcms_c_mhf(wlc, MHF1, MHF1_EDCF, MHF1_EDCF, BRCM_BAND_ALL);
- } else {
- brcms_c_mhf(wlc, MHF1, MHF1_EDCF, 0, BRCM_BAND_ALL);
- }
-
- if (BRCMS_WAR16165(wlc))
- brcms_c_mhf(wlc, MHF2, MHF2_PCISLOWCLKWAR, MHF2_PCISLOWCLKWAR,
- BRCM_BAND_ALL);
+ brcms_b_mhf(wlc->hw, MHF1, MHF1_EDCF, MHF1_EDCF, BRCM_BAND_ALL);
brcms_init(wlc->wl);
wlc->pub->up = true;
@@ -2100,15 +5458,11 @@ int brcms_c_up(struct brcms_c_info *wlc)
brcms_b_up_finish(wlc->hw);
- /* other software states up after ISR is running */
- /* start APs that were to be brought up but are not up yet */
- /* if (AP_ENAB(wlc->pub)) brcms_c_restart_ap(wlc->ap); */
-
/* Program the TX wme params with the current settings */
brcms_c_wme_retries_write(wlc);
/* start one second watchdog timer */
- brcms_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true);
+ brcms_add_timer(wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true);
wlc->WDarmed = true;
/* ensure antenna config is up to date */
@@ -2119,29 +5473,80 @@ int brcms_c_up(struct brcms_c_info *wlc)
return 0;
}
-/* Initialize the base precedence map for dequeueing from txq based on WME settings */
-static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc)
+static uint brcms_c_down_del_timer(struct brcms_c_info *wlc)
{
- wlc->tx_prec_map = BRCMS_PREC_BMP_ALL;
- memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16));
+ uint callbacks = 0;
- /* For non-WME, both fifos have overlapping MAXPRIO. So just disable all precedences
- * if either is full.
- */
- if (!EDCF_ENAB(wlc->pub)) {
- wlc->fifo2prec_map[TX_DATA_FIFO] = BRCMS_PREC_BMP_ALL;
- wlc->fifo2prec_map[TX_CTL_FIFO] = BRCMS_PREC_BMP_ALL;
- } else {
- wlc->fifo2prec_map[TX_AC_BK_FIFO] = BRCMS_PREC_BMP_AC_BK;
- wlc->fifo2prec_map[TX_AC_BE_FIFO] = BRCMS_PREC_BMP_AC_BE;
- wlc->fifo2prec_map[TX_AC_VI_FIFO] = BRCMS_PREC_BMP_AC_VI;
- wlc->fifo2prec_map[TX_AC_VO_FIFO] = BRCMS_PREC_BMP_AC_VO;
+ return callbacks;
+}
+
+static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw)
+{
+ bool dev_gone;
+ uint callbacks = 0;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ if (!wlc_hw->up)
+ return callbacks;
+
+ dev_gone = brcms_deviceremoved(wlc_hw->wlc);
+
+ /* disable interrupts */
+ if (dev_gone)
+ wlc_hw->wlc->macintmask = 0;
+ else {
+ /* now disable interrupts */
+ brcms_intrsoff(wlc_hw->wlc->wl);
+
+ /* ensure we're running on the pll clock again */
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
}
+ /* down phy at the last of this stage */
+ callbacks += wlc_phy_down(wlc_hw->band->pi);
+
+ return callbacks;
}
-static uint brcms_c_down_del_timer(struct brcms_c_info *wlc)
+static int brcms_b_down_finish(struct brcms_hardware *wlc_hw)
{
uint callbacks = 0;
+ bool dev_gone;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ if (!wlc_hw->up)
+ return callbacks;
+
+ wlc_hw->up = false;
+ wlc_phy_hw_state_upd(wlc_hw->band->pi, false);
+
+ dev_gone = brcms_deviceremoved(wlc_hw->wlc);
+
+ if (dev_gone) {
+ wlc_hw->sbclk = false;
+ wlc_hw->clk = false;
+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+
+ /* reclaim any posted packets */
+ brcms_c_flushqueues(wlc_hw->wlc);
+ } else {
+
+ /* Reset and disable the core */
+ if (ai_iscoreup(wlc_hw->sih)) {
+ if (R_REG(&wlc_hw->regs->maccontrol) &
+ MCTL_EN_MAC)
+ brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+ callbacks += brcms_reset(wlc_hw->wlc->wl);
+ brcms_c_coredisable(wlc_hw);
+ }
+
+ /* turn off primary xtal and pll */
+ if (!wlc_hw->noreset) {
+ ai_pci_down(wlc_hw->sih);
+ brcms_b_xtal(wlc_hw, OFF);
+ }
+ }
return callbacks;
}
@@ -2175,7 +5580,7 @@ uint brcms_c_down(struct brcms_c_info *wlc)
callbacks += brcms_b_bmac_down_prep(wlc->hw);
- dev_gone = DEVICEREMOVED(wlc);
+ dev_gone = brcms_deviceremoved(wlc);
/* Call any registered down handlers */
for (i = 0; i < BRCMS_MAXMODULES; i++) {
@@ -2186,7 +5591,7 @@ uint brcms_c_down(struct brcms_c_info *wlc)
/* cancel the watchdog timer */
if (wlc->WDarmed) {
- if (!brcms_del_timer(wlc->wl, wlc->wdtimer))
+ if (!brcms_del_timer(wlc->wdtimer))
callbacks++;
wlc->WDarmed = false;
}
@@ -2201,9 +5606,8 @@ uint brcms_c_down(struct brcms_c_info *wlc)
brcms_c_txflowcontrol_reset(wlc);
/* flush tx queues */
- for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
+ for (qi = wlc->tx_queues; qi != NULL; qi = qi->next)
brcmu_pktq_flush(&qi->q, true, NULL, NULL);
- }
callbacks += brcms_b_down_finish(wlc->hw);
@@ -2219,30 +5623,31 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
{
int ret = 0;
uint i;
- wlc_rateset_t rs;
+ struct brcms_c_rateset rs;
/* Default to 54g Auto */
/* Advertise and use shortslot (-1/0/1 Auto/Off/On) */
s8 shortslot = BRCMS_SHORTSLOT_AUTO;
- bool shortslot_restrict = false; /* Restrict association to stations that support shortslot
- */
+ bool shortslot_restrict = false; /* Restrict association to stations
+ * that support shortslot
+ */
bool ofdm_basic = false; /* Make 6, 12, and 24 basic rates */
/* Advertise and use short preambles (-1/0/1 Auto/Off/On) */
int preamble = BRCMS_PLCP_LONG;
- bool preamble_restrict = false; /* Restrict association to stations that support short
- * preambles
+ bool preamble_restrict = false; /* Restrict association to stations
+ * that support short preambles
*/
struct brcms_band *band;
/* if N-support is enabled, allow Gmode set as long as requested
* Gmode is not GMODE_LEGACY_B
*/
- if (N_ENAB(wlc->pub) && gmode == GMODE_LEGACY_B)
+ if ((wlc->pub->_n_enab & SUPPORT_11N) && gmode == GMODE_LEGACY_B)
return -ENOTSUPP;
/* verify that we are dealing with 2G band and grab the band pointer */
if (wlc->band->bandtype == BRCM_BAND_2G)
band = wlc->band;
- else if ((NBANDS(wlc) > 1) &&
+ else if ((wlc->pub->_nbands > 1) &&
(wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == BRCM_BAND_2G))
band = wlc->bandstate[OTHERBANDUNIT(wlc)];
else
@@ -2257,11 +5662,8 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
if (config == true)
brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode);
- /* Clear supported rates filter */
- memset(&wlc->sup_rates_override, 0, sizeof(wlc_rateset_t));
-
/* Clear rateset override */
- memset(&rs, 0, sizeof(wlc_rateset_t));
+ memset(&rs, 0, sizeof(struct brcms_c_rateset));
switch (gmode) {
case GMODE_LEGACY_B:
@@ -2271,9 +5673,6 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
break;
case GMODE_LRS:
- if (AP_ENAB(wlc->pub))
- brcms_c_rateset_copy(&cck_rates,
- &wlc->sup_rates_override);
break;
case GMODE_AUTO:
@@ -2287,10 +5686,6 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
break;
case GMODE_PERFORMANCE:
- if (AP_ENAB(wlc->pub)) /* Put all rates into the Supported Rates element */
- brcms_c_rateset_copy(&cck_ofdm_rates,
- &wlc->sup_rates_override);
-
shortslot = BRCMS_SHORTSLOT_ON;
shortslot_restrict = true;
ofdm_basic = true;
@@ -2305,46 +5700,10 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
return -ENOTSUPP;
}
- /*
- * If we are switching to gmode == GMODE_LEGACY_B,
- * clean up rate info that may refer to OFDM rates.
- */
- if ((gmode == GMODE_LEGACY_B) && (band->gmode != GMODE_LEGACY_B)) {
- band->gmode = gmode;
- if (band->rspec_override && !IS_CCK(band->rspec_override)) {
- band->rspec_override = 0;
- brcms_c_reprate_init(wlc);
- }
- if (band->mrspec_override && !IS_CCK(band->mrspec_override)) {
- band->mrspec_override = 0;
- }
- }
-
band->gmode = gmode;
wlc->shortslot_override = shortslot;
- if (AP_ENAB(wlc->pub)) {
- /* wlc->ap->shortslot_restrict = shortslot_restrict; */
- wlc->PLCPHdr_override =
- (preamble !=
- BRCMS_PLCP_LONG) ? BRCMS_PLCP_SHORT : BRCMS_PLCP_AUTO;
- }
-
- if ((AP_ENAB(wlc->pub) && preamble != BRCMS_PLCP_LONG)
- || preamble == BRCMS_PLCP_SHORT)
- wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
- else
- wlc->default_bss->capability &= ~WLAN_CAPABILITY_SHORT_PREAMBLE;
-
- /* Update shortslot capability bit for AP and IBSS */
- if ((AP_ENAB(wlc->pub) && shortslot == BRCMS_SHORTSLOT_AUTO) ||
- shortslot == BRCMS_SHORTSLOT_ON)
- wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
- else
- wlc->default_bss->capability &=
- ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
-
/* Use the default 11g rateset */
if (!rs.count)
brcms_c_rateset_copy(&cck_ofdm_rates, &rs);
@@ -2366,92 +5725,41 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
return ret;
}
-static int brcms_c_nmode_validate(struct brcms_c_info *wlc, s32 nmode)
-{
- int err = 0;
-
- switch (nmode) {
-
- case OFF:
- break;
-
- case AUTO:
- case WL_11N_2x2:
- case WL_11N_3x3:
- if (!(BRCMS_PHY_11N_CAP(wlc->band)))
- err = -EINVAL;
- break;
-
- default:
- err = -EINVAL;
- break;
- }
-
- return err;
-}
-
-int brcms_c_set_nmode(struct brcms_c_info *wlc, s32 nmode)
+int brcms_c_set_nmode(struct brcms_c_info *wlc)
{
uint i;
- int err;
+ s32 nmode = AUTO;
- err = brcms_c_nmode_validate(wlc, nmode);
- if (err)
- return err;
-
- switch (nmode) {
- case OFF:
- wlc->pub->_n_enab = OFF;
- wlc->default_bss->flags &= ~BRCMS_BSS_HT;
- /* delete the mcs rates from the default and hw ratesets */
- brcms_c_rateset_mcs_clear(&wlc->default_bss->rateset);
- for (i = 0; i < NBANDS(wlc); i++) {
- memset(wlc->bandstate[i]->hw_rateset.mcs, 0,
- MCSSET_LEN);
- if (IS_MCS(wlc->band->rspec_override)) {
- wlc->bandstate[i]->rspec_override = 0;
- brcms_c_reprate_init(wlc);
- }
- if (IS_MCS(wlc->band->mrspec_override))
- wlc->bandstate[i]->mrspec_override = 0;
- }
- break;
-
- case AUTO:
- if (wlc->stf->txstreams == WL_11N_3x3)
- nmode = WL_11N_3x3;
- else
- nmode = WL_11N_2x2;
- case WL_11N_2x2:
- case WL_11N_3x3:
- /* force GMODE_AUTO if NMODE is ON */
- brcms_c_set_gmode(wlc, GMODE_AUTO, true);
- if (nmode == WL_11N_3x3)
- wlc->pub->_n_enab = SUPPORT_HT;
- else
- wlc->pub->_n_enab = SUPPORT_11N;
- wlc->default_bss->flags |= BRCMS_BSS_HT;
- /* add the mcs rates to the default and hw ratesets */
- brcms_c_rateset_mcs_build(&wlc->default_bss->rateset,
- wlc->stf->txstreams);
- for (i = 0; i < NBANDS(wlc); i++)
- memcpy(wlc->bandstate[i]->hw_rateset.mcs,
- wlc->default_bss->rateset.mcs, MCSSET_LEN);
- break;
+ if (wlc->stf->txstreams == WL_11N_3x3)
+ nmode = WL_11N_3x3;
+ else
+ nmode = WL_11N_2x2;
- default:
- break;
- }
+ /* force GMODE_AUTO if NMODE is ON */
+ brcms_c_set_gmode(wlc, GMODE_AUTO, true);
+ if (nmode == WL_11N_3x3)
+ wlc->pub->_n_enab = SUPPORT_HT;
+ else
+ wlc->pub->_n_enab = SUPPORT_11N;
+ wlc->default_bss->flags |= BRCMS_BSS_HT;
+ /* add the mcs rates to the default and hw ratesets */
+ brcms_c_rateset_mcs_build(&wlc->default_bss->rateset,
+ wlc->stf->txstreams);
+ for (i = 0; i < wlc->pub->_nbands; i++)
+ memcpy(wlc->bandstate[i]->hw_rateset.mcs,
+ wlc->default_bss->rateset.mcs, MCSSET_LEN);
- return err;
+ return 0;
}
-static int brcms_c_set_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs_arg)
+static int
+brcms_c_set_internal_rateset(struct brcms_c_info *wlc,
+ struct brcms_c_rateset *rs_arg)
{
- wlc_rateset_t rs, new;
+ struct brcms_c_rateset rs, new;
uint bandunit;
- memcpy(&rs, rs_arg, sizeof(wlc_rateset_t));
+ memcpy(&rs, rs_arg, sizeof(struct brcms_c_rateset));
/* check for bad count value */
if ((rs.count == 0) || (rs.count > BRCMS_NUMRATES))
@@ -2459,16 +5767,16 @@ static int brcms_c_set_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs_arg)
/* try the current band */
bandunit = wlc->band->bandunit;
- memcpy(&new, &rs, sizeof(wlc_rateset_t));
+ memcpy(&new, &rs, sizeof(struct brcms_c_rateset));
if (brcms_c_rate_hwrs_filter_sort_validate
(&new, &wlc->bandstate[bandunit]->hw_rateset, true,
wlc->stf->txstreams))
goto good;
/* try the other band */
- if (IS_MBAND_UNLOCKED(wlc)) {
+ if (brcms_is_mband_unlocked(wlc)) {
bandunit = OTHERBANDUNIT(wlc);
- memcpy(&new, &rs, sizeof(wlc_rateset_t));
+ memcpy(&new, &rs, sizeof(struct brcms_c_rateset));
if (brcms_c_rate_hwrs_filter_sort_validate(&new,
&wlc->
bandstate[bandunit]->
@@ -2481,299 +5789,176 @@ static int brcms_c_set_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs_arg)
good:
/* apply new rateset */
- memcpy(&wlc->default_bss->rateset, &new, sizeof(wlc_rateset_t));
+ memcpy(&wlc->default_bss->rateset, &new,
+ sizeof(struct brcms_c_rateset));
memcpy(&wlc->bandstate[bandunit]->defrateset, &new,
- sizeof(wlc_rateset_t));
+ sizeof(struct brcms_c_rateset));
return 0;
}
-/* simplified integer set interface for common ioctl handler */
-int brcms_c_set(struct brcms_c_info *wlc, int cmd, int arg)
-{
- return brcms_c_ioctl(wlc, cmd, (void *)&arg, sizeof(arg), NULL);
-}
-
-/* simplified integer get interface for common ioctl handler */
-int brcms_c_get(struct brcms_c_info *wlc, int cmd, int *arg)
-{
- return brcms_c_ioctl(wlc, cmd, arg, sizeof(int), NULL);
-}
-
static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc)
{
u8 r;
bool war = false;
- if (wlc->cfg->associated)
- r = wlc->cfg->current_bss->rateset.rates[0];
+ if (wlc->bsscfg->associated)
+ r = wlc->bsscfg->current_bss->rateset.rates[0];
else
r = wlc->default_bss->rateset.rates[0];
wlc_phy_ofdm_rateset_war(wlc->band->pi, war);
-
- return;
}
-int
-brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
- struct brcms_c_if *wlcif)
+int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel)
{
- return _brcms_c_ioctl(wlc, cmd, arg, len, wlcif);
-}
-
-/* common ioctl handler. return: 0=ok, -1=error, positive=particular error */
-static int
-_brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
- struct brcms_c_if *wlcif)
-{
- int val, *pval;
- bool bool_val;
- int bcmerror;
- struct scb *nextscb;
- bool ta_ok;
- uint band;
- struct brcms_bss_cfg *bsscfg;
- struct brcms_bss_info *current_bss;
-
- /* update bsscfg pointer */
- bsscfg = wlc->cfg;
- current_bss = bsscfg->current_bss;
-
- /* initialize the following to get rid of compiler warning */
- nextscb = NULL;
- ta_ok = false;
- band = 0;
-
- /* If the device is turned off, then it's not "removed" */
- if (!wlc->pub->hw_off && DEVICEREMOVED(wlc)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
- __func__);
- brcms_down(wlc->wl);
- return -EBADE;
- }
+ u16 chspec = ch20mhz_chspec(channel);
- /* default argument is generic integer */
- pval = arg ? (int *)arg : NULL;
+ if (channel < 0 || channel > MAXCHANNEL)
+ return -EINVAL;
- /* This will prevent the misaligned access */
- if (pval && (u32) len >= sizeof(val))
- memcpy(&val, pval, sizeof(val));
- else
- val = 0;
+ if (!brcms_c_valid_chanspec_db(wlc->cmi, chspec))
+ return -EINVAL;
- /* bool conversion to avoid duplication below */
- bool_val = val != 0;
- bcmerror = 0;
- if ((arg == NULL) || (len <= 0)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Command %d needs arguments\n",
- wlc->pub->unit, __func__, cmd);
- bcmerror = -EINVAL;
- goto done;
+ if (!wlc->pub->up && brcms_is_mband_unlocked(wlc)) {
+ if (wlc->band->bandunit != chspec_bandunit(chspec))
+ wlc->bandinit_pending = true;
+ else
+ wlc->bandinit_pending = false;
}
- switch (cmd) {
-
- case BRCM_SET_CHANNEL:{
- chanspec_t chspec = CH20MHZ_CHSPEC(val);
-
- if (val < 0 || val > MAXCHANNEL) {
- bcmerror = -EINVAL;
- break;
- }
-
- if (!brcms_c_valid_chanspec_db(wlc->cmi, chspec)) {
- bcmerror = -EINVAL;
- break;
- }
-
- if (!wlc->pub->up && IS_MBAND_UNLOCKED(wlc)) {
- if (wlc->band->bandunit !=
- CHSPEC_BANDUNIT(chspec))
- wlc->bandinit_pending = true;
- else
- wlc->bandinit_pending = false;
- }
-
- wlc->default_bss->chanspec = chspec;
- /* brcms_c_BSSinit() will sanitize the rateset before
- * using it.. */
- if (wlc->pub->up &&
- (BRCMS_BAND_PI_RADIO_CHANSPEC != chspec)) {
- brcms_c_set_home_chanspec(wlc, chspec);
- brcms_c_suspend_mac_and_wait(wlc);
- brcms_c_set_chanspec(wlc, chspec);
- brcms_c_enable_mac(wlc);
- }
- break;
- }
-
- case BRCM_SET_SRL:
- if (val >= 1 && val <= RETRY_SHORT_MAX) {
- int ac;
- wlc->SRL = (u16) val;
-
- brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
-
- for (ac = 0; ac < AC_COUNT; ac++) {
- BRCMS_WME_RETRY_SHORT_SET(wlc, ac, wlc->SRL);
- }
- brcms_c_wme_retries_write(wlc);
- } else
- bcmerror = -EINVAL;
- break;
-
- case BRCM_SET_LRL:
- if (val >= 1 && val <= 255) {
- int ac;
- wlc->LRL = (u16) val;
+ wlc->default_bss->chanspec = chspec;
+ /* brcms_c_BSSinit() will sanitize the rateset before
+ * using it.. */
+ if (wlc->pub->up && (wlc_phy_chanspec_get(wlc->band->pi) != chspec)) {
+ brcms_c_set_home_chanspec(wlc, chspec);
+ brcms_c_suspend_mac_and_wait(wlc);
+ brcms_c_set_chanspec(wlc, chspec);
+ brcms_c_enable_mac(wlc);
+ }
+ return 0;
+}
- brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
+int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl)
+{
+ int ac;
- for (ac = 0; ac < AC_COUNT; ac++) {
- BRCMS_WME_RETRY_LONG_SET(wlc, ac, wlc->LRL);
- }
- brcms_c_wme_retries_write(wlc);
- } else
- bcmerror = -EINVAL;
- break;
+ if (srl < 1 || srl > RETRY_SHORT_MAX ||
+ lrl < 1 || lrl > RETRY_SHORT_MAX)
+ return -EINVAL;
- case BRCM_GET_CURR_RATESET:{
- wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
- wlc_rateset_t *rs;
+ wlc->SRL = srl;
+ wlc->LRL = lrl;
- if (wlc->pub->associated)
- rs = &current_bss->rateset;
- else
- rs = &wlc->default_bss->rateset;
+ brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
- if (len < (int)(rs->count + sizeof(rs->count))) {
- bcmerror = -EOVERFLOW;
- break;
- }
+ for (ac = 0; ac < AC_COUNT; ac++) {
+ wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac],
+ EDCF_SHORT, wlc->SRL);
+ wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac],
+ EDCF_LONG, wlc->LRL);
+ }
+ brcms_c_wme_retries_write(wlc);
- /* Copy only legacy rateset section */
- ret_rs->count = rs->count;
- memcpy(&ret_rs->rates, &rs->rates, rs->count);
- break;
- }
+ return 0;
+}
- case BRCM_SET_RATESET:{
- wlc_rateset_t rs;
- wl_rateset_t *in_rs = (wl_rateset_t *) arg;
+void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
+ struct brcm_rateset *currs)
+{
+ struct brcms_c_rateset *rs;
- if (len < (int)(in_rs->count + sizeof(in_rs->count))) {
- bcmerror = -EOVERFLOW;
- break;
- }
+ if (wlc->pub->associated)
+ rs = &wlc->bsscfg->current_bss->rateset;
+ else
+ rs = &wlc->default_bss->rateset;
- if (in_rs->count > BRCMS_NUMRATES) {
- bcmerror = -ENOBUFS;
- break;
- }
+ /* Copy only legacy rateset section */
+ currs->count = rs->count;
+ memcpy(&currs->rates, &rs->rates, rs->count);
+}
- memset(&rs, 0, sizeof(wlc_rateset_t));
-
- /* Copy only legacy rateset section */
- rs.count = in_rs->count;
- memcpy(&rs.rates, &in_rs->rates, rs.count);
-
- /* merge rateset coming in with the current mcsset */
- if (N_ENAB(wlc->pub)) {
- if (bsscfg->associated)
- memcpy(rs.mcs,
- &current_bss->rateset.mcs[0],
- MCSSET_LEN);
- else
- memcpy(rs.mcs,
- &wlc->default_bss->rateset.mcs[0],
- MCSSET_LEN);
- }
+int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
+{
+ struct brcms_c_rateset internal_rs;
+ int bcmerror;
- bcmerror = brcms_c_set_rateset(wlc, &rs);
+ if (rs->count > BRCMS_NUMRATES)
+ return -ENOBUFS;
- if (!bcmerror)
- brcms_c_ofdm_rateset_war(wlc);
+ memset(&internal_rs, 0, sizeof(struct brcms_c_rateset));
- break;
- }
+ /* Copy only legacy rateset section */
+ internal_rs.count = rs->count;
+ memcpy(&internal_rs.rates, &rs->rates, internal_rs.count);
- case BRCM_SET_BCNPRD:
- /* range [1, 0xffff] */
- if (val >= DOT11_MIN_BEACON_PERIOD
- && val <= DOT11_MAX_BEACON_PERIOD)
- wlc->default_bss->beacon_period = (u16) val;
+ /* merge rateset coming in with the current mcsset */
+ if (wlc->pub->_n_enab & SUPPORT_11N) {
+ struct brcms_bss_info *mcsset_bss;
+ if (wlc->bsscfg->associated)
+ mcsset_bss = wlc->bsscfg->current_bss;
else
- bcmerror = -EINVAL;
- break;
+ mcsset_bss = wlc->default_bss;
+ memcpy(internal_rs.mcs, &mcsset_bss->rateset.mcs[0],
+ MCSSET_LEN);
+ }
- case BRCM_GET_PHYLIST:
- {
- unsigned char *cp = arg;
- if (len < 3) {
- bcmerror = -EOVERFLOW;
- break;
- }
+ bcmerror = brcms_c_set_internal_rateset(wlc, &internal_rs);
+ if (!bcmerror)
+ brcms_c_ofdm_rateset_war(wlc);
- if (BRCMS_ISNPHY(wlc->band))
- *cp++ = 'n';
- else if (BRCMS_ISLCNPHY(wlc->band))
- *cp++ = 'c';
- else if (BRCMS_ISSSLPNPHY(wlc->band))
- *cp++ = 's';
- *cp = '\0';
- break;
- }
+ return bcmerror;
+}
- case BRCMS_SET_SHORTSLOT_OVERRIDE:
- if (val != BRCMS_SHORTSLOT_AUTO && val != BRCMS_SHORTSLOT_OFF &&
- val != BRCMS_SHORTSLOT_ON) {
- bcmerror = -EINVAL;
- break;
- }
+int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
+{
+ if (period < DOT11_MIN_BEACON_PERIOD ||
+ period > DOT11_MAX_BEACON_PERIOD)
+ return -EINVAL;
- wlc->shortslot_override = (s8) val;
+ wlc->default_bss->beacon_period = period;
+ return 0;
+}
- /* shortslot is an 11g feature, so no more work if we are
- * currently on the 5G band
- */
- if (BAND_5G(wlc->band->bandtype))
- break;
+u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx)
+{
+ return wlc->band->phytype;
+}
- if (wlc->pub->up && wlc->pub->associated) {
- /* let watchdog or beacon processing update shortslot */
- } else if (wlc->pub->up) {
- /* unassociated shortslot is off */
- brcms_c_switch_shortslot(wlc, false);
- } else {
- /* driver is down, so just update the brcms_c_info
- * value */
- if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO) {
- wlc->shortslot = false;
- } else {
- wlc->shortslot =
- (wlc->shortslot_override ==
- BRCMS_SHORTSLOT_ON);
- }
- }
+void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, s8 sslot_override)
+{
+ wlc->shortslot_override = sslot_override;
- break;
+ /*
+ * shortslot is an 11g feature, so no more work if we are
+ * currently on the 5G band
+ */
+ if (wlc->band->bandtype == BRCM_BAND_5G)
+ return;
+ if (wlc->pub->up && wlc->pub->associated) {
+ /* let watchdog or beacon processing update shortslot */
+ } else if (wlc->pub->up) {
+ /* unassociated shortslot is off */
+ brcms_c_switch_shortslot(wlc, false);
+ } else {
+ /* driver is down, so just update the brcms_c_info
+ * value */
+ if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO)
+ wlc->shortslot = false;
+ else
+ wlc->shortslot =
+ (wlc->shortslot_override ==
+ BRCMS_SHORTSLOT_ON);
}
- done:
-
- if (bcmerror)
- wlc->pub->bcmerror = bcmerror;
-
- return bcmerror;
}
/*
* register watchdog and down handlers.
*/
int brcms_c_module_register(struct brcms_pub *pub,
- const char *name, void *hdl,
- watchdog_fn_t w_fn, down_fn_t d_fn)
+ const char *name, struct brcms_info *hdl,
+ int (*d_fn)(void *handle))
{
struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
int i;
@@ -2784,7 +5969,6 @@ int brcms_c_module_register(struct brcms_pub *pub,
strncpy(wlc->modulecb[i].name, name,
sizeof(wlc->modulecb[i].name) - 1);
wlc->modulecb[i].hdl = hdl;
- wlc->modulecb[i].watchdog_fn = w_fn;
wlc->modulecb[i].down_fn = d_fn;
return 0;
}
@@ -2794,8 +5978,8 @@ int brcms_c_module_register(struct brcms_pub *pub,
}
/* unregister module callbacks */
-int
-brcms_c_module_unregister(struct brcms_pub *pub, const char *name, void *hdl)
+int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
+ struct brcms_info *hdl)
{
struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
int i;
@@ -2815,21 +5999,6 @@ brcms_c_module_unregister(struct brcms_pub *pub, const char *name, void *hdl)
return -ENODATA;
}
-/* Write WME tunable parameters for retransmit/max rate from wlc struct to ucode */
-static void brcms_c_wme_retries_write(struct brcms_c_info *wlc)
-{
- int ac;
-
- /* Need clock to do this */
- if (!wlc->clk)
- return;
-
- for (ac = 0; ac < AC_COUNT; ac++) {
- brcms_c_write_shm(wlc, M_AC_TXLMT_ADDR(ac),
- wlc->wme_retries[ac]);
- }
-}
-
#ifdef BCMDBG
static const char * const supr_reason[] = {
"None", "PMQ Entry", "Flush request",
@@ -2882,59 +6051,6 @@ void brcms_c_print_txstatus(struct tx_status *txs)
#endif /* defined(BCMDBG) */
}
-void brcms_c_statsupd(struct brcms_c_info *wlc)
-{
- int i;
- struct macstat macstats;
-#ifdef BCMDBG
- u16 delta;
- u16 rxf0ovfl;
- u16 txfunfl[NFIFO];
-#endif /* BCMDBG */
-
- /* if driver down, make no sense to update stats */
- if (!wlc->pub->up)
- return;
-
-#ifdef BCMDBG
- /* save last rx fifo 0 overflow count */
- rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
-
- /* save last tx fifo underflow count */
- for (i = 0; i < NFIFO; i++)
- txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
-#endif /* BCMDBG */
-
- /* Read mac stats from contiguous shared memory */
- brcms_b_copyfrom_shm(wlc->hw, M_UCODE_MACSTAT,
- &macstats, sizeof(struct macstat));
-
-#ifdef BCMDBG
- /* check for rx fifo 0 overflow */
- delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
- if (delta)
- wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n",
- wlc->pub->unit, delta);
-
- /* check for tx fifo underflows */
- for (i = 0; i < NFIFO; i++) {
- delta =
- (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
- txfunfl[i]);
- if (delta)
- wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!"
- "\n", wlc->pub->unit, delta, i);
- }
-#endif /* BCMDBG */
-
- /* merge counters from dma module */
- for (i = 0; i < NFIFO; i++) {
- if (wlc->hw->di[i]) {
- dma_counterreset(wlc->hw->di[i]);
- }
- }
-}
-
bool brcms_c_chipmatch(u16 vendor, u16 device)
{
if (vendor != PCI_VENDOR_ID_BROADCOM) {
@@ -3042,6 +6158,62 @@ void brcms_c_print_txdesc(struct d11txh *txh)
#endif /* defined(BCMDBG) */
#if defined(BCMDBG)
+int
+brcms_c_format_flags(const struct brcms_c_bit_desc *bd, u32 flags, char *buf,
+ int len)
+{
+ int i;
+ char *p = buf;
+ char hexstr[16];
+ int slen = 0, nlen = 0;
+ u32 bit;
+ const char *name;
+
+ if (len < 2 || !buf)
+ return 0;
+
+ buf[0] = '\0';
+
+ for (i = 0; flags != 0; i++) {
+ bit = bd[i].bit;
+ name = bd[i].name;
+ if (bit == 0 && flags != 0) {
+ /* print any unnamed bits */
+ snprintf(hexstr, 16, "0x%X", flags);
+ name = hexstr;
+ flags = 0; /* exit loop */
+ } else if ((flags & bit) == 0)
+ continue;
+ flags &= ~bit;
+ nlen = strlen(name);
+ slen += nlen;
+ /* count btwn flag space */
+ if (flags != 0)
+ slen += 1;
+ /* need NULL char as well */
+ if (len <= slen)
+ break;
+ /* copy NULL char but don't count it */
+ strncpy(p, name, nlen + 1);
+ p += nlen;
+ /* copy btwn flag space and NULL char */
+ if (flags != 0)
+ p += snprintf(p, 2, " ");
+ len -= slen;
+ }
+
+ /* indicate the str was too short */
+ if (flags != 0) {
+ if (len < 2)
+ p -= 2 - len; /* overwrite last char */
+ p += snprintf(p, 2, ">");
+ }
+
+ return (int)(p - buf);
+}
+#endif /* defined(BCMDBG) */
+
+#if defined(BCMDBG)
void brcms_c_print_rxh(struct d11rxhdr *rxh)
{
u16 len = rxh->RxFrameSize;
@@ -3053,7 +6225,7 @@ void brcms_c_print_rxh(struct d11rxhdr *rxh)
u16 macstatus2 = rxh->RxStatus2;
char flagstr[64];
char lenbuf[20];
- static const struct brcmu_bit_desc macstat_flags[] = {
+ static const struct brcms_c_bit_desc macstat_flags[] = {
{RXS_FCSERR, "FCSErr"},
{RXS_RESPFRAMETX, "Reply"},
{RXS_PBPRES, "PADDING"},
@@ -3067,7 +6239,7 @@ void brcms_c_print_rxh(struct d11rxhdr *rxh)
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, rxh,
sizeof(struct d11rxhdr));
- brcmu_format_flags(macstat_flags, macstatus1, flagstr, 64);
+ brcms_c_format_flags(macstat_flags, macstatus1, flagstr, 64);
snprintf(lenbuf, sizeof(lenbuf), "0x%x", len);
@@ -3082,29 +6254,30 @@ void brcms_c_print_rxh(struct d11rxhdr *rxh)
}
#endif /* defined(BCMDBG) */
-static u16 brcms_c_rate_shm_offset(struct brcms_c_info *wlc, u8 rate)
+u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
{
- return brcms_b_rate_shm_offset(wlc->hw, rate);
-}
+ u16 table_ptr;
+ u8 phy_rate, index;
-/* Callback for device removed */
+ /* get the phy specific rate encoding for the PLCP SIGNAL field */
+ if (is_ofdm_rate(rate))
+ table_ptr = M_RT_DIRMAP_A;
+ else
+ table_ptr = M_RT_DIRMAP_B;
-/*
- * Attempts to queue a packet onto a multiple-precedence queue,
- * if necessary evicting a lower precedence packet from the queue.
- *
- * 'prec' is the precedence number that has already been mapped
- * from the packet priority.
- *
- * Returns true if packet consumed (queued), false if not.
- */
-bool
-brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q, void *pkt, int prec)
-{
- return brcms_c_prec_enq_head(wlc, q, pkt, prec, false);
+ /* for a given rate, the LS-nibble of the PLCP SIGNAL field is
+ * the index into the rate table.
+ */
+ phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
+ index = phy_rate & 0xf;
+
+ /* Find the SHM pointer to the rate table entry by looking in the
+ * Direct-map Table
+ */
+ return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2));
}
-bool
+static bool
brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
struct sk_buff *pkt, int prec, bool head)
{
@@ -3127,7 +6300,7 @@ brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
if (eprec >= 0) {
bool discard_oldest;
- discard_oldest = AC_BITMAP_TST(wlc->wme_dp, eprec);
+ discard_oldest = ac_bitmap_tst(0, eprec);
/* Refuse newer packet unless configured to discard oldest */
if (eprec == prec && !discard_oldest) {
@@ -3151,10 +6324,24 @@ brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
return true;
}
-void brcms_c_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
- uint prec)
+/*
+ * Attempts to queue a packet onto a multiple-precedence queue,
+ * if necessary evicting a lower precedence packet from the queue.
+ *
+ * 'prec' is the precedence number that has already been mapped
+ * from the packet priority.
+ *
+ * Returns true if packet consumed (queued), false if not.
+ */
+static bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q,
+ struct sk_buff *pkt, int prec)
+{
+ return brcms_c_prec_enq_head(wlc, q, pkt, prec, false);
+}
+
+void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb,
+ struct sk_buff *sdu, uint prec)
{
- struct brcms_c_info *wlc = (struct brcms_c_info *) ctx;
struct brcms_txq_info *qi = wlc->pkt_queue; /* Check me */
struct pktq *q = &qi->q;
int prio;
@@ -3162,124 +6349,12 @@ void brcms_c_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
prio = sdu->priority;
if (!brcms_c_prec_enq(wlc, q, sdu, prec)) {
- if (!EDCF_ENAB(wlc->pub)
- || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL))
- wiphy_err(wlc->wiphy, "wl%d: txq_enq: txq overflow"
- "\n", wlc->pub->unit);
-
/*
* we might hit this condtion in case
* packet flooding from mac80211 stack
*/
brcmu_pkt_buf_free_skb(sdu);
}
-
- /* Check if flow control needs to be turned on after enqueuing the packet
- * Don't turn on flow control if EDCF is enabled. Driver would make the decision on what
- * to drop instead of relying on stack to make the right decision
- */
- if (!EDCF_ENAB(wlc->pub)
- || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
- if (pktq_len(q) >= wlc->pub->tunables->datahiwat) {
- brcms_c_txflowcontrol(wlc, qi, ON, ALLPRIO);
- }
- } else if (wlc->pub->_priofc) {
- if (pktq_plen(q, wlc_prio2prec_map[prio]) >=
- wlc->pub->tunables->datahiwat) {
- brcms_c_txflowcontrol(wlc, qi, ON, prio);
- }
- }
-}
-
-bool
-brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
- struct ieee80211_hw *hw)
-{
- u8 prio;
- uint fifo;
- void *pkt;
- struct scb *scb = &global_scb;
- struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data);
-
- /* 802.11 standard requires management traffic to go at highest priority */
- prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority :
- MAXPRIO;
- fifo = prio2fifo[prio];
- pkt = sdu;
- if (unlikely
- (brcms_c_d11hdrs_mac80211(
- wlc, hw, pkt, scb, 0, 1, fifo, 0, NULL, 0)))
- return -EINVAL;
- brcms_c_txq_enq(wlc, scb, pkt, BRCMS_PRIO_TO_PREC(prio));
- brcms_c_send_q(wlc);
- return 0;
-}
-
-void brcms_c_send_q(struct brcms_c_info *wlc)
-{
- struct sk_buff *pkt[DOT11_MAXNUMFRAGS];
- int prec;
- u16 prec_map;
- int err = 0, i, count;
- uint fifo;
- struct brcms_txq_info *qi = wlc->pkt_queue;
- struct pktq *q = &qi->q;
- struct ieee80211_tx_info *tx_info;
-
- if (in_send_q)
- return;
- else
- in_send_q = true;
-
- prec_map = wlc->tx_prec_map;
-
- /* Send all the enq'd pkts that we can.
- * Dequeue packets with precedence with empty HW fifo only
- */
- while (prec_map && (pkt[0] = brcmu_pktq_mdeq(q, prec_map, &prec))) {
- tx_info = IEEE80211_SKB_CB(pkt[0]);
- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
- err = brcms_c_sendampdu(wlc->ampdu, qi, pkt, prec);
- } else {
- count = 1;
- err = brcms_c_prep_pdu(wlc, pkt[0], &fifo);
- if (!err) {
- for (i = 0; i < count; i++) {
- brcms_c_txfifo(wlc, fifo, pkt[i], true,
- 1);
- }
- }
- }
-
- if (err == -EBUSY) {
- brcmu_pktq_penq_head(q, prec, pkt[0]);
- /* If send failed due to any other reason than a change in
- * HW FIFO condition, quit. Otherwise, read the new prec_map!
- */
- if (prec_map == wlc->tx_prec_map)
- break;
- prec_map = wlc->tx_prec_map;
- }
- }
-
- /* Check if flow control needs to be turned off after sending the packet */
- if (!EDCF_ENAB(wlc->pub)
- || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
- if (brcms_c_txflowcontrol_prio_isset(wlc, qi, ALLPRIO)
- && (pktq_len(q) < wlc->pub->tunables->datahiwat / 2)) {
- brcms_c_txflowcontrol(wlc, qi, OFF, ALLPRIO);
- }
- } else if (wlc->pub->_priofc) {
- int prio;
- for (prio = MAXPRIO; prio >= 0; prio--) {
- if (brcms_c_txflowcontrol_prio_isset(wlc, qi, prio) &&
- (pktq_plen(q, wlc_prio2prec_map[prio]) <
- wlc->pub->tunables->datahiwat / 2)) {
- brcms_c_txflowcontrol(wlc, qi, OFF, prio);
- }
- }
- }
- in_send_q = false;
}
/*
@@ -3303,92 +6378,284 @@ bcmc_fid_generate(struct brcms_c_info *wlc, struct brcms_bss_cfg *bsscfg,
return frameid;
}
-void
-brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p,
- bool commit, s8 txpktpend)
+static uint
+brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec,
+ u8 preamble_type)
{
- u16 frameid = INVALIDFID;
- struct d11txh *txh;
-
- txh = (struct d11txh *) (p->data);
+ uint dur = 0;
- /* When a BC/MC frame is being committed to the BCMC fifo via DMA (NOT PIO), update
- * ucode or BSS info as appropriate.
+ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n",
+ wlc->pub->unit, rspec, preamble_type);
+ /*
+ * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that
+ * is less than or equal to the rate of the immediately previous
+ * frame in the FES
*/
- if (fifo == TX_BCMC_FIFO) {
- frameid = le16_to_cpu(txh->TxFrameID);
+ rspec = brcms_basic_rate(wlc, rspec);
+ /* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */
+ dur =
+ brcms_c_calc_frame_time(wlc, rspec, preamble_type,
+ (DOT11_ACK_LEN + FCS_LEN));
+ return dur;
+}
- }
+static uint
+brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rspec,
+ u8 preamble_type)
+{
+ BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n",
+ wlc->pub->unit, rspec, preamble_type);
+ return brcms_c_calc_ack_time(wlc, rspec, preamble_type);
+}
- if (BRCMS_WAR16165(wlc))
- brcms_c_war16165(wlc, true);
+static uint
+brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rspec,
+ u8 preamble_type)
+{
+ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, "
+ "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type);
+ /*
+ * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that
+ * is less than or equal to the rate of the immediately previous
+ * frame in the FES
+ */
+ rspec = brcms_basic_rate(wlc, rspec);
+ /* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */
+ return brcms_c_calc_frame_time(wlc, rspec, preamble_type,
+ (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN +
+ FCS_LEN));
+}
+/* brcms_c_compute_frame_dur()
+ *
+ * Calculate the 802.11 MAC header DUR field for MPDU
+ * DUR for a single frame = 1 SIFS + 1 ACK
+ * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time
+ *
+ * rate MPDU rate in unit of 500kbps
+ * next_frag_len next MPDU length in bytes
+ * preamble_type use short/GF or long/MM PLCP header
+ */
+static u16
+brcms_c_compute_frame_dur(struct brcms_c_info *wlc, u32 rate,
+ u8 preamble_type, uint next_frag_len)
+{
+ u16 dur, sifs;
- /* Bump up pending count for if not using rpc. If rpc is used, this will be handled
- * in brcms_b_txfifo()
- */
- if (commit) {
- TXPKTPENDINC(wlc, fifo, txpktpend);
- BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n",
- txpktpend, TXPKTPENDGET(wlc, fifo));
- }
+ sifs = get_sifs(wlc->band);
- /* Commit BCMC sequence number in the SHM frame ID location */
- if (frameid != INVALIDFID)
- BCMCFID(wlc, frameid);
+ dur = sifs;
+ dur += (u16) brcms_c_calc_ack_time(wlc, rate, preamble_type);
- if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) {
- wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n");
+ if (next_frag_len) {
+ /* Double the current DUR to get 2 SIFS + 2 ACKs */
+ dur *= 2;
+ /* add another SIFS and the frag time */
+ dur += sifs;
+ dur +=
+ (u16) brcms_c_calc_frame_time(wlc, rate, preamble_type,
+ next_frag_len);
}
+ return dur;
}
-void
-brcms_c_compute_plcp(struct brcms_c_info *wlc, ratespec_t rspec,
- uint length, u8 *plcp)
+/* The opposite of brcms_c_calc_frame_time */
+static uint
+brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec,
+ u8 preamble_type, uint dur)
{
- if (IS_MCS(rspec)) {
- brcms_c_compute_mimo_plcp(rspec, length, plcp);
- } else if (IS_OFDM(rspec)) {
- brcms_c_compute_ofdm_plcp(rspec, length, plcp);
+ uint nsyms, mac_len, Ndps, kNdps;
+ uint rate = rspec2rate(ratespec);
+
+ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, dur %d\n",
+ wlc->pub->unit, ratespec, preamble_type, dur);
+
+ if (is_mcs_rate(ratespec)) {
+ uint mcs = ratespec & RSPEC_RATE_MASK;
+ int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec);
+ dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
+ /* payload calculation matches that of regular ofdm */
+ if (wlc->band->bandtype == BRCM_BAND_2G)
+ dur -= DOT11_OFDM_SIGNAL_EXTENSION;
+ /* kNdbps = kbps * 4 */
+ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
+ rspec_issgi(ratespec)) * 4;
+ nsyms = dur / APHY_SYMBOL_TIME;
+ mac_len =
+ ((nsyms * kNdps) -
+ ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000;
+ } else if (is_ofdm_rate(ratespec)) {
+ dur -= APHY_PREAMBLE_TIME;
+ dur -= APHY_SIGNAL_TIME;
+ /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
+ Ndps = rate * 2;
+ nsyms = dur / APHY_SYMBOL_TIME;
+ mac_len =
+ ((nsyms * Ndps) -
+ (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8;
} else {
- brcms_c_compute_cck_plcp(wlc, rspec, length, plcp);
+ if (preamble_type & BRCMS_SHORT_PREAMBLE)
+ dur -= BPHY_PLCP_SHORT_TIME;
+ else
+ dur -= BPHY_PLCP_TIME;
+ mac_len = dur * rate;
+ /* divide out factor of 2 in rate (1/2 mbps) */
+ mac_len = mac_len / 8 / 2;
}
- return;
+ return mac_len;
}
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void brcms_c_compute_mimo_plcp(ratespec_t rspec, uint length, u8 *plcp)
+/*
+ * Return true if the specified rate is supported by the specified band.
+ * BRCM_BAND_AUTO indicates the current band.
+ */
+static bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band,
+ bool verbose)
{
- u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
- plcp[0] = mcs;
- if (RSPEC_IS40MHZ(rspec) || (mcs == 32))
- plcp[0] |= MIMO_PLCP_40MHZ;
- BRCMS_SET_MIMO_PLCP_LEN(plcp, length);
- plcp[3] = RSPEC_MIMOPLCP3(rspec); /* rspec already holds this byte */
- plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */
- plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */
- plcp[5] = 0;
+ struct brcms_c_rateset *hw_rateset;
+ uint i;
+
+ if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype))
+ hw_rateset = &wlc->band->hw_rateset;
+ else if (wlc->pub->_nbands > 1)
+ hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
+ else
+ /* other band specified and we are a single band device */
+ return false;
+
+ /* check if this is a mimo rate */
+ if (is_mcs_rate(rspec)) {
+ if ((rspec & RSPEC_RATE_MASK) >= MCS_TABLE_SIZE)
+ goto error;
+
+ return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
+ }
+
+ for (i = 0; i < hw_rateset->count; i++)
+ if (hw_rateset->rates[i] == rspec2rate(rspec))
+ return true;
+ error:
+ if (verbose)
+ wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x "
+ "not in hw_rateset\n", wlc->pub->unit, rspec);
+
+ return false;
}
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void
-brcms_c_compute_ofdm_plcp(ratespec_t rspec, u32 length, u8 *plcp)
+static u32
+mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
+ u32 int_val)
{
- u8 rate_signal;
- u32 tmp = 0;
- int rate = RSPEC2RATE(rspec);
+ u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
+ u8 rate = int_val & NRATE_RATE_MASK;
+ u32 rspec;
+ bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE);
+ bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT);
+ bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY)
+ == NRATE_OVERRIDE_MCS_ONLY);
+ int bcmerror = 0;
- /* encode rate per 802.11a-1999 sec 17.3.4.1, with lsb transmitted first */
- rate_signal = rate_info[rate] & BRCMS_RATE_MASK;
- memset(plcp, 0, D11_PHY_HDR_LEN);
- D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal);
+ if (!ismcs)
+ return (u32) rate;
- tmp = (length & 0xfff) << 5;
- plcp[2] |= (tmp >> 16) & 0xff;
- plcp[1] |= (tmp >> 8) & 0xff;
- plcp[0] |= tmp & 0xff;
+ /* validate the combination of rate/mcs/stf is allowed */
+ if ((wlc->pub->_n_enab & SUPPORT_11N) && ismcs) {
+ /* mcs only allowed when nmode */
+ if (stf > PHY_TXC1_MODE_SDM) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n",
+ wlc->pub->unit, __func__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
- return;
+ /* mcs 32 is a special case, DUP mode 40 only */
+ if (rate == 32) {
+ if (!CHSPEC_IS40(wlc->home_chanspec) ||
+ ((stf != PHY_TXC1_MODE_SISO)
+ && (stf != PHY_TXC1_MODE_CDD))) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid mcs "
+ "32\n", wlc->pub->unit, __func__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
+ /* mcs > 7 must use stf SDM */
+ } else if (rate > HIGHEST_SINGLE_STREAM_MCS) {
+ /* mcs > 7 must use stf SDM */
+ if (stf != PHY_TXC1_MODE_SDM) {
+ BCMMSG(wlc->wiphy, "wl%d: enabling "
+ "SDM mode for mcs %d\n",
+ wlc->pub->unit, rate);
+ stf = PHY_TXC1_MODE_SDM;
+ }
+ } else {
+ /*
+ * MCS 0-7 may use SISO, CDD, and for
+ * phy_rev >= 3 STBC
+ */
+ if ((stf > PHY_TXC1_MODE_STBC) ||
+ (!BRCMS_STBC_CAP_PHY(wlc)
+ && (stf == PHY_TXC1_MODE_STBC))) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid STBC"
+ "\n", wlc->pub->unit, __func__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
+ }
+ } else if (is_ofdm_rate(rate)) {
+ if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n",
+ wlc->pub->unit, __func__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
+ } else if (is_cck_rate(rate)) {
+ if ((cur_band->bandtype != BRCM_BAND_2G)
+ || (stf != PHY_TXC1_MODE_SISO)) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n",
+ wlc->pub->unit, __func__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
+ } else {
+ wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n",
+ wlc->pub->unit, __func__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
+ /* make sure multiple antennae are available for non-siso rates */
+ if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: SISO antenna but !SISO "
+ "request\n", wlc->pub->unit, __func__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
+
+ rspec = rate;
+ if (ismcs) {
+ rspec |= RSPEC_MIMORATE;
+ /* For STBC populate the STC field of the ratespec */
+ if (stf == PHY_TXC1_MODE_STBC) {
+ u8 stc;
+ stc = 1; /* Nss for single stream is always 1 */
+ rspec |= (stc << RSPEC_STC_SHIFT);
+ }
+ }
+
+ rspec |= (stf << RSPEC_STF_SHIFT);
+
+ if (override_mcs_only)
+ rspec |= RSPEC_OVERRIDE_MCS_ONLY;
+
+ if (issgi)
+ rspec |= RSPEC_SHORT_GI;
+
+ if ((rate != 0)
+ && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true))
+ return rate;
+
+ return rspec;
+done:
+ return rate;
}
/*
@@ -3426,8 +6693,9 @@ static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500,
break;
default:
- wiphy_err(wlc->wiphy, "brcms_c_cck_plcp_set: unsupported rate %d"
- "\n", rate_500);
+ wiphy_err(wlc->wiphy,
+ "brcms_c_cck_plcp_set: unsupported rate %d\n",
+ rate_500);
rate_500 = BRCM_RATE_1M;
usec = length << 3;
break;
@@ -3445,45 +6713,60 @@ static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500,
}
/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, ratespec_t rspec,
- uint length, u8 *plcp)
+static void brcms_c_compute_mimo_plcp(u32 rspec, uint length, u8 *plcp)
{
- int rate = RSPEC2RATE(rspec);
-
- brcms_c_cck_plcp_set(wlc, rate, length, plcp);
+ u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
+ plcp[0] = mcs;
+ if (rspec_is40mhz(rspec) || (mcs == 32))
+ plcp[0] |= MIMO_PLCP_40MHZ;
+ BRCMS_SET_MIMO_PLCP_LEN(plcp, length);
+ plcp[3] = rspec_mimoplcp3(rspec); /* rspec already holds this byte */
+ plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */
+ plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */
+ plcp[5] = 0;
}
-/* brcms_c_compute_frame_dur()
- *
- * Calculate the 802.11 MAC header DUR field for MPDU
- * DUR for a single frame = 1 SIFS + 1 ACK
- * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time
- *
- * rate MPDU rate in unit of 500kbps
- * next_frag_len next MPDU length in bytes
- * preamble_type use short/GF or long/MM PLCP header
- */
-static u16
-brcms_c_compute_frame_dur(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type, uint next_frag_len)
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void
+brcms_c_compute_ofdm_plcp(u32 rspec, u32 length, u8 *plcp)
{
- u16 dur, sifs;
+ u8 rate_signal;
+ u32 tmp = 0;
+ int rate = rspec2rate(rspec);
- sifs = SIFS(wlc->band);
+ /*
+ * encode rate per 802.11a-1999 sec 17.3.4.1, with lsb
+ * transmitted first
+ */
+ rate_signal = rate_info[rate] & BRCMS_RATE_MASK;
+ memset(plcp, 0, D11_PHY_HDR_LEN);
+ D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal);
- dur = sifs;
- dur += (u16) brcms_c_calc_ack_time(wlc, rate, preamble_type);
+ tmp = (length & 0xfff) << 5;
+ plcp[2] |= (tmp >> 16) & 0xff;
+ plcp[1] |= (tmp >> 8) & 0xff;
+ plcp[0] |= tmp & 0xff;
+}
- if (next_frag_len) {
- /* Double the current DUR to get 2 SIFS + 2 ACKs */
- dur *= 2;
- /* add another SIFS and the frag time */
- dur += sifs;
- dur +=
- (u16) brcms_c_calc_frame_time(wlc, rate, preamble_type,
- next_frag_len);
- }
- return dur;
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rspec,
+ uint length, u8 *plcp)
+{
+ int rate = rspec2rate(rspec);
+
+ brcms_c_cck_plcp_set(wlc, rate, length, plcp);
+}
+
+static void
+brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rspec,
+ uint length, u8 *plcp)
+{
+ if (is_mcs_rate(rspec))
+ brcms_c_compute_mimo_plcp(rspec, length, plcp);
+ else if (is_ofdm_rate(rspec))
+ brcms_c_compute_ofdm_plcp(rspec, length, plcp);
+ else
+ brcms_c_compute_cck_plcp(wlc, rspec, length, plcp);
}
/* brcms_c_compute_rtscts_dur()
@@ -3499,20 +6782,22 @@ brcms_c_compute_frame_dur(struct brcms_c_info *wlc, ratespec_t rate,
*/
u16
brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
- ratespec_t rts_rate,
- ratespec_t frame_rate, u8 rts_preamble_type,
+ u32 rts_rate,
+ u32 frame_rate, u8 rts_preamble_type,
u8 frame_preamble_type, uint frame_len, bool ba)
{
u16 dur, sifs;
- sifs = SIFS(wlc->band);
+ sifs = get_sifs(wlc->band);
- if (!cts_only) { /* RTS/CTS */
+ if (!cts_only) {
+ /* RTS/CTS */
dur = 3 * sifs;
dur +=
(u16) brcms_c_calc_cts_time(wlc, rts_rate,
rts_preamble_type);
- } else { /* CTS-TO-SELF */
+ } else {
+ /* CTS-TO-SELF */
dur = 2 * sifs;
}
@@ -3530,7 +6815,7 @@ brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
return dur;
}
-u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, ratespec_t rspec)
+static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec)
{
u16 phyctl1 = 0;
u16 bw;
@@ -3538,7 +6823,7 @@ u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, ratespec_t rspec)
if (BRCMS_ISLCNPHY(wlc->band)) {
bw = PHY_TXC1_BW_20MHZ;
} else {
- bw = RSPEC_GET_BW(rspec);
+ bw = rspec_get_bw(rspec);
/* 10Mhz is not supported yet */
if (bw < PHY_TXC1_BW_20MHZ) {
wiphy_err(wlc->wiphy, "phytxctl1_calc: bw %d is "
@@ -3547,23 +6832,26 @@ u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, ratespec_t rspec)
}
}
- if (IS_MCS(rspec)) {
+ if (is_mcs_rate(rspec)) {
uint mcs = rspec & RSPEC_RATE_MASK;
- /* bw, stf, coding-type is part of RSPEC_PHYTXBYTE2 returns */
- phyctl1 = RSPEC_PHYTXBYTE2(rspec);
+ /* bw, stf, coding-type is part of rspec_phytxbyte2 returns */
+ phyctl1 = rspec_phytxbyte2(rspec);
/* set the upper byte of phyctl1 */
phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8);
- } else if (IS_CCK(rspec) && !BRCMS_ISLCNPHY(wlc->band)
+ } else if (is_cck_rate(rspec) && !BRCMS_ISLCNPHY(wlc->band)
&& !BRCMS_ISSSLPNPHY(wlc->band)) {
- /* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
- /* Eventually MIMOPHY would also be converted to this format */
+ /*
+ * 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 */
- phyctl1 = (bw | (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
+ phyctl1 = (bw | (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT));
} else { /* legacy OFDM/CCK */
s16 phycfg;
/* get the phyctl byte from rate phycfg table */
- phycfg = brcms_c_rate_legacy_phyctl(RSPEC2RATE(rspec));
+ phycfg = brcms_c_rate_legacy_phyctl(rspec2rate(rspec));
if (phycfg == -1) {
wiphy_err(wlc->wiphy, "phytxctl1_calc: wrong "
"legacy OFDM/CCK rate\n");
@@ -3572,58 +6860,11 @@ u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, ratespec_t rspec)
/* set the upper byte of phyctl1 */
phyctl1 =
(bw | (phycfg << 8) |
- (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
+ (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT));
}
return phyctl1;
}
-ratespec_t
-brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, ratespec_t rspec,
- bool use_rspec, u16 mimo_ctlchbw)
-{
- ratespec_t rts_rspec = 0;
-
- if (use_rspec) {
- /* use frame rate as rts rate */
- rts_rspec = rspec;
-
- } else if (wlc->band->gmode && wlc->protection->_g && !IS_CCK(rspec)) {
- /* Use 11Mbps as the g protection RTS target rate and fallback.
- * Use the BRCMS_BASIC_RATE() lookup to find the best basic rate
- * under the target in case 11 Mbps is not Basic.
- * 6 and 9 Mbps are not usually selected by rate selection, but even
- * if the OFDM rate we are protecting is 6 or 9 Mbps, 11 is more robust.
- */
- rts_rspec = BRCMS_BASIC_RATE(wlc, BRCM_RATE_11M);
- } else {
- /* calculate RTS rate and fallback rate based on the frame rate
- * RTS must be sent at a basic rate since it is a
- * control frame, sec 9.6 of 802.11 spec
- */
- rts_rspec = BRCMS_BASIC_RATE(wlc, rspec);
- }
-
- if (BRCMS_PHY_11N_CAP(wlc->band)) {
- /* set rts txbw to correct side band */
- rts_rspec &= ~RSPEC_BW_MASK;
-
- /* if rspec/rspec_fallback is 40MHz, then send RTS on both 20MHz channel
- * (DUP), otherwise send RTS on control channel
- */
- if (RSPEC_IS40MHZ(rspec) && !IS_CCK(rts_rspec))
- rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT);
- else
- rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
-
- /* pick siso/cdd as default for ofdm */
- if (IS_OFDM(rts_rspec)) {
- rts_rspec &= ~RSPEC_STF_MASK;
- rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
- }
- }
- return rts_rspec;
-}
-
/*
* Add struct d11txh, struct cck_phy_hdr.
*
@@ -3636,8 +6877,7 @@ brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, ratespec_t rspec,
static u16
brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
struct sk_buff *p, struct scb *scb, uint frag,
- uint nfrags, uint queue, uint next_frag_len,
- struct wsec_key *key, ratespec_t rspec_override)
+ uint nfrags, uint queue, uint next_frag_len)
{
struct ieee80211_hdr *h;
struct d11txh *txh;
@@ -3645,8 +6885,8 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
int len, phylen, rts_phylen;
u16 mch, phyctl, xfts, mainrates;
u16 seq = 0, mcl = 0, status = 0, frameid = 0;
- ratespec_t rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }, rts_rspec[2] = {
- BRCM_RATE_1M, BRCM_RATE_1M};
+ u32 rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M };
+ u32 rts_rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M };
bool use_rts = false;
bool use_cts = false;
bool use_rifs = false;
@@ -3657,7 +6897,6 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
struct ieee80211_rts *rts = NULL;
bool qos;
uint ac;
- u32 rate_val[2];
bool hwtkmic = false;
u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
#define ANTCFG_NONE 0xFF
@@ -3668,7 +6907,7 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
struct ieee80211_tx_rate *txrate[2];
int k;
struct ieee80211_tx_info *tx_info;
- bool is_mcs[2];
+ bool is_mcs;
u16 mimo_txbw;
u8 mimo_preamble_type;
@@ -3680,15 +6919,6 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
len = brcmu_pkttotlen(p);
phylen = len + FCS_LEN;
- /* If WEP enabled, add room in phylen for the additional bytes of
- * ICV which MAC generates. We do NOT add the additional bytes to
- * the packet itself, thus phylen = packet length + ICV_LEN + FCS_LEN
- * in this case
- */
- if (key) {
- phylen += key->icv_len;
- }
-
/* Get tx_info */
tx_info = IEEE80211_SKB_CB(p);
@@ -3704,17 +6934,16 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
/* non-AP STA should never use BCMC queue */
if (queue == TX_BCMC_FIFO) {
wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == "
- "TX_BCMC!\n", BRCMS_UNIT(wlc), __func__);
+ "TX_BCMC!\n", wlc->pub->unit, __func__);
frameid = bcmc_fid_generate(wlc, NULL, txh);
} else {
/* Increment the counter for first fragment */
- if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) {
- SCB_SEQNUM(scb, p->priority)++;
- }
+ if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+ scb->seqnum[p->priority]++;
/* extract fragment number from frame first */
- seq = le16_to_cpu(seq) & FRAGNUM_MASK;
- seq |= (SCB_SEQNUM(scb, p->priority) << SEQNUM_SHIFT);
+ seq = le16_to_cpu(h->seq_ctrl) & FRAGNUM_MASK;
+ seq |= (scb->seqnum[p->priority] << SEQNUM_SHIFT);
h->seq_ctrl = cpu_to_le16(seq);
frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
@@ -3724,25 +6953,26 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
frameid |= queue & TXFID_QUEUE_MASK;
/* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */
- if (SCB_PS(scb) || ieee80211_is_beacon(h->frame_control))
+ if (ieee80211_is_beacon(h->frame_control))
mcl |= TXC_IGNOREPMQ;
txrate[0] = tx_info->control.rates;
txrate[1] = txrate[0] + 1;
- /* if rate control algorithm didn't give us a fallback rate, use the primary rate */
- if (txrate[1]->idx < 0) {
+ /*
+ * if rate control algorithm didn't give us a fallback
+ * rate, use the primary rate
+ */
+ if (txrate[1]->idx < 0)
txrate[1] = txrate[0];
- }
for (k = 0; k < hw->max_rates; k++) {
- is_mcs[k] =
- txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false;
- if (!is_mcs[k]) {
+ is_mcs = txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false;
+ if (!is_mcs) {
if ((txrate[k]->idx >= 0)
&& (txrate[k]->idx <
hw->wiphy->bands[tx_info->band]->n_bitrates)) {
- rate_val[k] =
+ rspec[k] =
hw->wiphy->bands[tx_info->band]->
bitrates[txrate[k]->idx].hw_value;
short_preamble[k] =
@@ -3750,13 +6980,17 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ?
true : false;
} else {
- rate_val[k] = BRCM_RATE_1M;
+ rspec[k] = BRCM_RATE_1M;
}
} else {
- rate_val[k] = txrate[k]->idx;
+ rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band,
+ NRATE_MCS_INUSE | txrate[k]->idx);
}
- /* Currently only support same setting for primay and fallback rates.
- * Unify flags for each rate into a single value for the frame
+
+ /*
+ * Currently only support same setting for primay and
+ * fallback rates. Unify flags for each rate into a
+ * single value for the frame
*/
use_rts |=
txrate[k]->
@@ -3765,13 +6999,13 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
txrate[k]->
flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false;
- if (is_mcs[k])
- rate_val[k] |= NRATE_MCS_INUSE;
- rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band, rate_val[k]);
-
- /* (1) RATE: determine and validate primary rate and fallback rates */
- if (!RSPEC_ACTIVE(rspec[k])) {
+ /*
+ * (1) RATE:
+ * determine and validate primary rate
+ * and fallback rates
+ */
+ if (!rspec_active(rspec[k])) {
rspec[k] = BRCM_RATE_1M;
} else {
if (!is_multicast_ether_addr(h->addr1)) {
@@ -3784,41 +7018,49 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
phyctl1_stf = wlc->stf->ss_opmode;
- if (N_ENAB(wlc->pub)) {
+ if (wlc->pub->_n_enab & SUPPORT_11N) {
for (k = 0; k < hw->max_rates; k++) {
- /* apply siso/cdd to single stream mcs's or ofdm if rspec is auto selected */
- if (((IS_MCS(rspec[k]) &&
- IS_SINGLE_STREAM(rspec[k] & RSPEC_RATE_MASK)) ||
- IS_OFDM(rspec[k]))
+ /*
+ * apply siso/cdd to single stream mcs's or ofdm
+ * if rspec is auto selected
+ */
+ if (((is_mcs_rate(rspec[k]) &&
+ is_single_stream(rspec[k] & RSPEC_RATE_MASK)) ||
+ is_ofdm_rate(rspec[k]))
&& ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY)
|| !(rspec[k] & RSPEC_OVERRIDE))) {
rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK);
/* For SISO MCS use STBC if possible */
- if (IS_MCS(rspec[k])
+ if (is_mcs_rate(rspec[k])
&& BRCMS_STF_SS_STBC_TX(wlc, scb)) {
u8 stc;
- stc = 1; /* Nss for single stream is always 1 */
- rspec[k] |=
- (PHY_TXC1_MODE_STBC <<
- RSPEC_STF_SHIFT) | (stc <<
- RSPEC_STC_SHIFT);
+ /* Nss for single stream is always 1 */
+ stc = 1;
+ rspec[k] |= (PHY_TXC1_MODE_STBC <<
+ RSPEC_STF_SHIFT) |
+ (stc << RSPEC_STC_SHIFT);
} else
rspec[k] |=
(phyctl1_stf << RSPEC_STF_SHIFT);
}
- /* Is the phy configured to use 40MHZ frames? If so then pick the desired txbw */
- if (CHSPEC_WLC_BW(wlc->chanspec) == BRCMS_40_MHZ) {
+ /*
+ * Is the phy configured to use 40MHZ frames? If
+ * so then pick the desired txbw
+ */
+ if (brcms_chspec_bw(wlc->chanspec) == BRCMS_40_MHZ) {
/* default txbw is 20in40 SB */
mimo_ctlchbw = mimo_txbw =
- CHSPEC_SB_UPPER(BRCMS_BAND_PI_RADIO_CHANSPEC)
+ CHSPEC_SB_UPPER(wlc_phy_chanspec_get(
+ wlc->band->pi))
? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
- if (IS_MCS(rspec[k])) {
+ if (is_mcs_rate(rspec[k])) {
/* mcs 32 must be 40b/w DUP */
- if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
+ if ((rspec[k] & RSPEC_RATE_MASK)
+ == 32) {
mimo_txbw =
PHY_TXC1_BW_40MHZ_DUP;
/* use override */
@@ -3827,66 +7069,61 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
/* else check if dst is using 40 Mhz */
else if (scb->flags & SCB_IS40)
mimo_txbw = PHY_TXC1_BW_40MHZ;
- } else if (IS_OFDM(rspec[k])) {
+ } else if (is_ofdm_rate(rspec[k])) {
if (wlc->ofdm_40txbw != AUTO)
mimo_txbw = wlc->ofdm_40txbw;
- } else {
- if (wlc->cck_40txbw != AUTO)
- mimo_txbw = wlc->cck_40txbw;
+ } else if (wlc->cck_40txbw != AUTO) {
+ mimo_txbw = wlc->cck_40txbw;
}
} else {
- /* mcs32 is 40 b/w only.
- * This is possible for probe packets on a STA during SCAN
+ /*
+ * mcs32 is 40 b/w only.
+ * This is possible for probe packets on
+ * a STA during SCAN
*/
- if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
+ if ((rspec[k] & RSPEC_RATE_MASK) == 32)
/* mcs 0 */
rspec[k] = RSPEC_MIMORATE;
- }
+
mimo_txbw = PHY_TXC1_BW_20MHZ;
}
/* Set channel width */
rspec[k] &= ~RSPEC_BW_MASK;
- if ((k == 0) || ((k > 0) && IS_MCS(rspec[k])))
+ if ((k == 0) || ((k > 0) && is_mcs_rate(rspec[k])))
rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT);
else
rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
- /* Set Short GI */
-#ifdef NOSGIYET
- if (IS_MCS(rspec[k])
- && (txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
- rspec[k] |= RSPEC_SHORT_GI;
- else if (!(txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
- rspec[k] &= ~RSPEC_SHORT_GI;
-#else
+ /* Disable short GI, not supported yet */
rspec[k] &= ~RSPEC_SHORT_GI;
-#endif
mimo_preamble_type = BRCMS_MM_PREAMBLE;
if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD)
mimo_preamble_type = BRCMS_GF_PREAMBLE;
if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
- && (!IS_MCS(rspec[k]))) {
+ && (!is_mcs_rate(rspec[k]))) {
wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_"
- "RC_MCS != IS_MCS(rspec)\n",
- BRCMS_UNIT(wlc), __func__);
+ "RC_MCS != is_mcs_rate(rspec)\n",
+ wlc->pub->unit, __func__);
}
- if (IS_MCS(rspec[k])) {
+ if (is_mcs_rate(rspec[k])) {
preamble_type[k] = mimo_preamble_type;
- /* if SGI is selected, then forced mm for single stream */
+ /*
+ * if SGI is selected, then forced mm
+ * for single stream
+ */
if ((rspec[k] & RSPEC_SHORT_GI)
- && IS_SINGLE_STREAM(rspec[k] &
- RSPEC_RATE_MASK)) {
+ && is_single_stream(rspec[k] &
+ RSPEC_RATE_MASK))
preamble_type[k] = BRCMS_MM_PREAMBLE;
- }
}
/* should be better conditionalized */
- if (!IS_MCS(rspec[0])
+ if (!is_mcs_rate(rspec[0])
&& (tx_info->control.rates[0].
flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
preamble_type[k] = BRCMS_SHORT_PREAMBLE;
@@ -3898,7 +7135,7 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT);
/* for nphy, stf of ofdm frames must follow policies */
- if (BRCMS_ISNPHY(wlc->band) && IS_OFDM(rspec[k])) {
+ if (BRCMS_ISNPHY(wlc->band) && is_ofdm_rate(rspec[k])) {
rspec[k] &= ~RSPEC_STF_MASK;
rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT;
}
@@ -3923,13 +7160,13 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
plcp_fallback, sizeof(txh->FragPLCPFallback));
/* Length field now put in CCK FBR CRC field */
- if (IS_CCK(rspec[1])) {
+ if (is_cck_rate(rspec[1])) {
txh->FragPLCPFallback[4] = phylen & 0xff;
txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8;
}
/* MIMO-RATE: need validation ?? */
- mainrates = IS_OFDM(rspec[0]) ?
+ mainrates = is_ofdm_rate(rspec[0]) ?
D11A_PHY_HDR_GRATE((struct ofdm_phy_hdr *) plcp) :
plcp[0];
@@ -3968,10 +7205,10 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
if (!is_multicast_ether_addr(h->addr1))
mcl |= TXC_IMMEDACK;
- if (BAND_5G(wlc->band->bandtype))
+ if (wlc->band->bandtype == BRCM_BAND_5G)
mcl |= TXC_FREQBAND_5G;
- if (CHSPEC_IS40(BRCMS_BAND_PI_RADIO_CHANSPEC))
+ if (CHSPEC_IS40(wlc_phy_chanspec_get(wlc->band->pi)))
mcl |= TXC_BW_40;
/* set AMIC bit if using hardware TKIP MIC */
@@ -3986,7 +7223,7 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
/* Set fallback rate preamble type */
if ((preamble_type[1] == BRCMS_SHORT_PREAMBLE) ||
(preamble_type[1] == BRCMS_GF_PREAMBLE)) {
- if (RSPEC2RATE(rspec[1]) != BRCM_RATE_1M)
+ if (rspec2rate(rspec[1]) != BRCM_RATE_1M)
mch |= TXC_PREAMBLE_DATA_FB_SHORT;
}
@@ -4002,12 +7239,14 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
/* TxFrameID */
txh->TxFrameID = cpu_to_le16(frameid);
- /* TxStatus, Note the case of recreating the first frag of a suppressed frame
- * then we may need to reset the retry cnt's via the status reg
+ /*
+ * TxStatus, Note the case of recreating the first frag of a suppressed
+ * frame then we may need to reset the retry cnt's via the status reg
*/
txh->TxStatus = cpu_to_le16(status);
- /* extra fields for ucode AMPDU aggregation, the new fields are added to
+ /*
+ * extra fields for ucode AMPDU aggregation, the new fields are added to
* the END of previous structure so that it's compatible in driver.
*/
txh->MaxNMpdus = cpu_to_le16(0);
@@ -4028,15 +7267,15 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
mimo_ctlchbw);
}
- if (!IS_OFDM(rts_rspec[0]) &&
- !((RSPEC2RATE(rts_rspec[0]) == BRCM_RATE_1M) ||
+ if (!is_ofdm_rate(rts_rspec[0]) &&
+ !((rspec2rate(rts_rspec[0]) == BRCM_RATE_1M) ||
(wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
rts_preamble_type[0] = BRCMS_SHORT_PREAMBLE;
mch |= TXC_PREAMBLE_RTS_MAIN_SHORT;
}
- if (!IS_OFDM(rts_rspec[1]) &&
- !((RSPEC2RATE(rts_rspec[1]) == BRCM_RATE_1M) ||
+ if (!is_ofdm_rate(rts_rspec[1]) &&
+ !((rspec2rate(rts_rspec[1]) == BRCM_RATE_1M) ||
(wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
rts_preamble_type[1] = BRCMS_SHORT_PREAMBLE;
mch |= TXC_PREAMBLE_RTS_FB_SHORT;
@@ -4095,7 +7334,7 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
* low 8 bits: main frag rate/mcs,
* high 8 bits: rts/cts rate/mcs
*/
- mainrates |= (IS_OFDM(rts_rspec[0]) ?
+ mainrates |= (is_ofdm_rate(rts_rspec[0]) ?
D11A_PHY_HDR_GRATE(
(struct ofdm_phy_hdr *) rts_plcp) :
rts_plcp[0]) << 8;
@@ -4110,31 +7349,37 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
#ifdef SUPPORT_40MHZ
/* add null delimiter count */
- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && IS_MCS(rspec)) {
+ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && is_mcs_rate(rspec))
txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] =
brcm_c_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen);
- }
+
#endif
- /* Now that RTS/RTS FB preamble types are updated, write the final value */
+ /*
+ * Now that RTS/RTS FB preamble types are updated, write
+ * the final value
+ */
txh->MacTxControlHigh = cpu_to_le16(mch);
- /* MainRates (both the rts and frag plcp rates have been calculated now) */
+ /*
+ * MainRates (both the rts and frag plcp rates have
+ * been calculated now)
+ */
txh->MainRates = cpu_to_le16(mainrates);
/* XtraFrameTypes */
- xfts = FRAMETYPE(rspec[1], wlc->mimoft);
- xfts |= (FRAMETYPE(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT);
- xfts |= (FRAMETYPE(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT);
- xfts |=
- CHSPEC_CHANNEL(BRCMS_BAND_PI_RADIO_CHANSPEC) << XFTS_CHANNEL_SHIFT;
+ xfts = frametype(rspec[1], wlc->mimoft);
+ xfts |= (frametype(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT);
+ xfts |= (frametype(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT);
+ xfts |= CHSPEC_CHANNEL(wlc_phy_chanspec_get(wlc->band->pi)) <<
+ XFTS_CHANNEL_SHIFT;
txh->XtraFrameTypes = cpu_to_le16(xfts);
/* PhyTxControlWord */
- phyctl = FRAMETYPE(rspec[0], wlc->mimoft);
+ phyctl = frametype(rspec[0], wlc->mimoft);
if ((preamble_type[0] == BRCMS_SHORT_PREAMBLE) ||
(preamble_type[0] == BRCMS_GF_PREAMBLE)) {
- if (RSPEC2RATE(rspec[0]) != BRCM_RATE_1M)
+ if (rspec2rate(rspec[0]) != BRCM_RATE_1M)
phyctl |= PHY_TXC_SHORT_HDR;
}
@@ -4159,18 +7404,18 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
}
/*
- * For mcs frames, if mixedmode(overloaded with long preamble) is going to be set,
- * fill in non-zero MModeLen and/or MModeFbrLen
- * it will be unnecessary if they are separated
+ * For mcs frames, if mixedmode(overloaded with long preamble)
+ * is going to be set, fill in non-zero MModeLen and/or
+ * MModeFbrLen it will be unnecessary if they are separated
*/
- if (IS_MCS(rspec[0]) &&
+ if (is_mcs_rate(rspec[0]) &&
(preamble_type[0] == BRCMS_MM_PREAMBLE)) {
u16 mmodelen =
brcms_c_calc_lsig_len(wlc, rspec[0], phylen);
txh->MModeLen = cpu_to_le16(mmodelen);
}
- if (IS_MCS(rspec[1]) &&
+ if (is_mcs_rate(rspec[1]) &&
(preamble_type[1] == BRCMS_MM_PREAMBLE)) {
u16 mmodefbrlen =
brcms_c_calc_lsig_len(wlc, rspec[1], phylen);
@@ -4179,11 +7424,11 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
}
ac = skb_get_queue_mapping(p);
- if (SCB_WME(scb) && qos && wlc->edcf_txop[ac]) {
+ if ((scb->flags & SCB_WMECAP) && qos && wlc->edcf_txop[ac]) {
uint frag_dur, dur, dur_fallback;
/* WME: Update TXOP threshold */
- if ((!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) && (frag == 0)) {
+ if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) && frag == 0) {
frag_dur =
brcms_c_calc_frame_time(wlc, rspec[0],
preamble_type[0], phylen);
@@ -4220,40 +7465,44 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
}
/* NEED to set TxFesTimeNormal (hard) */
txh->TxFesTimeNormal = cpu_to_le16((u16) dur);
- /* NEED to set fallback rate version of TxFesTimeNormal (hard) */
+ /*
+ * NEED to set fallback rate version of
+ * TxFesTimeNormal (hard)
+ */
txh->TxFesTimeFallback =
cpu_to_le16((u16) dur_fallback);
- /* update txop byte threshold (txop minus intraframe overhead) */
+ /*
+ * update txop byte threshold (txop minus intraframe
+ * overhead)
+ */
if (wlc->edcf_txop[ac] >= (dur - frag_dur)) {
- {
- uint newfragthresh;
-
+ uint newfragthresh;
+
+ newfragthresh =
+ brcms_c_calc_frame_len(wlc,
+ rspec[0], preamble_type[0],
+ (wlc->edcf_txop[ac] -
+ (dur - frag_dur)));
+ /* range bound the fragthreshold */
+ if (newfragthresh < DOT11_MIN_FRAG_LEN)
newfragthresh =
- brcms_c_calc_frame_len(wlc,
- rspec[0], preamble_type[0],
- (wlc->edcf_txop[ac] -
- (dur - frag_dur)));
- /* range bound the fragthreshold */
- if (newfragthresh < DOT11_MIN_FRAG_LEN)
- newfragthresh =
- DOT11_MIN_FRAG_LEN;
- else if (newfragthresh >
- wlc->usr_fragthresh)
- newfragthresh =
- wlc->usr_fragthresh;
- /* update the fragthresh and do txc update */
- if (wlc->fragthresh[queue] !=
- (u16) newfragthresh) {
- wlc->fragthresh[queue] =
- (u16) newfragthresh;
- }
- }
- } else
+ DOT11_MIN_FRAG_LEN;
+ else if (newfragthresh >
+ wlc->usr_fragthresh)
+ newfragthresh =
+ wlc->usr_fragthresh;
+ /* update the fragthresh and do txc update */
+ if (wlc->fragthresh[queue] !=
+ (u16) newfragthresh)
+ wlc->fragthresh[queue] =
+ (u16) newfragthresh;
+ } else {
wiphy_err(wlc->wiphy, "wl%d: %s txop invalid "
"for rate %d\n",
wlc->pub->unit, fifo_names[queue],
- RSPEC2RATE(rspec[0]));
+ rspec2rate(rspec[0]));
+ }
if (dur > wlc->edcf_txop[ac])
wiphy_err(wlc->wiphy, "wl%d: %s: %s txop "
@@ -4268,225 +7517,191 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
return 0;
}
-void brcms_c_tbtt(struct brcms_c_info *wlc)
+void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
+ struct ieee80211_hw *hw)
{
- struct brcms_bss_cfg *cfg = wlc->cfg;
-
- if (!cfg->BSS) {
- /* DirFrmQ is now valid...defer setting until end of ATIM window */
- wlc->qvalid |= MCMD_DIRFRMQVAL;
- }
-}
+ u8 prio;
+ uint fifo;
+ struct scb *scb = &wlc->pri_scb;
+ struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data);
-static void brcms_c_war16165(struct brcms_c_info *wlc, bool tx)
-{
- if (tx) {
- /* the post-increment is used in STAY_AWAKE macro */
- if (wlc->txpend16165war++ == 0)
- brcms_c_set_ps_ctrl(wlc);
- } else {
- wlc->txpend16165war--;
- if (wlc->txpend16165war == 0)
- brcms_c_set_ps_ctrl(wlc);
- }
+ /*
+ * 802.11 standard requires management traffic
+ * to go at highest priority
+ */
+ prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority :
+ MAXPRIO;
+ fifo = prio2fifo[prio];
+ if (brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0))
+ return;
+ brcms_c_txq_enq(wlc, scb, sdu, BRCMS_PRIO_TO_PREC(prio));
+ brcms_c_send_q(wlc);
}
-/* process an individual struct tx_status */
-bool
-brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs, u32 frm_tx2)
+void brcms_c_send_q(struct brcms_c_info *wlc)
{
- struct sk_buff *p;
- uint queue;
- struct d11txh *txh;
- struct scb *scb = NULL;
- bool free_pdu;
- int tx_rts, tx_frame_count, tx_rts_count;
- uint totlen, supr_status;
- bool lastframe;
- struct ieee80211_hdr *h;
- u16 mcl;
+ struct sk_buff *pkt[DOT11_MAXNUMFRAGS];
+ int prec;
+ u16 prec_map;
+ int err = 0, i, count;
+ uint fifo;
+ struct brcms_txq_info *qi = wlc->pkt_queue;
+ struct pktq *q = &qi->q;
struct ieee80211_tx_info *tx_info;
- struct ieee80211_tx_rate *txrate;
- int i;
- (void)(frm_tx2); /* Compiler reference to avoid unused variable warning */
+ prec_map = wlc->tx_prec_map;
- /* discard intermediate indications for ucode with one legitimate case:
- * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
- * tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
- * transmission count)
+ /* Send all the enq'd pkts that we can.
+ * Dequeue packets with precedence with empty HW fifo only
*/
- if (!(txs->status & TX_STATUS_AMPDU)
- && (txs->status & TX_STATUS_INTERMEDIATE)) {
- wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
- __func__);
- return false;
- }
+ while (prec_map && (pkt[0] = brcmu_pktq_mdeq(q, prec_map, &prec))) {
+ tx_info = IEEE80211_SKB_CB(pkt[0]);
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+ err = brcms_c_sendampdu(wlc->ampdu, qi, pkt, prec);
+ } else {
+ count = 1;
+ err = brcms_c_prep_pdu(wlc, pkt[0], &fifo);
+ if (!err) {
+ for (i = 0; i < count; i++)
+ brcms_c_txfifo(wlc, fifo, pkt[i], true,
+ 1);
+ }
+ }
- queue = txs->frameid & TXFID_QUEUE_MASK;
- if (queue >= NFIFO) {
- p = NULL;
- goto fatal;
+ if (err == -EBUSY) {
+ brcmu_pktq_penq_head(q, prec, pkt[0]);
+ /*
+ * If send failed due to any other reason than a
+ * change in HW FIFO condition, quit. Otherwise,
+ * read the new prec_map!
+ */
+ if (prec_map == wlc->tx_prec_map)
+ break;
+ prec_map = wlc->tx_prec_map;
+ }
}
+}
- p = GETNEXTTXP(wlc, queue);
- if (BRCMS_WAR16165(wlc))
- brcms_c_war16165(wlc, false);
- if (p == NULL)
- goto fatal;
+void
+brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p,
+ bool commit, s8 txpktpend)
+{
+ u16 frameid = INVALIDFID;
+ struct d11txh *txh;
txh = (struct d11txh *) (p->data);
- mcl = le16_to_cpu(txh->MacTxControlLow);
-
- if (txs->phyerr) {
- if (WL_ERROR_ON()) {
- wiphy_err(wlc->wiphy, "phyerr 0x%x, rate 0x%x\n",
- txs->phyerr, txh->MainRates);
- brcms_c_print_txdesc(txh);
- }
- brcms_c_print_txstatus(txs);
- }
- if (txs->frameid != cpu_to_le16(txh->TxFrameID))
- goto fatal;
- tx_info = IEEE80211_SKB_CB(p);
- h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
-
- if (tx_info->control.sta)
- scb = (struct scb *)tx_info->control.sta->drv_priv;
+ /* When a BC/MC frame is being committed to the BCMC fifo
+ * via DMA (NOT PIO), update ucode or BSS info as appropriate.
+ */
+ if (fifo == TX_BCMC_FIFO)
+ frameid = le16_to_cpu(txh->TxFrameID);
- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
- brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
- return false;
+ /*
+ * Bump up pending count for if not using rpc. If rpc is
+ * used, this will be handled in brcms_b_txfifo()
+ */
+ if (commit) {
+ wlc->core->txpktpend[fifo] += txpktpend;
+ BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n",
+ txpktpend, wlc->core->txpktpend[fifo]);
}
- supr_status = txs->status & TX_STATUS_SUPR_MASK;
- if (supr_status == TX_STATUS_SUPR_BADCH)
- BCMMSG(wlc->wiphy,
- "%s: Pkt tx suppressed, possibly channel %d\n",
- __func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec));
+ /* Commit BCMC sequence number in the SHM frame ID location */
+ if (frameid != INVALIDFID) {
+ /*
+ * To inform the ucode of the last mcast frame posted
+ * so that it can clear moredata bit
+ */
+ brcms_b_write_shm(wlc->hw, M_BCMC_FID, frameid);
+ }
- tx_rts = cpu_to_le16(txh->MacTxControlLow) & TXC_SENDRTS;
- tx_frame_count =
- (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT;
- tx_rts_count =
- (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT;
+ if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0)
+ wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n");
+}
- lastframe = !ieee80211_has_morefrags(h->frame_control);
+u32
+brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
+ bool use_rspec, u16 mimo_ctlchbw)
+{
+ u32 rts_rspec = 0;
- if (!lastframe) {
- wiphy_err(wlc->wiphy, "Not last frame!\n");
- } else {
- /*
- * Set information to be consumed by Minstrel ht.
- *
- * The "fallback limit" is the number of tx attempts a given
- * MPDU is sent at the "primary" rate. Tx attempts beyond that
- * limit are sent at the "secondary" rate.
- * A 'short frame' does not exceed RTS treshold.
+ if (use_rspec)
+ /* use frame rate as rts rate */
+ rts_rspec = rspec;
+ else if (wlc->band->gmode && wlc->protection->_g && !is_cck_rate(rspec))
+ /* Use 11Mbps as the g protection RTS target rate and fallback.
+ * Use the brcms_basic_rate() lookup to find the best basic rate
+ * under the target in case 11 Mbps is not Basic.
+ * 6 and 9 Mbps are not usually selected by rate selection, but
+ * even if the OFDM rate we are protecting is 6 or 9 Mbps, 11
+ * is more robust.
*/
- u16 sfbl, /* Short Frame Rate Fallback Limit */
- lfbl, /* Long Frame Rate Fallback Limit */
- fbl;
+ rts_rspec = brcms_basic_rate(wlc, BRCM_RATE_11M);
+ else
+ /* calculate RTS rate and fallback rate based on the frame rate
+ * RTS must be sent at a basic rate since it is a
+ * control frame, sec 9.6 of 802.11 spec
+ */
+ rts_rspec = brcms_basic_rate(wlc, rspec);
- if (queue < AC_COUNT) {
- sfbl = BRCMS_WME_RETRY_SFB_GET(wlc, wme_fifo2ac[queue]);
- lfbl = BRCMS_WME_RETRY_LFB_GET(wlc, wme_fifo2ac[queue]);
- } else {
- sfbl = wlc->SFBL;
- lfbl = wlc->LFBL;
- }
+ if (BRCMS_PHY_11N_CAP(wlc->band)) {
+ /* set rts txbw to correct side band */
+ rts_rspec &= ~RSPEC_BW_MASK;
- txrate = tx_info->status.rates;
- if (txrate[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
- fbl = lfbl;
+ /*
+ * if rspec/rspec_fallback is 40MHz, then send RTS on both
+ * 20MHz channel (DUP), otherwise send RTS on control channel
+ */
+ if (rspec_is40mhz(rspec) && !is_cck_rate(rts_rspec))
+ rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT);
else
- fbl = sfbl;
-
- ieee80211_tx_info_clear_status(tx_info);
-
- if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) {
- /* rate selection requested a fallback rate and we used it */
- txrate[0].count = fbl;
- txrate[1].count = tx_frame_count - fbl;
- } else {
- /* rate selection did not request fallback rate, or we didn't need it */
- txrate[0].count = tx_frame_count;
- /* rc80211_minstrel.c:minstrel_tx_status() expects unused rates to be marked with idx = -1 */
- txrate[1].idx = -1;
- txrate[1].count = 0;
- }
+ rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
- /* clear the rest of the rates */
- for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
- txrate[i].idx = -1;
- txrate[i].count = 0;
+ /* pick siso/cdd as default for ofdm */
+ if (is_ofdm_rate(rts_rspec)) {
+ rts_rspec &= ~RSPEC_STF_MASK;
+ rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
}
-
- if (txs->status & TX_STATUS_ACK_RCV)
- tx_info->flags |= IEEE80211_TX_STAT_ACK;
- }
-
- totlen = brcmu_pkttotlen(p);
- free_pdu = true;
-
- brcms_c_txfifo_complete(wlc, queue, 1);
-
- if (lastframe) {
- p->next = NULL;
- p->prev = NULL;
- /* remove PLCP & Broadcom tx descriptor header */
- skb_pull(p, D11_PHY_HDR_LEN);
- skb_pull(p, D11_TXH_LEN);
- ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p);
- } else {
- wiphy_err(wlc->wiphy, "%s: Not last frame => not calling "
- "tx_status\n", __func__);
}
-
- return false;
-
- fatal:
- if (p)
- brcmu_pkt_buf_free_skb(p);
-
- return true;
-
+ return rts_rspec;
}
void
brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend)
{
- TXPKTPENDDEC(wlc, fifo, txpktpend);
+ wlc->core->txpktpend[fifo] -= txpktpend;
BCMMSG(wlc->wiphy, "pktpend dec %d to %d\n", txpktpend,
- TXPKTPENDGET(wlc, fifo));
+ wlc->core->txpktpend[fifo]);
/* There is more room; mark precedences related to this FIFO sendable */
- BRCMS_TX_FIFO_ENAB(wlc, fifo);
-
- /* Clear MHF2_TXBCMC_NOW flag if BCMC fifo has drained */
- if (AP_ENAB(wlc->pub) &&
- !TXPKTPENDGET(wlc, TX_BCMC_FIFO)) {
- brcms_c_mhf(wlc, MHF2, MHF2_TXBCMC_NOW, 0, BRCM_BAND_AUTO);
- }
+ wlc->tx_prec_map |= wlc->fifo2prec_map[fifo];
/* figure out which bsscfg is being worked on... */
}
/* Update beacon listen interval in shared memory */
-void brcms_c_bcn_li_upd(struct brcms_c_info *wlc)
+static void brcms_c_bcn_li_upd(struct brcms_c_info *wlc)
{
- if (AP_ENAB(wlc->pub))
- return;
-
/* wake up every DTIM is the default */
if (wlc->bcn_li_dtim == 1)
- brcms_c_write_shm(wlc, M_BCN_LI, 0);
+ brcms_b_write_shm(wlc->hw, M_BCN_LI, 0);
else
- brcms_c_write_shm(wlc, M_BCN_LI,
+ brcms_b_write_shm(wlc->hw, M_BCN_LI,
(wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn);
}
+static void
+brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
+ u32 *tsf_h_ptr)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+
+ /* read the tsf timer low, then high to get an atomic read */
+ *tsf_l_ptr = R_REG(&regs->tsf_timerlow);
+ *tsf_h_ptr = R_REG(&regs->tsf_timerhigh);
+}
+
/*
* recover 64bit TSF value from the 16bit TSF value in the rx header
* given the assumption that the TSF passed in header is within 65ms
@@ -4502,7 +7717,7 @@ void brcms_c_bcn_li_upd(struct brcms_c_info *wlc)
* are used. Finally, the tsf_h is read from the tsf register.
*/
static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc,
- struct brcms_d11rxhdr *rxh)
+ struct d11rxhdr *rxh)
{
u32 tsf_h, tsf_l;
u16 rx_tsf_0_15, rx_tsf_16_31;
@@ -4510,7 +7725,7 @@ static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc,
brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h);
rx_tsf_16_31 = (u16)(tsf_l >> 16);
- rx_tsf_0_15 = rxh->rxhdr.RxTSFTime;
+ rx_tsf_0_15 = rxh->RxTSFTime;
/*
* a greater tsf time indicates the low 16 bits of
@@ -4530,14 +7745,13 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
struct sk_buff *p,
struct ieee80211_rx_status *rx_status)
{
- struct brcms_d11rxhdr *wlc_rxh = (struct brcms_d11rxhdr *) rxh;
int preamble;
int channel;
- ratespec_t rspec;
+ u32 rspec;
unsigned char *plcp;
/* fill in TSF and flag its presence */
- rx_status->mactime = brcms_c_recover_tsf64(wlc, wlc_rxh);
+ rx_status->mactime = brcms_c_recover_tsf64(wlc, rxh);
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
channel = BRCMS_CHAN_CHANNEL(rxh->RxChan);
@@ -4552,22 +7766,23 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
rx_status->freq = ieee80211_dsss_chan_to_freq(channel);
}
- rx_status->signal = wlc_rxh->rssi; /* signal */
+ rx_status->signal = wlc_phy_rssi_compute(wlc->hw->band->pi, rxh);
/* noise */
/* qual */
- rx_status->antenna = (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0; /* ant */
+ rx_status->antenna =
+ (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;
plcp = p->data;
rspec = brcms_c_compute_rspec(rxh, plcp);
- if (IS_MCS(rspec)) {
+ if (is_mcs_rate(rspec)) {
rx_status->rate_idx = rspec & RSPEC_RATE_MASK;
rx_status->flag |= RX_FLAG_HT;
- if (RSPEC_IS40MHZ(rspec))
+ if (rspec_is40mhz(rspec))
rx_status->flag |= RX_FLAG_40MHZ;
} else {
- switch (RSPEC2RATE(rspec)) {
+ switch (rspec2rate(rspec)) {
case BRCM_RATE_1M:
rx_status->rate_idx = 0;
break;
@@ -4618,10 +7833,10 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
/* Determine short preamble and rate_idx */
preamble = 0;
- if (IS_CCK(rspec)) {
+ if (is_cck_rate(rspec)) {
if (rxh->PhyRxStatus_0 & PRXS0_SHORTH)
rx_status->flag |= RX_FLAG_SHORTPRE;
- } else if (IS_OFDM(rspec)) {
+ } else if (is_ofdm_rate(rspec)) {
rx_status->flag |= RX_FLAG_SHORTPRE;
} else {
wiphy_err(wlc->wiphy, "%s: Unknown modulation\n",
@@ -4629,7 +7844,7 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
}
}
- if (PLCP3_ISSGI(plcp[3]))
+ if (plcp3_issgi(plcp[3]))
rx_status->flag |= RX_FLAG_SHORT_GI;
if (rxh->RxStatus1 & RXS_DECERR) {
@@ -4661,102 +7876,6 @@ brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
- return;
-}
-
-/* Process received frames */
-/*
- * Return true if more frames need to be processed. false otherwise.
- * Param 'bound' indicates max. # frames to process before break out.
- */
-void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
-{
- struct d11rxhdr *rxh;
- struct ieee80211_hdr *h;
- uint len;
- bool is_amsdu;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
- /* frame starts with rxhdr */
- rxh = (struct d11rxhdr *) (p->data);
-
- /* strip off rxhdr */
- skb_pull(p, BRCMS_HWRXOFF);
-
- /* fixup rx header endianness */
- rxh->RxFrameSize = le16_to_cpu(rxh->RxFrameSize);
- rxh->PhyRxStatus_0 = le16_to_cpu(rxh->PhyRxStatus_0);
- rxh->PhyRxStatus_1 = le16_to_cpu(rxh->PhyRxStatus_1);
- rxh->PhyRxStatus_2 = le16_to_cpu(rxh->PhyRxStatus_2);
- rxh->PhyRxStatus_3 = le16_to_cpu(rxh->PhyRxStatus_3);
- rxh->PhyRxStatus_4 = le16_to_cpu(rxh->PhyRxStatus_4);
- rxh->PhyRxStatus_5 = le16_to_cpu(rxh->PhyRxStatus_5);
- rxh->RxStatus1 = le16_to_cpu(rxh->RxStatus1);
- rxh->RxStatus2 = le16_to_cpu(rxh->RxStatus2);
- rxh->RxTSFTime = le16_to_cpu(rxh->RxTSFTime);
- rxh->RxChan = le16_to_cpu(rxh->RxChan);
-
- /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
- if (rxh->RxStatus1 & RXS_PBPRES) {
- if (p->len < 2) {
- wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of "
- "len %d\n", wlc->pub->unit, p->len);
- goto toss;
- }
- skb_pull(p, 2);
- }
-
- h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN);
- len = p->len;
-
- if (rxh->RxStatus1 & RXS_FCSERR) {
- if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) {
- wiphy_err(wlc->wiphy, "FCSERR while scanning******* -"
- " tossing\n");
- goto toss;
- } else {
- wiphy_err(wlc->wiphy, "RCSERR!!!\n");
- goto toss;
- }
- }
-
- /* check received pkt has at least frame control field */
- if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control)) {
- goto toss;
- }
-
- is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
-
- /* explicitly test bad src address to avoid sending bad deauth */
- if (!is_amsdu) {
- /* CTS and ACK CTL frames are w/o a2 */
-
- if (ieee80211_is_data(h->frame_control) ||
- ieee80211_is_mgmt(h->frame_control)) {
- if ((is_zero_ether_addr(h->addr2) ||
- is_multicast_ether_addr(h->addr2))) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dropping a "
- "frame with invalid src mac address,"
- " a2: %pM\n",
- wlc->pub->unit, __func__, h->addr2);
- goto toss;
- }
- }
- }
-
- /* due to sheer numbers, toss out probe reqs for now */
- if (ieee80211_is_probe_req(h->frame_control))
- goto toss;
-
- if (is_amsdu)
- goto toss;
-
- brcms_c_recvctl(wlc, rxh, p);
- return;
-
- toss:
- brcmu_pkt_buf_free_skb(p);
}
/* calculate frame duration for Mixed-mode L-SIG spoofing, return
@@ -4766,76 +7885,28 @@ void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
* len = 3(nsyms + nstream + 3) - 3
*/
u16
-brcms_c_calc_lsig_len(struct brcms_c_info *wlc, ratespec_t ratespec,
+brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
uint mac_len)
{
uint nsyms, len = 0, kNdps;
BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n",
- wlc->pub->unit, RSPEC2RATE(ratespec), mac_len);
-
- if (IS_MCS(ratespec)) {
- uint mcs = ratespec & RSPEC_RATE_MASK;
- /* MCS_TXS(mcs) returns num tx streams - 1 */
- int tot_streams = (MCS_TXS(mcs) + 1) + RSPEC_STC(ratespec);
-
- /* the payload duration calculation matches that of regular ofdm */
- /* 1000Ndbps = kbps * 4 */
- kNdps =
- MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
- RSPEC_ISSGI(ratespec)) * 4;
-
- if (RSPEC_STC(ratespec) == 0)
- /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
- nsyms =
- CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
- APHY_TAIL_NBITS) * 1000, kNdps);
- else
- /* STBC needs to have even number of symbols */
- nsyms =
- 2 *
- CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
- APHY_TAIL_NBITS) * 1000, 2 * kNdps);
-
- nsyms += (tot_streams + 3); /* (+3) account for HT-SIG(2) and HT-STF(1) */
- /* 3 bytes/symbol @ legacy 6Mbps rate */
- len = (3 * nsyms) - 3; /* (-3) excluding service bits and tail bits */
- }
+ wlc->pub->unit, rspec2rate(ratespec), mac_len);
- return (u16) len;
-}
-
-/* calculate frame duration of a given rate and length, return time in usec unit */
-uint
-brcms_c_calc_frame_time(struct brcms_c_info *wlc, ratespec_t ratespec,
- u8 preamble_type, uint mac_len)
-{
- uint nsyms, dur = 0, Ndps, kNdps;
- uint rate = RSPEC2RATE(ratespec);
-
- if (rate == 0) {
- wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n",
- wlc->pub->unit);
- rate = BRCM_RATE_1M;
- }
-
- BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n",
- wlc->pub->unit, ratespec, preamble_type, mac_len);
-
- if (IS_MCS(ratespec)) {
+ if (is_mcs_rate(ratespec)) {
uint mcs = ratespec & RSPEC_RATE_MASK;
- int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
+ int tot_streams = (mcs_2_txstreams(mcs) + 1) +
+ rspec_stc(ratespec);
- dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
- if (preamble_type == BRCMS_MM_PREAMBLE)
- dur += PREN_MM_EXT;
+ /*
+ * the payload duration calculation matches that
+ * of regular ofdm
+ */
/* 1000Ndbps = kbps * 4 */
- kNdps =
- MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
- RSPEC_ISSGI(ratespec)) * 4;
+ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
+ rspec_issgi(ratespec)) * 4;
- if (RSPEC_STC(ratespec) == 0)
- /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
+ if (rspec_stc(ratespec) == 0)
nsyms =
CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
APHY_TAIL_NBITS) * 1000, kNdps);
@@ -4846,398 +7917,62 @@ brcms_c_calc_frame_time(struct brcms_c_info *wlc, ratespec_t ratespec,
CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
APHY_TAIL_NBITS) * 1000, 2 * kNdps);
- dur += APHY_SYMBOL_TIME * nsyms;
- if (BAND_2G(wlc->band->bandtype))
- dur += DOT11_OFDM_SIGNAL_EXTENSION;
- } else if (IS_OFDM(rate)) {
- dur = APHY_PREAMBLE_TIME;
- dur += APHY_SIGNAL_TIME;
- /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
- Ndps = rate * 2;
- /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
- nsyms =
- CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
- Ndps);
- dur += APHY_SYMBOL_TIME * nsyms;
- if (BAND_2G(wlc->band->bandtype))
- dur += DOT11_OFDM_SIGNAL_EXTENSION;
- } else {
- /* calc # bits * 2 so factor of 2 in rate (1/2 mbps) will divide out */
- mac_len = mac_len * 8 * 2;
- /* calc ceiling of bits/rate = microseconds of air time */
- dur = (mac_len + rate - 1) / rate;
- if (preamble_type & BRCMS_SHORT_PREAMBLE)
- dur += BPHY_PLCP_SHORT_TIME;
- else
- dur += BPHY_PLCP_TIME;
- }
- return dur;
-}
-
-/* The opposite of brcms_c_calc_frame_time */
-static uint
-brcms_c_calc_frame_len(struct brcms_c_info *wlc, ratespec_t ratespec,
- u8 preamble_type, uint dur)
-{
- uint nsyms, mac_len, Ndps, kNdps;
- uint rate = RSPEC2RATE(ratespec);
-
- BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, dur %d\n",
- wlc->pub->unit, ratespec, preamble_type, dur);
-
- if (IS_MCS(ratespec)) {
- uint mcs = ratespec & RSPEC_RATE_MASK;
- int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
- dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
- /* payload calculation matches that of regular ofdm */
- if (BAND_2G(wlc->band->bandtype))
- dur -= DOT11_OFDM_SIGNAL_EXTENSION;
- /* kNdbps = kbps * 4 */
- kNdps =
- MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
- RSPEC_ISSGI(ratespec)) * 4;
- nsyms = dur / APHY_SYMBOL_TIME;
- mac_len =
- ((nsyms * kNdps) -
- ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000;
- } else if (IS_OFDM(ratespec)) {
- dur -= APHY_PREAMBLE_TIME;
- dur -= APHY_SIGNAL_TIME;
- /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
- Ndps = rate * 2;
- nsyms = dur / APHY_SYMBOL_TIME;
- mac_len =
- ((nsyms * Ndps) -
- (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8;
- } else {
- if (preamble_type & BRCMS_SHORT_PREAMBLE)
- dur -= BPHY_PLCP_SHORT_TIME;
- else
- dur -= BPHY_PLCP_TIME;
- mac_len = dur * rate;
- /* divide out factor of 2 in rate (1/2 mbps) */
- mac_len = mac_len / 8 / 2;
- }
- return mac_len;
-}
-
-static uint
-brcms_c_calc_ba_time(struct brcms_c_info *wlc, ratespec_t rspec,
- u8 preamble_type)
-{
- BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, "
- "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type);
- /* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than
- * or equal to the rate of the immediately previous frame in the FES
- */
- rspec = BRCMS_BASIC_RATE(wlc, rspec);
- /* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */
- return brcms_c_calc_frame_time(wlc, rspec, preamble_type,
- (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN +
- FCS_LEN));
-}
-
-static uint
-brcms_c_calc_ack_time(struct brcms_c_info *wlc, ratespec_t rspec,
- u8 preamble_type)
-{
- uint dur = 0;
-
- BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n",
- wlc->pub->unit, rspec, preamble_type);
- /* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than
- * or equal to the rate of the immediately previous frame in the FES
- */
- rspec = BRCMS_BASIC_RATE(wlc, rspec);
- /* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */
- dur =
- brcms_c_calc_frame_time(wlc, rspec, preamble_type,
- (DOT11_ACK_LEN + FCS_LEN));
- return dur;
-}
-
-static uint
-brcms_c_calc_cts_time(struct brcms_c_info *wlc, ratespec_t rspec,
- u8 preamble_type)
-{
- BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n",
- wlc->pub->unit, rspec, preamble_type);
- return brcms_c_calc_ack_time(wlc, rspec, preamble_type);
-}
-
-/* derive wlc->band->basic_rate[] table from 'rateset' */
-void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, wlc_rateset_t *rateset)
-{
- u8 rate;
- u8 mandatory;
- u8 cck_basic = 0;
- u8 ofdm_basic = 0;
- u8 *br = wlc->band->basic_rate;
- uint i;
-
- /* incoming rates are in 500kbps units as in 802.11 Supported Rates */
- memset(br, 0, BRCM_MAXRATE + 1);
-
- /* For each basic rate in the rates list, make an entry in the
- * best basic lookup.
- */
- for (i = 0; i < rateset->count; i++) {
- /* only make an entry for a basic rate */
- if (!(rateset->rates[i] & BRCMS_RATE_FLAG))
- continue;
-
- /* mask off basic bit */
- rate = (rateset->rates[i] & BRCMS_RATE_MASK);
-
- if (rate > BRCM_MAXRATE) {
- wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: "
- "invalid rate 0x%X in rate set\n",
- rateset->rates[i]);
- continue;
- }
-
- br[rate] = rate;
- }
-
- /* The rate lookup table now has non-zero entries for each
- * basic rate, equal to the basic rate: br[basicN] = basicN
- *
- * To look up the best basic rate corresponding to any
- * particular rate, code can use the basic_rate table
- * like this
- *
- * basic_rate = wlc->band->basic_rate[tx_rate]
- *
- * Make sure there is a best basic rate entry for
- * every rate by walking up the table from low rates
- * to high, filling in holes in the lookup table
- */
-
- for (i = 0; i < wlc->band->hw_rateset.count; i++) {
- rate = wlc->band->hw_rateset.rates[i];
-
- if (br[rate] != 0) {
- /* This rate is a basic rate.
- * Keep track of the best basic rate so far by
- * modulation type.
- */
- if (IS_OFDM(rate))
- ofdm_basic = rate;
- else
- cck_basic = rate;
-
- continue;
- }
-
- /* This rate is not a basic rate so figure out the
- * best basic rate less than this rate and fill in
- * the hole in the table
- */
-
- br[rate] = IS_OFDM(rate) ? ofdm_basic : cck_basic;
-
- if (br[rate] != 0)
- continue;
-
- if (IS_OFDM(rate)) {
- /* In 11g and 11a, the OFDM mandatory rates are 6, 12, and 24 Mbps */
- if (rate >= BRCM_RATE_24M)
- mandatory = BRCM_RATE_24M;
- else if (rate >= BRCM_RATE_12M)
- mandatory = BRCM_RATE_12M;
- else
- mandatory = BRCM_RATE_6M;
- } else {
- /* In 11b, all the CCK rates are mandatory 1 - 11 Mbps */
- mandatory = rate;
- }
-
- br[rate] = mandatory;
- }
-}
-
-static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate,
- u8 basic_rate)
-{
- u8 phy_rate, index;
- u8 basic_phy_rate, basic_index;
- u16 dir_table, basic_table;
- u16 basic_ptr;
-
- /* Shared memory address for the table we are reading */
- dir_table = IS_OFDM(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
-
- /* Shared memory address for the table we are writing */
- basic_table = IS_OFDM(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
-
- /*
- * for a given rate, the LS-nibble of the PLCP SIGNAL field is
- * the index into the rate table.
- */
- phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
- basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK;
- index = phy_rate & 0xf;
- basic_index = basic_phy_rate & 0xf;
-
- /* Find the SHM pointer to the ACK rate entry by looking in the
- * Direct-map Table
- */
- basic_ptr = brcms_c_read_shm(wlc, (dir_table + basic_index * 2));
-
- /* Update the SHM BSS-basic-rate-set mapping table with the pointer
- * to the correct basic rate for the given incoming rate
- */
- brcms_c_write_shm(wlc, (basic_table + index * 2), basic_ptr);
-}
-
-static const wlc_rateset_t *brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc)
-{
- const wlc_rateset_t *rs_dflt;
-
- if (BRCMS_PHY_11N_CAP(wlc->band)) {
- if (BAND_5G(wlc->band->bandtype))
- rs_dflt = &ofdm_mimo_rates;
- else
- rs_dflt = &cck_ofdm_mimo_rates;
- } else if (wlc->band->gmode)
- rs_dflt = &cck_ofdm_rates;
- else
- rs_dflt = &cck_rates;
-
- return rs_dflt;
-}
-
-void brcms_c_set_ratetable(struct brcms_c_info *wlc)
-{
- const wlc_rateset_t *rs_dflt;
- wlc_rateset_t rs;
- u8 rate, basic_rate;
- uint i;
-
- rs_dflt = brcms_c_rateset_get_hwrs(wlc);
-
- brcms_c_rateset_copy(rs_dflt, &rs);
- brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
-
- /* walk the phy rate table and update SHM basic rate lookup table */
- for (i = 0; i < rs.count; i++) {
- rate = rs.rates[i] & BRCMS_RATE_MASK;
-
- /* for a given rate BRCMS_BASIC_RATE returns the rate at
- * which a response ACK/CTS should be sent.
+ /* (+3) account for HT-SIG(2) and HT-STF(1) */
+ nsyms += (tot_streams + 3);
+ /*
+ * 3 bytes/symbol @ legacy 6Mbps rate
+ * (-3) excluding service bits and tail bits
*/
- basic_rate = BRCMS_BASIC_RATE(wlc, rate);
- if (basic_rate == 0) {
- /* This should only happen if we are using a
- * restricted rateset.
- */
- basic_rate = rs.rates[0] & BRCMS_RATE_MASK;
- }
-
- brcms_c_write_rate_shm(wlc, rate, basic_rate);
- }
-}
-
-/*
- * Return true if the specified rate is supported by the specified band.
- * BRCM_BAND_AUTO indicates the current band.
- */
-bool brcms_c_valid_rate(struct brcms_c_info *wlc, ratespec_t rspec, int band,
- bool verbose)
-{
- wlc_rateset_t *hw_rateset;
- uint i;
-
- if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype)) {
- hw_rateset = &wlc->band->hw_rateset;
- } else if (NBANDS(wlc) > 1) {
- hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
- } else {
- /* other band specified and we are a single band device */
- return false;
+ len = (3 * nsyms) - 3;
}
- /* check if this is a mimo rate */
- if (IS_MCS(rspec)) {
- if (!VALID_MCS((rspec & RSPEC_RATE_MASK)))
- goto error;
-
- return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
- }
-
- for (i = 0; i < hw_rateset->count; i++)
- if (hw_rateset->rates[i] == RSPEC2RATE(rspec))
- return true;
- error:
- if (verbose) {
- wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x "
- "not in hw_rateset\n", wlc->pub->unit, rspec);
- }
-
- return false;
-}
-
-static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap)
-{
- uint i;
- struct brcms_band *band;
-
- for (i = 0; i < NBANDS(wlc); i++) {
- if (IS_SINGLEBAND_5G(wlc->deviceid))
- i = BAND_5G_INDEX;
- band = wlc->bandstate[i];
- if (band->bandtype == BRCM_BAND_5G) {
- if ((bwcap == BRCMS_N_BW_40ALL)
- || (bwcap == BRCMS_N_BW_20IN2G_40IN5G))
- band->mimo_cap_40 = true;
- else
- band->mimo_cap_40 = false;
- } else {
- if (bwcap == BRCMS_N_BW_40ALL)
- band->mimo_cap_40 = true;
- else
- band->mimo_cap_40 = false;
- }
- }
+ return (u16) len;
}
-void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
+static void
+brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
{
- const wlc_rateset_t *rs_dflt;
- wlc_rateset_t rs;
+ const struct brcms_c_rateset *rs_dflt;
+ struct brcms_c_rateset rs;
u8 rate;
u16 entry_ptr;
u8 plcp[D11_PHY_HDR_LEN];
u16 dur, sifs;
uint i;
- sifs = SIFS(wlc->band);
+ sifs = get_sifs(wlc->band);
rs_dflt = brcms_c_rateset_get_hwrs(wlc);
brcms_c_rateset_copy(rs_dflt, &rs);
brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
- /* walk the phy rate table and update MAC core SHM basic rate table entries */
+ /*
+ * walk the phy rate table and update MAC core SHM
+ * basic rate table entries
+ */
for (i = 0; i < rs.count; i++) {
rate = rs.rates[i] & BRCMS_RATE_MASK;
- entry_ptr = brcms_c_rate_shm_offset(wlc, rate);
+ entry_ptr = brcms_b_rate_shm_offset(wlc->hw, rate);
/* Calculate the Probe Response PLCP for the given rate */
brcms_c_compute_plcp(wlc, rate, frame_len, plcp);
- /* Calculate the duration of the Probe Response frame plus SIFS for the MAC */
+ /*
+ * Calculate the duration of the Probe Response
+ * frame plus SIFS for the MAC
+ */
dur = (u16) brcms_c_calc_frame_time(wlc, rate,
BRCMS_LONG_PREAMBLE, frame_len);
dur += sifs;
/* Update the SHM Rate Table entry Probe Response values */
- brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS,
+ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS,
(u16) (plcp[0] + (plcp[1] << 8)));
- brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS + 2,
+ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS + 2,
(u16) (plcp[2] + (plcp[3] << 8)));
- brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_DUR_POS, dur);
+ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_DUR_POS, dur);
}
}
@@ -5250,12 +7985,12 @@ void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
*
* *len on input contains the max length of the packet available.
*
- * The *len value is set to the number of bytes in buf used, and starts with the PLCP
- * and included up to, but not including, the 4 byte FCS.
+ * The *len value is set to the number of bytes in buf used, and starts
+ * with the PLCP and included up to, but not including, the 4 byte FCS.
*/
static void
brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
- ratespec_t bcn_rspec,
+ u32 bcn_rspec,
struct brcms_bss_cfg *cfg, u16 *buf, int *len)
{
static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
@@ -5263,36 +7998,33 @@ brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
struct ieee80211_mgmt *h;
int hdr_len, body_len;
- if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
- hdr_len = DOT11_MAC_HDR_LEN;
- else
- hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
- body_len = *len - hdr_len; /* calc buffer size provided for frame body */
+ hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
- *len = hdr_len + body_len; /* return actual size */
+ /* calc buffer size provided for frame body */
+ body_len = *len - hdr_len;
+ /* return actual size */
+ *len = hdr_len + body_len;
/* format PHY and MAC headers */
memset((char *)buf, 0, hdr_len);
plcp = (struct cck_phy_hdr *) buf;
- /* PLCP for Probe Response frames are filled in from core's rate table */
- if (type == IEEE80211_STYPE_BEACON && !MBSS_BCN_ENAB(cfg)) {
+ /*
+ * PLCP for Probe Response frames are filled in from
+ * core's rate table
+ */
+ if (type == IEEE80211_STYPE_BEACON)
/* fill in PLCP */
brcms_c_compute_plcp(wlc, bcn_rspec,
(DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
(u8 *) plcp);
- }
/* "Regular" and 16 MBSS but not for 4 MBSS */
/* Update the phytxctl for the beacon based on the rspec */
- if (!SOFTBCN_ENAB(cfg))
- brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
+ brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
- if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
- h = (struct ieee80211_mgmt *)&plcp[0];
- else
- h = (struct ieee80211_mgmt *)&plcp[1];
+ h = (struct ieee80211_mgmt *)&plcp[1];
/* fill in 802.11 header */
h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
@@ -5305,80 +8037,28 @@ brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
/* SEQ filled in by MAC */
-
- return;
}
-int brcms_c_get_header_len()
+int brcms_c_get_header_len(void)
{
return TXOFF;
}
-/* Update a beacon for a particular BSS
- * For MBSS, this updates the software template and sets "latest" to the index of the
- * template updated.
- * Otherwise, it updates the hardware template.
- */
-void brcms_c_bss_update_beacon(struct brcms_c_info *wlc,
- struct brcms_bss_cfg *cfg)
-{
- int len = BCN_TMPL_LEN;
-
- /* Clear the soft intmask */
- wlc->defmacintmask &= ~MI_BCNTPL;
-
- if (!cfg->up) { /* Only allow updates on an UP bss */
- return;
- }
-
- /* Optimize: Some of if/else could be combined */
- if (!MBSS_BCN_ENAB(cfg) && HWBCN_ENAB(cfg)) {
- /* Hardware beaconing for this config */
- u16 bcn[BCN_TMPL_LEN / 2];
- u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD;
- d11regs_t *regs = wlc->regs;
-
- /* Check if both templates are in use, if so sched. an interrupt
- * that will call back into this routine
- */
- if ((R_REG(&regs->maccommand) & both_valid) == both_valid) {
- /* clear any previous status */
- W_REG(&regs->macintstatus, MI_BCNTPL);
- }
- /* Check that after scheduling the interrupt both of the
- * templates are still busy. if not clear the int. & remask
- */
- if ((R_REG(&regs->maccommand) & both_valid) == both_valid) {
- wlc->defmacintmask |= MI_BCNTPL;
- return;
- }
-
- wlc->bcn_rspec =
- brcms_c_lowest_basic_rspec(wlc, &cfg->current_bss->rateset);
- /* update the template and ucode shm */
- brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_BEACON,
- wlc->bcn_rspec, cfg, bcn, &len);
- brcms_c_write_hw_bcntemplates(wlc, bcn, len, false);
- }
-}
-
/*
* Update all beacons for the system.
*/
void brcms_c_update_beacon(struct brcms_c_info *wlc)
{
- int idx;
- struct brcms_bss_cfg *bsscfg;
+ struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
- /* update AP or IBSS beacons */
- FOREACH_BSS(wlc, idx, bsscfg) {
- if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
- brcms_c_bss_update_beacon(wlc, bsscfg);
- }
+ if (bsscfg->up && !bsscfg->BSS)
+ /* Clear the soft intmask */
+ wlc->defmacintmask &= ~MI_BCNTPL;
}
/* Write ssid into shared memory */
-void brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
+static void
+brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
{
u8 *ssidptr = cfg->SSID;
u16 base = M_SSID;
@@ -5389,24 +8069,10 @@ void brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
memcpy(ssidbuf, ssidptr, cfg->SSID_len);
brcms_c_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN);
-
- if (!MBSS_BCN_ENAB(cfg))
- brcms_c_write_shm(wlc, M_SSIDLEN, (u16) cfg->SSID_len);
-}
-
-void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
-{
- int idx;
- struct brcms_bss_cfg *bsscfg;
-
- /* update AP or IBSS probe responses */
- FOREACH_BSS(wlc, idx, bsscfg) {
- if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
- brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
- }
+ brcms_b_write_shm(wlc->hw, M_SSIDLEN, (u16) cfg->SSID_len);
}
-void
+static void
brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
struct brcms_bss_cfg *cfg,
bool suspend)
@@ -5414,40 +8080,48 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
u16 prb_resp[BCN_TMPL_LEN / 2];
int len = BCN_TMPL_LEN;
- /* write the probe response to hardware, or save in the config structure */
- if (!MBSS_PRB_ENAB(cfg)) {
+ /*
+ * write the probe response to hardware, or save in
+ * the config structure
+ */
+
+ /* create the probe response template */
+ brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
+ cfg, prb_resp, &len);
- /* create the probe response template */
- brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
- cfg, prb_resp, &len);
+ if (suspend)
+ brcms_c_suspend_mac_and_wait(wlc);
- if (suspend)
- brcms_c_suspend_mac_and_wait(wlc);
+ /* write the probe response into the template region */
+ brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
+ (len + 3) & ~3, prb_resp);
- /* write the probe response into the template region */
- brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
- (len + 3) & ~3, prb_resp);
+ /* write the length of the probe response frame (+PLCP/-FCS) */
+ brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len);
- /* write the length of the probe response frame (+PLCP/-FCS) */
- brcms_c_write_shm(wlc, M_PRB_RESP_FRM_LEN, (u16) len);
+ /* write the SSID and SSID length */
+ brcms_c_shm_ssid_upd(wlc, cfg);
- /* write the SSID and SSID length */
- brcms_c_shm_ssid_upd(wlc, cfg);
+ /*
+ * Write PLCP headers and durations for probe response frames
+ * at all rates. Use the actual frame length covered by the
+ * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table()
+ * by subtracting the PLCP len and adding the FCS.
+ */
+ len += (-D11_PHY_HDR_LEN + FCS_LEN);
+ brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len);
- /*
- * Write PLCP headers and durations for probe response frames at all rates.
- * Use the actual frame length covered by the PLCP header for the call to
- * brcms_c_mod_prb_rsp_rate_table() by subtracting the PLCP len
- * and adding the FCS.
- */
- len += (-D11_PHY_HDR_LEN + FCS_LEN);
- brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len);
+ if (suspend)
+ brcms_c_enable_mac(wlc);
+}
- if (suspend)
- brcms_c_enable_mac(wlc);
- } else { /* Generating probe resp in sw; update local template */
- /* error: No software probe response support without MBSS */
- }
+void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
+{
+ struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
+
+ /* update AP or IBSS probe responses */
+ if (bsscfg->up && !bsscfg->BSS)
+ brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
}
/* prepares pdu for transmission. returns BCM error codes */
@@ -5470,641 +8144,632 @@ int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifop)
*fifop = fifo;
/* return if insufficient dma resources */
- if (TXAVAIL(wlc, fifo) < MAX_DMA_SEGS) {
+ if (*wlc->core->txavail[fifo] < MAX_DMA_SEGS) {
/* Mark precedences related to this FIFO, unsendable */
- BRCMS_TX_FIFO_CLEAR(wlc, fifo);
+ /* A fifo is full. Clear precedences related to that FIFO */
+ wlc->tx_prec_map &= ~(wlc->fifo2prec_map[fifo]);
return -EBUSY;
}
return 0;
}
-/* init tx reported rate mechanism */
-void brcms_c_reprate_init(struct brcms_c_info *wlc)
+int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
+ uint *blocks)
{
- int i;
- struct brcms_bss_cfg *bsscfg;
+ if (fifo >= NFIFO)
+ return -EINVAL;
- FOREACH_BSS(wlc, i, bsscfg) {
- brcms_c_bsscfg_reprate_init(bsscfg);
- }
-}
+ *blocks = wlc_hw->xmtfifo_sz[fifo];
-/* per bsscfg init tx reported rate mechanism */
-void brcms_c_bsscfg_reprate_init(struct brcms_bss_cfg *bsscfg)
-{
- bsscfg->txrspecidx = 0;
- memset((char *)bsscfg->txrspec, 0, sizeof(bsscfg->txrspec));
+ return 0;
}
-void brcms_default_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs)
+void
+brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
+ const u8 *addr)
{
- brcms_c_rateset_default(rs, NULL, wlc->band->phytype,
- wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL,
- (bool) N_ENAB(wlc->pub),
- CHSPEC_WLC_BW(wlc->default_bss->chanspec),
- wlc->stf->txstreams);
+ brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr);
+ if (match_reg_offset == RCM_BSSID_OFFSET)
+ memcpy(wlc->bsscfg->BSSID, addr, ETH_ALEN);
}
-static void brcms_c_bss_default_init(struct brcms_c_info *wlc)
+/*
+ * Flag 'scan in progress' to withhold dynamic phy calibration
+ */
+void brcms_c_scan_start(struct brcms_c_info *wlc)
{
- chanspec_t chanspec;
- struct brcms_band *band;
- struct brcms_bss_info *bi = wlc->default_bss;
-
- /* init default and target BSS with some sane initial values */
- memset((char *)(bi), 0, sizeof(struct brcms_bss_info));
- bi->beacon_period = BEACON_INTERVAL_DEFAULT;
- bi->dtim_period = DTIM_INTERVAL_DEFAULT;
-
- /* fill the default channel as the first valid channel
- * starting from the 2G channels
- */
- chanspec = CH20MHZ_CHSPEC(1);
- wlc->home_chanspec = bi->chanspec = chanspec;
-
- /* find the band of our default channel */
- band = wlc->band;
- if (NBANDS(wlc) > 1 && band->bandunit != CHSPEC_BANDUNIT(chanspec))
- band = wlc->bandstate[OTHERBANDUNIT(wlc)];
-
- /* init bss rates to the band specific default rate set */
- brcms_c_rateset_default(&bi->rateset, NULL, band->phytype,
- band->bandtype, false, BRCMS_RATE_MASK_FULL,
- (bool) N_ENAB(wlc->pub), CHSPEC_WLC_BW(chanspec),
- wlc->stf->txstreams);
-
- if (N_ENAB(wlc->pub))
- bi->flags |= BRCMS_BSS_HT;
+ wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
}
-static ratespec_t
-mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
- u32 int_val)
+void brcms_c_scan_stop(struct brcms_c_info *wlc)
{
- u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
- u8 rate = int_val & NRATE_RATE_MASK;
- ratespec_t rspec;
- bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE);
- bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT);
- bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY)
- == NRATE_OVERRIDE_MCS_ONLY);
- int bcmerror = 0;
-
- if (!ismcs) {
- return (ratespec_t) rate;
- }
-
- /* validate the combination of rate/mcs/stf is allowed */
- if (N_ENAB(wlc->pub) && ismcs) {
- /* mcs only allowed when nmode */
- if (stf > PHY_TXC1_MODE_SDM) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n",
- BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
-
- /* mcs 32 is a special case, DUP mode 40 only */
- if (rate == 32) {
- if (!CHSPEC_IS40(wlc->home_chanspec) ||
- ((stf != PHY_TXC1_MODE_SISO)
- && (stf != PHY_TXC1_MODE_CDD))) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid mcs "
- "32\n", BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
- /* mcs > 7 must use stf SDM */
- } else if (rate > HIGHEST_SINGLE_STREAM_MCS) {
- /* mcs > 7 must use stf SDM */
- if (stf != PHY_TXC1_MODE_SDM) {
- BCMMSG(wlc->wiphy, "wl%d: enabling "
- "SDM mode for mcs %d\n",
- BRCMS_UNIT(wlc), rate);
- stf = PHY_TXC1_MODE_SDM;
- }
- } else {
- /* MCS 0-7 may use SISO, CDD, and for phy_rev >= 3 STBC */
- if ((stf > PHY_TXC1_MODE_STBC) ||
- (!BRCMS_STBC_CAP_PHY(wlc)
- && (stf == PHY_TXC1_MODE_STBC))) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid STBC"
- "\n", BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
- }
- } else if (IS_OFDM(rate)) {
- if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n",
- BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
- } else if (IS_CCK(rate)) {
- if ((cur_band->bandtype != BRCM_BAND_2G)
- || (stf != PHY_TXC1_MODE_SISO)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n",
- BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
- } else {
- wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n",
- BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
- /* make sure multiple antennae are available for non-siso rates */
- if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: SISO antenna but !SISO "
- "request\n", BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
-
- rspec = rate;
- if (ismcs) {
- rspec |= RSPEC_MIMORATE;
- /* For STBC populate the STC field of the ratespec */
- if (stf == PHY_TXC1_MODE_STBC) {
- u8 stc;
- stc = 1; /* Nss for single stream is always 1 */
- rspec |= (stc << RSPEC_STC_SHIFT);
- }
- }
-
- rspec |= (stf << RSPEC_STF_SHIFT);
-
- if (override_mcs_only)
- rspec |= RSPEC_OVERRIDE_MCS_ONLY;
-
- if (issgi)
- rspec |= RSPEC_SHORT_GI;
-
- if ((rate != 0)
- && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true)) {
- return rate;
- }
-
- return rspec;
-done:
- return rate;
+ wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
}
-/* formula: IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */
-static int
-brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM,
- bool writeToShm)
+void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
{
- int idle_busy_ratio_x_16 = 0;
- uint offset =
- isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM :
- M_TX_IDLE_BUSY_RATIO_X_16_CCK;
- if (duty_cycle > 100 || duty_cycle < 0) {
- wiphy_err(wlc->wiphy, "wl%d: duty cycle value off limit\n",
- wlc->pub->unit);
- return -EINVAL;
- }
- if (duty_cycle)
- idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle;
- /* Only write to shared memory when wl is up */
- if (writeToShm)
- brcms_c_write_shm(wlc, offset, (u16) idle_busy_ratio_x_16);
-
- if (isOFDM)
- wlc->tx_duty_cycle_ofdm = (u16) duty_cycle;
- else
- wlc->tx_duty_cycle_cck = (u16) duty_cycle;
-
- return 0;
+ wlc->pub->associated = state;
+ wlc->bsscfg->associated = state;
}
-/* Read a single u16 from shared memory.
- * SHM 'offset' needs to be an even address
+/*
+ * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
+ * AMPDU traffic, packets pending in hardware have to be invalidated so that
+ * when later on hardware releases them, they can be handled appropriately.
*/
-u16 brcms_c_read_shm(struct brcms_c_info *wlc, uint offset)
+void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
+ struct ieee80211_sta *sta,
+ void (*dma_callback_fn))
{
- return brcms_b_read_shm(wlc->hw, offset);
+ struct dma_pub *dmah;
+ int i;
+ for (i = 0; i < NFIFO; i++) {
+ dmah = hw->di[i];
+ if (dmah != NULL)
+ dma_walk_packets(dmah, dma_callback_fn, sta);
+ }
}
-/* Write a single u16 to shared memory.
- * SHM 'offset' needs to be an even address
- */
-void brcms_c_write_shm(struct brcms_c_info *wlc, uint offset, u16 v)
+int brcms_c_get_curband(struct brcms_c_info *wlc)
{
- brcms_b_write_shm(wlc->hw, offset, v);
+ return wlc->band->bandunit;
}
-/* Copy a buffer to shared memory.
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- */
-void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset, const void *buf,
- int len)
+void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
{
- /* offset and len need to be even */
- if (len <= 0 || (offset & 1) || (len & 1))
- return;
-
- brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
+ /* flush packet queue when requested */
+ if (drop)
+ brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
+ /* wait for queue and DMA fifos to run dry */
+ while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0)
+ brcms_msleep(wlc->wl, 1);
}
-/* wrapper BMAC functions to for HIGH driver access */
-void brcms_c_mctrl(struct brcms_c_info *wlc, u32 mask, u32 val)
+void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
{
- brcms_b_mctrl(wlc->hw, mask, val);
+ wlc->bcn_li_bcn = interval;
+ if (wlc->pub->up)
+ brcms_c_bcn_li_upd(wlc);
}
-void brcms_c_mhf(struct brcms_c_info *wlc, u8 idx, u16 mask, u16 val, int bands)
+int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr)
{
- brcms_b_mhf(wlc->hw, idx, mask, val, bands);
-}
+ uint qdbm;
-int brcms_c_xmtfifo_sz_get(struct brcms_c_info *wlc, uint fifo, uint *blocks)
-{
- return brcms_b_xmtfifo_sz_get(wlc->hw, fifo, blocks);
+ /* Remove override bit and clip to max qdbm value */
+ qdbm = min_t(uint, txpwr * BRCMS_TXPWR_DB_FACTOR, 0xff);
+ return wlc_phy_txpower_set(wlc->band->pi, qdbm, false);
}
-void brcms_c_write_template_ram(struct brcms_c_info *wlc, int offset, int len,
- void *buf)
+int brcms_c_get_tx_power(struct brcms_c_info *wlc)
{
- brcms_b_write_template_ram(wlc->hw, offset, len, buf);
-}
+ uint qdbm;
+ bool override;
-void brcms_c_write_hw_bcntemplates(struct brcms_c_info *wlc, void *bcn, int len,
- bool both)
-{
- brcms_b_write_hw_bcntemplates(wlc->hw, bcn, len, both);
-}
+ wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override);
-void
-brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
- const u8 *addr)
-{
- brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr);
- if (match_reg_offset == RCM_BSSID_OFFSET)
- memcpy(wlc->cfg->BSSID, addr, ETH_ALEN);
+ /* Return qdbm units */
+ return (int)(qdbm / BRCMS_TXPWR_DB_FACTOR);
}
-void brcms_c_pllreq(struct brcms_c_info *wlc, bool set, mbool req_bit)
+void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc)
{
- brcms_b_pllreq(wlc->hw, set, req_bit);
+ wlc->mpc = mpc;
+ brcms_c_radio_mpc_upd(wlc);
}
-void brcms_c_reset_bmac_done(struct brcms_c_info *wlc)
+/* Process received frames */
+/*
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
+ */
+static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
{
-}
+ struct d11rxhdr *rxh;
+ struct ieee80211_hdr *h;
+ uint len;
+ bool is_amsdu;
-/* check for the particular priority flow control bit being set */
-bool
-brcms_c_txflowcontrol_prio_isset(struct brcms_c_info *wlc,
- struct brcms_txq_info *q,
- int prio)
-{
- uint prio_mask;
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
- if (prio == ALLPRIO) {
- prio_mask = TXQ_STOP_FOR_PRIOFC_MASK;
- } else {
- prio_mask = NBITVAL(prio);
- }
+ /* frame starts with rxhdr */
+ rxh = (struct d11rxhdr *) (p->data);
- return (q->stopped & prio_mask) == prio_mask;
-}
+ /* strip off rxhdr */
+ skb_pull(p, BRCMS_HWRXOFF);
-/* propagate the flow control to all interfaces using the given tx queue */
-void brcms_c_txflowcontrol(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi,
- bool on, int prio)
-{
- uint prio_bits;
- uint cur_bits;
+ /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
+ if (rxh->RxStatus1 & RXS_PBPRES) {
+ if (p->len < 2) {
+ wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of "
+ "len %d\n", wlc->pub->unit, p->len);
+ goto toss;
+ }
+ skb_pull(p, 2);
+ }
- BCMMSG(wlc->wiphy, "flow control kicks in\n");
+ h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN);
+ len = p->len;
- if (prio == ALLPRIO) {
- prio_bits = TXQ_STOP_FOR_PRIOFC_MASK;
- } else {
- prio_bits = NBITVAL(prio);
+ if (rxh->RxStatus1 & RXS_FCSERR) {
+ if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) {
+ wiphy_err(wlc->wiphy, "FCSERR while scanning******* -"
+ " tossing\n");
+ goto toss;
+ } else {
+ wiphy_err(wlc->wiphy, "RCSERR!!!\n");
+ goto toss;
+ }
}
- cur_bits = qi->stopped & prio_bits;
+ /* check received pkt has at least frame control field */
+ if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control))
+ goto toss;
- /* Check for the case of no change and return early
- * Otherwise update the bit and continue
- */
- if (on) {
- if (cur_bits == prio_bits) {
- return;
- }
- mboolset(qi->stopped, prio_bits);
- } else {
- if (cur_bits == 0) {
- return;
+ /* not supporting A-MSDU */
+ is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
+ if (is_amsdu)
+ goto toss;
+
+ brcms_c_recvctl(wlc, rxh, p);
+ return;
+
+ toss:
+ brcmu_pkt_buf_free_skb(p);
+}
+
+/* Process received frames */
+/*
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
+ */
+static bool
+brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
+{
+ struct sk_buff *p;
+ struct sk_buff *head = NULL;
+ struct sk_buff *tail = NULL;
+ uint n = 0;
+ uint bound_limit = bound ? RXBND : -1;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ /* gather received frames */
+ while ((p = dma_rx(wlc_hw->di[fifo]))) {
+
+ if (!tail)
+ head = tail = p;
+ else {
+ tail->prev = p;
+ tail = p;
}
- mboolclr(qi->stopped, prio_bits);
+
+ /* !give others some time to run! */
+ if (++n >= bound_limit)
+ break;
}
- /* If there is a flow control override we will not change the external
- * flow control state.
- */
- if (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK) {
- return;
+ /* post more rbufs */
+ dma_rxfill(wlc_hw->di[fifo]);
+
+ /* process each frame */
+ while ((p = head) != NULL) {
+ struct d11rxhdr_le *rxh_le;
+ struct d11rxhdr *rxh;
+ head = head->prev;
+ p->prev = NULL;
+
+ rxh_le = (struct d11rxhdr_le *)p->data;
+ rxh = (struct d11rxhdr *)p->data;
+
+ /* fixup rx header endianness */
+ rxh->RxFrameSize = le16_to_cpu(rxh_le->RxFrameSize);
+ rxh->PhyRxStatus_0 = le16_to_cpu(rxh_le->PhyRxStatus_0);
+ rxh->PhyRxStatus_1 = le16_to_cpu(rxh_le->PhyRxStatus_1);
+ rxh->PhyRxStatus_2 = le16_to_cpu(rxh_le->PhyRxStatus_2);
+ rxh->PhyRxStatus_3 = le16_to_cpu(rxh_le->PhyRxStatus_3);
+ rxh->PhyRxStatus_4 = le16_to_cpu(rxh_le->PhyRxStatus_4);
+ rxh->PhyRxStatus_5 = le16_to_cpu(rxh_le->PhyRxStatus_5);
+ rxh->RxStatus1 = le16_to_cpu(rxh_le->RxStatus1);
+ rxh->RxStatus2 = le16_to_cpu(rxh_le->RxStatus2);
+ rxh->RxTSFTime = le16_to_cpu(rxh_le->RxTSFTime);
+ rxh->RxChan = le16_to_cpu(rxh_le->RxChan);
+
+ brcms_c_recv(wlc_hw->wlc, p);
}
- brcms_c_txflowcontrol_signal(wlc, qi, on, prio);
+ return n >= bound_limit;
}
-void
-brcms_c_txflowcontrol_override(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi,
- bool on, uint override)
+/* second-level interrupt processing
+ * Return true if another dpc needs to be re-scheduled. false otherwise.
+ * Param 'bounded' indicates if applicable loops should be bounded.
+ */
+bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
{
- uint prev_override;
+ u32 macintstatus;
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ struct wiphy *wiphy = wlc->wiphy;
- prev_override = (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK);
+ if (brcms_deviceremoved(wlc)) {
+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ __func__);
+ brcms_down(wlc->wl);
+ return false;
+ }
- /* Update the flow control bits and do an early return if there is
- * no change in the external flow control state.
- */
- if (on) {
- mboolset(qi->stopped, override);
- /* if there was a previous override bit on, then setting this
- * makes no difference.
- */
- if (prev_override) {
- return;
- }
+ /* grab and clear the saved software intstatus bits */
+ macintstatus = wlc->macintstatus;
+ wlc->macintstatus = 0;
- brcms_c_txflowcontrol_signal(wlc, qi, ON, ALLPRIO);
- } else {
- mboolclr(qi->stopped, override);
- /* clearing an override bit will only make a difference for
- * flow control if it was the only bit set. For any other
- * override setting, just return
- */
- if (prev_override != override) {
- return;
- }
+ BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
+ wlc_hw->unit, macintstatus);
- if (qi->stopped == 0) {
- brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
- } else {
- int prio;
+ WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
- for (prio = MAXPRIO; prio >= 0; prio--) {
- if (!mboolisset(qi->stopped, NBITVAL(prio)))
- brcms_c_txflowcontrol_signal(
- wlc, qi, OFF, prio);
- }
+ /* tx status */
+ if (macintstatus & MI_TFS) {
+ bool fatal;
+ if (brcms_b_txstatus(wlc->hw, bounded, &fatal))
+ wlc->macintstatus |= MI_TFS;
+ if (fatal) {
+ wiphy_err(wiphy, "MI_TFS: fatal\n");
+ goto fatal;
}
}
-}
-static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc)
-{
- struct brcms_txq_info *qi;
+ if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
+ brcms_c_tbtt(wlc);
- for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
- if (qi->stopped) {
- brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
- qi->stopped = 0;
- }
+ /* ATIM window end */
+ if (macintstatus & MI_ATIMWINEND) {
+ BCMMSG(wlc->wiphy, "end of ATIM window\n");
+ OR_REG(&regs->maccommand, wlc->qvalid);
+ wlc->qvalid = 0;
}
-}
-static void
-brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi, bool on, int prio)
-{
-#ifdef NON_FUNCTIONAL
- /* wlcif_list is never filled so this function is not functional */
- struct brcms_c_if *wlcif;
+ /*
+ * received data or control frame, MI_DMAINT is
+ * indication of RX_FIFO interrupt
+ */
+ if (macintstatus & MI_DMAINT)
+ if (brcms_b_recv(wlc_hw, RX_FIFO, bounded))
+ wlc->macintstatus |= MI_DMAINT;
- for (wlcif = wlc->wlcif_list; wlcif != NULL; wlcif = wlcif->next) {
- if (wlcif->qi == qi && wlcif->flags & BRCMS_IF_LINKED)
- brcms_txflowcontrol(wlc->wl, wlcif->wlif, on, prio);
+ /* noise sample collected */
+ if (macintstatus & MI_BG_NOISE)
+ wlc_phy_noise_sample_intr(wlc_hw->band->pi);
+
+ if (macintstatus & MI_GP0) {
+ wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d "
+ "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
+
+ printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
+ __func__, wlc_hw->sih->chip,
+ wlc_hw->sih->chiprev);
+ /* big hammer */
+ brcms_init(wlc->wl);
}
-#endif
+
+ /* gptimer timeout */
+ if (macintstatus & MI_TO)
+ W_REG(&regs->gptimer, 0);
+
+ if (macintstatus & MI_RFDISABLE) {
+ BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the"
+ " RF Disable Input\n", wlc_hw->unit);
+ brcms_rfkill_set_hw_state(wlc->wl);
+ }
+
+ /* send any enq'd tx packets. Just makes sure to jump start tx */
+ if (!pktq_empty(&wlc->pkt_queue->q))
+ brcms_c_send_q(wlc);
+
+ /* it isn't done and needs to be resched if macintstatus is non-zero */
+ return wlc->macintstatus != 0;
+
+ fatal:
+ brcms_init(wlc->wl);
+ return wlc->macintstatus != 0;
}
-static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc)
+void brcms_c_init(struct brcms_c_info *wlc)
{
- struct brcms_txq_info *qi, *p;
+ struct d11regs __iomem *regs;
+ u16 chanspec;
+ bool mute = false;
- qi = kzalloc(sizeof(struct brcms_txq_info), GFP_ATOMIC);
- if (qi != NULL) {
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+ regs = wlc->regs;
+
+ /*
+ * This will happen if a big-hammer was executed. In
+ * that case, we want to go back to the channel that
+ * we were on and not new channel
+ */
+ if (wlc->pub->associated)
+ chanspec = wlc->home_chanspec;
+ else
+ chanspec = brcms_c_init_chanspec(wlc);
+
+ brcms_b_init(wlc->hw, chanspec, mute);
+
+ /* update beacon listen interval */
+ brcms_c_bcn_li_upd(wlc);
+
+ /* write ethernet address to core */
+ brcms_c_set_mac(wlc->bsscfg);
+ brcms_c_set_bssid(wlc->bsscfg);
+
+ /* Update tsf_cfprep if associated and up */
+ if (wlc->pub->associated && wlc->bsscfg->up) {
+ u32 bi;
+
+ /* get beacon period and convert to uS */
+ bi = wlc->bsscfg->current_bss->beacon_period << 10;
/*
- * Have enough room for control packets along with HI watermark
- * Also, add room to txq for total psq packets if all the SCBs
- * leave PS mode. The watermark for flowcontrol to OS packets
- * will remain the same
+ * update since init path would reset
+ * to default value
*/
- brcmu_pktq_init(&qi->q, BRCMS_PREC_COUNT,
- (2 * wlc->pub->tunables->datahiwat) + PKTQ_LEN_DEFAULT
- + wlc->pub->psq_pkts_total);
+ W_REG(&regs->tsf_cfprep,
+ (bi << CFPREP_CBI_SHIFT));
- /* add this queue to the the global list */
- p = wlc->tx_queues;
- if (p == NULL) {
- wlc->tx_queues = qi;
- } else {
- while (p->next != NULL)
- p = p->next;
- p->next = qi;
- }
+ /* Update maccontrol PM related bits */
+ brcms_c_set_ps_ctrl(wlc);
}
- return qi;
-}
-static void brcms_c_txq_free(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi)
-{
- struct brcms_txq_info *p;
+ brcms_c_bandinit_ordered(wlc, chanspec);
- if (qi == NULL)
- return;
+ /* init probe response timeout */
+ brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout);
- /* remove the queue from the linked list */
- p = wlc->tx_queues;
- if (p == qi)
- wlc->tx_queues = p->next;
- else {
- while (p != NULL && p->next != qi)
- p = p->next;
- if (p != NULL)
- p->next = p->next->next;
+ /* init max burst txop (framebursting) */
+ brcms_b_write_shm(wlc->hw, M_MBURST_TXOP,
+ (wlc->
+ _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
+
+ /* initialize maximum allowed duty cycle */
+ brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
+ brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
+
+ /*
+ * Update some shared memory locations related to
+ * max AMPDU size allowed to received
+ */
+ brcms_c_ampdu_shm_upd(wlc->ampdu);
+
+ /* band-specific inits */
+ brcms_c_bsinit(wlc);
+
+ /* Enable EDCF mode (while the MAC is suspended) */
+ OR_REG(&regs->ifs_ctl, IFS_USEEDCF);
+ brcms_c_edcf_setparams(wlc, false);
+
+ /* Init precedence maps for empty FIFOs */
+ brcms_c_tx_prec_map_init(wlc);
+
+ /* read the ucode version if we have not yet done so */
+ if (wlc->ucode_rev == 0) {
+ wlc->ucode_rev =
+ brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16);
+ wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR);
}
- kfree(qi);
-}
+ /* ..now really unleash hell (allow the MAC out of suspend) */
+ brcms_c_enable_mac(wlc);
-/*
- * Flag 'scan in progress' to withhold dynamic phy calibration
- */
-void brcms_c_scan_start(struct brcms_c_info *wlc)
-{
- wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
-}
+ /* clear tx flow control */
+ brcms_c_txflowcontrol_reset(wlc);
-void brcms_c_scan_stop(struct brcms_c_info *wlc)
-{
- wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
-}
+ /* enable the RF Disable Delay timer */
+ W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
-void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
-{
- wlc->pub->associated = state;
- wlc->cfg->associated = state;
+ /* initialize mpc delay */
+ wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
+
+ /*
+ * Initialize WME parameters; if they haven't been set by some other
+ * mechanism (IOVar, etc) then read them from the hardware.
+ */
+ if (GFIELD(wlc->wme_retries[0], EDCF_SHORT) == 0) {
+ /* Uninitialized; read from HW */
+ int ac;
+
+ for (ac = 0; ac < AC_COUNT; ac++)
+ wlc->wme_retries[ac] =
+ brcms_b_read_shm(wlc->hw, M_AC_TXLMT_ADDR(ac));
+ }
}
/*
- * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
- * AMPDU traffic, packets pending in hardware have to be invalidated so that
- * when later on hardware releases them, they can be handled appropriately.
+ * The common driver entry routine. Error codes should be unique
*/
-void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
- struct ieee80211_sta *sta,
- void (*dma_callback_fn))
+struct brcms_c_info *
+brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
+ bool piomode, void __iomem *regsva, struct pci_dev *btparam,
+ uint *perr)
{
- struct dma_pub *dmah;
- int i;
- for (i = 0; i < NFIFO; i++) {
- dmah = hw->di[i];
- if (dmah != NULL)
- dma_walk_packets(dmah, dma_callback_fn, sta);
- }
-}
+ struct brcms_c_info *wlc;
+ uint err = 0;
+ uint i, j;
+ struct brcms_pub *pub;
-int brcms_c_get_curband(struct brcms_c_info *wlc)
-{
- return wlc->band->bandunit;
-}
+ /* allocate struct brcms_c_info state and its substructures */
+ wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device);
+ if (wlc == NULL)
+ goto fail;
+ wlc->wiphy = wl->wiphy;
+ pub = wlc->pub;
-void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
-{
- /* flush packet queue when requested */
- if (drop)
- brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
+#if defined(BCMDBG)
+ wlc_info_dbg = wlc;
+#endif
- /* wait for queue and DMA fifos to run dry */
- while (!pktq_empty(&wlc->pkt_queue->q) ||
- TXPKTPENDTOT(wlc) > 0) {
- brcms_msleep(wlc->wl, 1);
- }
-}
+ wlc->band = wlc->bandstate[0];
+ wlc->core = wlc->corestate;
+ wlc->wl = wl;
+ pub->unit = unit;
+ pub->_piomode = piomode;
+ wlc->bandinit_pending = false;
-int brcms_c_set_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
- int int_val)
-{
- int err = 0;
+ /* populate struct brcms_c_info with default values */
+ brcms_c_info_init(wlc, unit);
- switch (par_id) {
- case IOV_BCN_LI_BCN:
- wlc->bcn_li_bcn = (u8) int_val;
- if (wlc->pub->up)
- brcms_c_bcn_li_upd(wlc);
- break;
- /* As long as override is false, this only sets the *user*
- targets. User can twiddle this all he wants with no harm.
- wlc_phy_txpower_set() explicitly sets override to false if
- not internal or test.
- */
- case IOV_QTXPOWER:{
- u8 qdbm;
- bool override;
-
- /* Remove override bit and clip to max qdbm value */
- qdbm = (u8)min_t(u32, (int_val & ~WL_TXPWR_OVERRIDE), 0xff);
- /* Extract override setting */
- override = (int_val & WL_TXPWR_OVERRIDE) ? true : false;
- err =
- wlc_phy_txpower_set(wlc->band->pi, qdbm, override);
- break;
+ /* update sta/ap related parameters */
+ brcms_c_ap_upd(wlc);
+
+ /*
+ * low level attach steps(all hw accesses go
+ * inside, no more in rest of the attach)
+ */
+ err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva,
+ btparam);
+ if (err)
+ goto fail;
+
+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, OFF);
+
+ pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band);
+
+ /* disable allowed duty cycle */
+ wlc->tx_duty_cycle_ofdm = 0;
+ wlc->tx_duty_cycle_cck = 0;
+
+ brcms_c_stf_phy_chain_calc(wlc);
+
+ /* txchain 1: txant 0, txchain 2: txant 1 */
+ if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
+ wlc->stf->txant = wlc->stf->hw_txchain - 1;
+
+ /* push to BMAC driver */
+ wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
+ wlc->stf->hw_rxchain);
+
+ /* pull up some info resulting from the low attach */
+ for (i = 0; i < NFIFO; i++)
+ wlc->core->txavail[i] = wlc->hw->txavail[i];
+
+ memcpy(&wlc->perm_etheraddr, &wlc->hw->etheraddr, ETH_ALEN);
+ memcpy(&pub->cur_etheraddr, &wlc->hw->etheraddr, ETH_ALEN);
+
+ for (j = 0; j < wlc->pub->_nbands; j++) {
+ wlc->band = wlc->bandstate[j];
+
+ if (!brcms_c_attach_stf_ant_init(wlc)) {
+ err = 24;
+ goto fail;
}
- case IOV_MPC:
- wlc->mpc = (bool)int_val;
- brcms_c_radio_mpc_upd(wlc);
- break;
- default:
- err = -ENOTSUPP;
- }
- return err;
-}
-int brcms_c_get_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
- int *ret_int_ptr)
-{
- int err = 0;
+ /* default contention windows size limits */
+ wlc->band->CWmin = APHY_CWMIN;
+ wlc->band->CWmax = PHY_CWMAX;
- switch (par_id) {
- case IOV_BCN_LI_BCN:
- *ret_int_ptr = wlc->bcn_li_bcn;
- break;
- case IOV_QTXPOWER: {
- uint qdbm;
- bool override;
-
- err = wlc_phy_txpower_get(wlc->band->pi, &qdbm,
- &override);
- if (err != 0)
- return err;
-
- /* Return qdbm units */
- *ret_int_ptr =
- qdbm | (override ? WL_TXPWR_OVERRIDE : 0);
- break;
+ /* init gmode value */
+ if (wlc->band->bandtype == BRCM_BAND_2G) {
+ wlc->band->gmode = GMODE_AUTO;
+ brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER,
+ wlc->band->gmode);
}
- case IOV_MPC:
- *ret_int_ptr = (s32) wlc->mpc;
- break;
- default:
- err = -ENOTSUPP;
+
+ /* init _n_enab supported mode */
+ if (BRCMS_PHY_11N_CAP(wlc->band)) {
+ pub->_n_enab = SUPPORT_11N;
+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
+ ((pub->_n_enab ==
+ SUPPORT_11N) ? WL_11N_2x2 :
+ WL_11N_3x3));
+ }
+
+ /* init per-band default rateset, depend on band->gmode */
+ brcms_default_rateset(wlc, &wlc->band->defrateset);
+
+ /* fill in hw_rateset */
+ brcms_c_rateset_filter(&wlc->band->defrateset,
+ &wlc->band->hw_rateset, false,
+ BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
+ (bool) (wlc->pub->_n_enab & SUPPORT_11N));
}
- return err;
-}
-/*
- * Search the name=value vars for a specific one and return its value.
- * Returns NULL if not found.
- */
-char *getvar(char *vars, const char *name)
-{
- char *s;
- int len;
+ /*
+ * update antenna config due to
+ * wlc->stf->txant/txchain/ant_rx_ovr change
+ */
+ brcms_c_stf_phy_txant_upd(wlc);
- if (!name)
- return NULL;
+ /* attach each modules */
+ err = brcms_c_attach_module(wlc);
+ if (err != 0)
+ goto fail;
- len = strlen(name);
- if (len == 0)
- return NULL;
+ if (!brcms_c_timers_init(wlc, unit)) {
+ wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit,
+ __func__);
+ err = 32;
+ goto fail;
+ }
- /* first look in vars[] */
- for (s = vars; s && *s;) {
- if ((memcmp(s, name, len) == 0) && (s[len] == '='))
- return &s[len + 1];
+ /* depend on rateset, gmode */
+ wlc->cmi = brcms_c_channel_mgr_attach(wlc);
+ if (!wlc->cmi) {
+ wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed"
+ "\n", unit, __func__);
+ err = 33;
+ goto fail;
+ }
- while (*s++)
- ;
+ /* init default when all parameters are ready, i.e. ->rateset */
+ brcms_c_bss_default_init(wlc);
+
+ /*
+ * Complete the wlc default state initializations..
+ */
+
+ /* allocate our initial queue */
+ wlc->pkt_queue = brcms_c_txq_alloc(wlc);
+ if (wlc->pkt_queue == NULL) {
+ wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n",
+ unit, __func__);
+ err = 100;
+ goto fail;
}
- /* nothing found */
- return NULL;
-}
-/*
- * Search the vars for a specific one and return its value as
- * an integer. Returns 0 if not found.
- */
-int getintvar(char *vars, const char *name)
-{
- char *val;
+ wlc->bsscfg->wlc = wlc;
- val = getvar(vars, name);
- if (val == NULL)
- return 0;
+ wlc->mimoft = FT_HT;
+ wlc->mimo_40txbw = AUTO;
+ wlc->ofdm_40txbw = AUTO;
+ wlc->cck_40txbw = AUTO;
+ brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G);
+
+ /* Set default values of SGI */
+ if (BRCMS_SGI_CAP_PHY(wlc)) {
+ brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
+ BRCMS_N_SGI_40));
+ } else if (BRCMS_ISSSLPNPHY(wlc->band)) {
+ brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
+ BRCMS_N_SGI_40));
+ } else {
+ brcms_c_ht_update_sgi_rx(wlc, 0);
+ }
+
+ /* initialize radio_mpc_disable according to wlc->mpc */
+ brcms_c_radio_mpc_upd(wlc);
+ brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail);
+
+ if (perr)
+ *perr = 0;
+
+ return wlc;
- return simple_strtoul(val, NULL, 0);
+ fail:
+ wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n",
+ unit, __func__, err);
+ if (wlc)
+ brcms_c_detach(wlc);
+
+ if (perr)
+ *perr = err;
+ return NULL;
}
diff --git a/drivers/staging/brcm80211/brcmsmac/main.h b/drivers/staging/brcm80211/brcmsmac/main.h
index f204b1f47475..c0e0fcfdfaf8 100644
--- a/drivers/staging/brcm80211/brcmsmac/main.h
+++ b/drivers/staging/brcm80211/brcmsmac/main.h
@@ -22,35 +22,23 @@
#include <brcmu_utils.h>
#include "types.h"
#include "d11.h"
+#include "scb.h"
-#define MA_WINDOW_SZ 8 /* moving average window size */
-#define BRCMS_HWRXOFF 38 /* chip rx buffer offset */
#define INVCHANNEL 255 /* invalid channel */
-/* max # supported core revisions (0 .. MAXCOREREV - 1) */
-#define MAXCOREREV 28
+
/* max # brcms_c_module_register() calls */
#define BRCMS_MAXMODULES 22
#define SEQNUM_SHIFT 4
-#define AMPDU_DELIMITER_LEN 4
#define SEQNUM_MAX 0x1000
-#define APHY_CWMIN 15
-#define PHY_CWMAX 1023
-
-#define EDCF_AIFSN_MIN 1
-#define FRAGNUM_MASK 0xF
-
#define NTXRATE 64 /* # tx MPDUs rate is reported for */
-#define BRCMS_BITSCNT(x) brcmu_bitcount((u8 *)&(x), sizeof(u8))
-
/* Maximum wait time for a MAC suspend */
/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */
#define BRCMS_MAX_MAC_SUSPEND 83000
-/* Probe Response timeout - responses for probe requests older that this are tossed, zero to disable
- */
+/* 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 */
@@ -78,13 +66,14 @@
#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 */
-#define VALID_COREREV(corerev) CONF_HAS(D11CONF, corerev)
-
/* values for shortslot_override */
#define BRCMS_SHORTSLOT_AUTO -1 /* Driver will manage Shortslot setting */
#define BRCMS_SHORTSLOT_OFF 0 /* Turn off short slot */
@@ -98,17 +87,6 @@
#define BRCMS_IS_MIMO_PREAMBLE(_pre) (((_pre) == BRCMS_GF_PREAMBLE) || \
((_pre) == BRCMS_MM_PREAMBLE))
-/* values for barker_preamble */
-#define BRCMS_BARKER_SHORT_ALLOWED 0 /* Short pre-amble allowed */
-
-/* A fifo is full. Clear precedences related to that FIFO */
-#define BRCMS_TX_FIFO_CLEAR(wlc, fifo) \
- ((wlc)->tx_prec_map &= ~(wlc)->fifo2prec_map[fifo])
-
-/* Fifo is NOT full. Enable precedences for that FIFO */
-#define BRCMS_TX_FIFO_ENAB(wlc, fifo) \
- ((wlc)->tx_prec_map |= (wlc)->fifo2prec_map[fifo])
-
/* TxFrameID */
/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */
/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */
@@ -123,18 +101,6 @@
#define BOARDREV_PROMOTABLE 0xFF /* from */
#define BOARDREV_PROMOTED 1 /* to */
-/* if wpa is in use then portopen is true when the group key is plumbed otherwise it is always true
- */
-#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
-#define BRCMS_SW_KEYS(wlc, bsscfg) ((((wlc)->wsec_swkeys) || \
- ((bsscfg)->wsec & WSEC_SWFLAG)))
-
-#define BRCMS_PORTOPEN(cfg) \
- (((cfg)->WPA_auth != WPA_AUTH_DISABLED && WSEC_ENABLED((cfg)->wsec)) ? \
- (cfg)->wsec_portopen : true)
-
-#define PS_ALLOWED(wlc) brcms_c_ps_allowed(wlc)
-
#define DATA_BLOCK_TX_SUPR (1 << 4)
/* 802.1D Priority to TX FIFO number for wme */
@@ -160,48 +126,14 @@ extern const u8 prio2fifo[];
MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \
MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP)
-#define RETRY_SHORT_DEF 7 /* Default Short retry Limit */
-#define RETRY_SHORT_MAX 255 /* Maximum Short retry Limit */
-#define RETRY_LONG_DEF 4 /* Default Long retry count */
-#define RETRY_SHORT_FB 3 /* Short retry count for fallback rate */
-#define RETRY_LONG_FB 2 /* Long retry count for fallback rate */
-
#define MAXTXPKTS 6 /* max # pkts pending */
/* frameburst */
-#define MAXTXFRAMEBURST 8 /* vanilla xpress mode: max frames/burst */
+#define MAXTXFRAMEBURST 8 /* vanilla xpress mode: max frames/burst */
#define MAXFRAMEBURST_TXOP 10000 /* Frameburst TXOP in usec */
-/* Per-AC retry limit register definitions; uses defs.h bitfield macros */
-#define EDCF_SHORT_S 0
-#define EDCF_SFB_S 4
-#define EDCF_LONG_S 8
-#define EDCF_LFB_S 12
-#define EDCF_SHORT_M BITFIELD_MASK(4)
-#define EDCF_SFB_M BITFIELD_MASK(4)
-#define EDCF_LONG_M BITFIELD_MASK(4)
-#define EDCF_LFB_M BITFIELD_MASK(4)
-
#define NFIFO 6 /* # tx/rx fifopairs */
-#define BRCMS_WME_RETRY_SHORT_GET(wlc, ac) \
- GFIELD(wlc->wme_retries[ac], EDCF_SHORT)
-#define BRCMS_WME_RETRY_SFB_GET(wlc, ac) \
- GFIELD(wlc->wme_retries[ac], EDCF_SFB)
-#define BRCMS_WME_RETRY_LONG_GET(wlc, ac) \
- GFIELD(wlc->wme_retries[ac], EDCF_LONG)
-#define BRCMS_WME_RETRY_LFB_GET(wlc, ac) \
- GFIELD(wlc->wme_retries[ac], EDCF_LFB)
-
-#define BRCMS_WME_RETRY_SHORT_SET(wlc, ac, val) \
- (wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SHORT, val))
-#define BRCMS_WME_RETRY_SFB_SET(wlc, ac, val) \
- (wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SFB, val))
-#define BRCMS_WME_RETRY_LONG_SET(wlc, ac, val) \
- (wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LONG, val))
-#define BRCMS_WME_RETRY_LFB_SET(wlc, ac, val) \
- (wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LFB, val))
-
/* PLL requests */
/* pll is shared on old chips */
@@ -211,83 +143,86 @@ extern const u8 prio2fifo[];
/* hold/release pll for some short operation */
#define BRCMS_PLLREQ_FLIP 0x4
-/*
- * Macros to check if AP or STA is active.
- * AP Active means more than just configured: driver and BSS are "up";
- * that is, we are beaconing/responding as an AP (aps_associated).
- * STA Active similarly means the driver is up and a configured STA BSS
- * is up: either associated (stas_associated) or trying.
- *
- * Macro definitions vary as per AP/STA ifdefs, allowing references to
- * ifdef'd structure fields and constant values (0) for optimization.
- * Make sure to enclose blocks of code such that any routines they
- * reference can also be unused and optimized out by the linker.
- */
-/* NOTE: References structure fields defined in wlc.h */
-#define AP_ACTIVE(wlc) (0)
-
-/*
- * Detect Card removed.
- * Even checking an sbconfig register read will not false trigger when the core is in reset.
- * it breaks CF address mechanism. Accessing gphy phyversion will cause SB error if aphy
- * is in reset on 4306B0-DB. Need a simple accessible reg with fixed 0/1 pattern
- * (some platforms return all 0).
- * If clocks are present, call the sb routine which will figure out if the device is removed.
- */
-#define DEVICEREMOVED(wlc) \
- ((wlc->hw->clk) ? \
- ((R_REG(&wlc->hw->regs->maccontrol) & \
- (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN) : \
- (ai_deviceremoved(wlc->hw->sih)))
+#define CHANNEL_BANDUNIT(wlc, ch) \
+ (((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX)
-#define BRCMS_UNIT(wlc) ((wlc)->pub->unit)
+#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; /* use g spec protection, driver internal */
- s8 g_override; /* override for use of g spec protection */
- u8 gmode_user; /* user config gmode, operating band->gmode is different */
- s8 overlap; /* Overlap BSS/IBSS protection for both 11g and 11n */
- s8 nmode_user; /* user config nmode, operating pub->nmode is different */
- s8 n_cfg; /* use OFDM protection on MIMO frames */
- s8 n_cfg_override; /* override for use of N protection */
- bool nongf; /* non-GF present protection */
- s8 nongf_override; /* override for use of GF protection */
- s8 n_pam_override; /* override for preamble: MM or GF */
- bool n_obss; /* indicated OBSS Non-HT STA present */
+ 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 affects the single/dual streams/antenna operation */
+/*
+ * 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; /* HW txchain bitmap cfg */
- u8 txchain; /* txchain bitmap being used */
- u8 txstreams; /* number of txchains being used */
-
- u8 hw_rxchain; /* HW rxchain bitmap cfg */
- u8 rxchain; /* rxchain bitmap being used */
- u8 rxstreams; /* number of rxchains being used */
-
- u8 ant_rx_ovr; /* rx antenna override */
- s8 txant; /* userTx antenna setting */
- u16 phytxant; /* phyTx antenna setting in txheader */
-
- u8 ss_opmode; /* singlestream Operational mode, 0:siso; 1:cdd */
- bool ss_algosel_auto; /* if true, use wlc->stf->ss_algo_channel; */
- /* else use wlc->band->stf->ss_mode_band; */
- u16 ss_algo_channel; /* ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC */
- u8 no_cddstbc; /* stf override, 1: no CDD (or STBC) allowed */
-
- u8 rxchain_restore_delay; /* delay time to restore default rxchain */
-
- s8 ldpc; /* AUTO/ON/OFF ldpc cap supported */
- u8 txcore[MAX_STREAMS_SUPPORTED + 1]; /* bitmap of selected core for each Nsts */
+ 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_STBC_CAP((scb)) && \
- (wlc)->band->band_stf_stbc_tx == AUTO && \
- isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC))))
+ (((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))
@@ -300,60 +235,6 @@ struct brcms_stf {
>> RXS_CHAN_PHYTYPE_SHIFT)
#define BRCMS_CHAN_CHANNEL(x) (((x) & RXS_CHAN_ID_MASK) \
>> RXS_CHAN_ID_SHIFT)
-#define BRCMS_RX_CHANNEL(rxh) (BRCMS_CHAN_CHANNEL((rxh)->RxChan))
-
-/* brcms_bss_info flag bit values */
-#define BRCMS_BSS_HT 0x0020 /* BSS is HT (MIMO) capable */
-
-/* Flags used in brcms_c_txq_info.stopped */
-#define TXQ_STOP_FOR_PRIOFC_MASK 0x000000FF /* per prio flow control bits */
-#define TXQ_STOP_FOR_PKT_DRAIN 0x00000100 /* stop txq enqueue for packet drain */
-#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL 0x00000200 /* stop txq enqueue for ampdu flow control */
-
-#define BRCMS_HT_WEP_RESTRICT 0x01 /* restrict HT with WEP */
-#define BRCMS_HT_TKIP_RESTRICT 0x02 /* restrict HT with TKIP */
-
-/* Maximum # of keys that wl driver supports in S/W.
- * Keys supported in H/W is less than or equal to WSEC_MAX_KEYS.
- */
-#define WSEC_MAX_KEYS 54 /* Max # of keys (50 + 4 default keys) */
-#define BRCMS_DEFAULT_KEYS 4 /* Default # of keys */
-
-/*
-* Max # of keys currently supported:
-*
-* s/w keys if WSEC_SW(wlc->wsec).
-* h/w keys otherwise.
-*/
-#define BRCMS_MAX_WSEC_KEYS(wlc) WSEC_MAX_KEYS
-
-/* number of 802.11 default (non-paired, group keys) */
-#define WSEC_MAX_DEFAULT_KEYS 4 /* # of default keys */
-
-struct wsec_iv {
- u32 hi; /* upper 32 bits of IV */
- u16 lo; /* lower 16 bits of IV */
-};
-
-#define BRCMS_NUMRXIVS 16 /* # rx IVs (one per 802.11e TID) */
-
-struct wsec_key {
- u8 ea[ETH_ALEN]; /* per station */
- u8 idx; /* key index in wsec_keys array */
- u8 id; /* key ID [0-3] */
- u8 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
- u8 rcmta; /* rcmta entry index, same as idx by default */
- u16 flags; /* misc flags */
- u8 algo_hw; /* cache for hw register */
- u8 aes_mode; /* cache for hw register */
- s8 iv_len; /* IV length */
- s8 icv_len; /* ICV length */
- u32 len; /* key length..don't move this var */
- /* data is 4byte aligned */
- u8 data[WLAN_MAX_KEY_LEN]; /* key data */
- struct wsec_iv rxiv[BRCMS_NUMRXIVS]; /* Rx IV (one per TID) */
- struct wsec_iv txiv; /* Tx IV */
-};
/*
* core state (mac)
@@ -386,92 +267,37 @@ struct brcms_band {
struct scb *hwrs_scb; /* permanent scb for hw rateset */
- wlc_rateset_t defrateset; /* band-specific copy of default_bss.rateset */
+ /* band-specific copy of default_bss.rateset */
+ struct brcms_c_rateset defrateset;
- ratespec_t rspec_override; /* 802.11 rate override */
- ratespec_t mrspec_override; /* multicast rate override */
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 */
- wlc_rateset_t hw_rateset; /* rates supported by chip (phy-specific) */
+ /* 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; /* The minimum size of contention window, in unit of aSlotTime */
- u16 CWmax; /* The maximum size of contention window, in unit of aSlotTime */
- u16 bcntsfoff; /* beacon tsf offset */
-};
-
-/* tx completion callback takes 3 args */
-typedef void (*pkcb_fn_t) (struct brcms_c_info *wlc, uint txstatus, void *arg);
-
-struct pkt_cb {
- pkcb_fn_t fn; /* function to call when tx frame completes */
- void *arg; /* void arg for fn */
- u8 nextidx; /* index of next call back if threading */
- bool entered; /* recursion check */
+ 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 {
- char name[32]; /* module name : NULL indicates empty array member */
- const struct brcmu_iovar *iovars; /* iovar table */
- void *hdl; /* handle passed when handler 'doiovar' is called */
- watchdog_fn_t watchdog_fn; /* watchdog handler */
- iovar_fn_t iovar_fn; /* iovar handler */
- down_fn_t down_fn; /* down handler. Note: the int returned
- * by the down function is a count of the
- * number of timers that could not be
- * freed.
- */
-};
+ /* module name : NULL indicates empty array member */
+ char name[32];
+ /* handle passed when handler 'doiovar' is called */
+ struct brcms_info *hdl;
-/* dump control blocks */
-struct dumpcb_s {
- const char *name; /* dump name */
- dump_fn_t dump_fn; /* 'wl dump' handler */
- void *dump_fn_arg;
- struct dumpcb_s *next;
-};
+ 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 edcf_acparam {
- u8 ACI;
- u8 ECW;
- u16 TXOP;
-} __packed;
-
-struct wme_param_ie {
- u8 oui[3];
- u8 type;
- u8 subtype;
- u8 version;
- u8 qosinfo;
- u8 rsvd;
- struct edcf_acparam acparam[AC_COUNT];
-} __packed;
-
-/* virtual interface */
-struct brcms_c_if {
- struct brcms_c_if *next;
- u8 type; /* BSS or WDS */
- u8 index; /* assigned in wl_add_if(), index of the wlif if any,
- * not necessarily corresponding to bsscfg._idx or
- * AID2PVBMAP(scb).
- */
- u8 flags; /* flags for the interface */
- struct brcms_if *wlif; /* pointer to wlif */
- struct brcms_txq_info *qi; /* pointer to associated tx queue */
- union {
- /* pointer to scb if WDS */
- struct scb *scb;
- /* pointer to bsscfg if BSS */
- struct brcms_bss_cfg *bsscfg;
- } u;
};
-/* flags for the interface, this interface is linked to a brcms_if */
-#define BRCMS_IF_LINKED 0x02
-
struct brcms_hw_band {
int bandtype; /* BRCM_BAND_2G, BRCM_BAND_5G */
uint bandunit; /* bandstate[] index */
@@ -508,14 +334,11 @@ struct brcms_hardware {
u32 boardflags2; /* More board flags if sromrev >= 4 */
u32 machwcap; /* MAC capabilities */
u32 machwcap_backup; /* backup of machwcap */
- u16 ucode_dbgsel; /* dbgsel for ucode debug(config gpio) */
struct si_pub *sih; /* SI handle (cookie for siutils calls) */
- char *vars; /* "environment" name=value */
- uint vars_size; /* size of vars, free vars on detach */
- d11regs_t *regs; /* pointer to device registers */
- void *physhim; /* phy shim layer handler */
- void *phy_sh; /* pointer to shared phy state */
+ struct d11regs __iomem *regs; /* pointer to device registers */
+ 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];
@@ -529,27 +352,24 @@ struct brcms_hardware {
bool up; /* d11 hardware up and running */
uint now; /* # elapsed seconds */
uint _nbands; /* # bands supported */
- chanspec_t chanspec; /* bmac chanspec shadow */
+ u16 chanspec; /* bmac chanspec shadow */
uint *txavail[NFIFO]; /* # tx descriptors available */
- u16 *xmtfifo_sz; /* fifo size in 256B for each xmt fifo */
+ const u16 *xmtfifo_sz; /* fifo size in 256B for each xmt fifo */
- mbool pllreq; /* pll requests to keep PLL on */
+ 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; /* Various conditions to force MAC to WAKE mode */
+ 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 */
- u32 led_gpio_mask; /* LED GPIO Mask */
bool noreset; /* true= do not reset hw, used by WLC_OUT */
- bool forcefastclk; /* true if the h/w is forcing the use of fast clk */
+ 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 */
- struct bmac_pmq *bmac_pmq; /* bmac PM states derived from ucode PMQ */
bool phyclk; /* phy is out of reset and has clock */
- bool dma_lpbk; /* core is in DMA loopback */
bool ucode_loaded; /* true after ucode downloaded */
@@ -578,195 +398,212 @@ struct brcms_txq_info {
};
/*
- * Principal common (os-independent) software data structure.
+ * Principal common driver data structure.
+ *
+ * pub: pointer to driver public state.
+ * wl: pointer to specific private state.
+ * regs: pointer to device registers.
+ * 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.
+ * mpc: enable minimum power consumption.
+ * mpc_dlycnt: # of watchdog cnt before turn disable radio.
+ * mpc_offcnt: # of watchdog cnt that radio is disabled.
+ * mpc_delay_off: delay radio disable by # of watchdog cnt.
+ * prev_non_delay_mpc: prev state brcms_c_is_non_delay_mpc.
+ * 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[AC_COUNT]: current txop for each ac.
+ * wme_retries: per-AC retry limits.
+ * tx_prec_map: Precedence map based on HW FIFO space.
+ * fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME.
+ * bsscfg: set of BSS configurations, idx 0 is default and always valid.
+ * cfg: the primary bsscfg (can be AP or STA).
+ * tx_queues: common TX Queue list.
+ * 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.
+ * pkt_queue: txq for transmit packets.
+ * wiphy:
+ * pri_scb: primary Station Control Block
*/
struct brcms_c_info {
- struct brcms_pub *pub; /* pointer to wlc public state */
- struct brcms_info *wl; /* pointer to os-specific private state */
- d11regs_t *regs; /* pointer to device registers */
-
- /* HW related state used primarily by BMAC */
+ struct brcms_pub *pub;
+ struct brcms_info *wl;
+ struct d11regs __iomem *regs;
struct brcms_hardware *hw;
/* clock */
- int clkreq_override; /* setting for clkreq for PCIE : Auto, 0, 1 */
- u16 fastpwrup_dly; /* time in us needed to bring up d11 fast clock */
+ u16 fastpwrup_dly;
/* interrupt */
- u32 macintstatus; /* bit channel between isr and dpc */
- u32 macintmask; /* sw runtime master macintmask value */
- u32 defmacintmask; /* default "on" macintmask value */
-
- /* up and down */
- bool device_present; /* (removable) device is present */
+ u32 macintstatus;
+ u32 macintmask;
+ u32 defmacintmask;
- bool clk; /* core is out of reset and has clock */
+ bool clk;
/* multiband */
- struct brcms_core *core; /* pointer to active io core */
- struct brcms_band *band; /* pointer to active per-band state */
- struct brcms_core *corestate; /* per-core state (one per hw core) */
- /* per-band state (one per phy/radio): */
+ struct brcms_core *core;
+ struct brcms_band *band;
+ struct brcms_core *corestate;
struct brcms_band *bandstate[MAXBANDS];
- bool war16165; /* PCI slow clock 16165 war flag */
-
- bool tx_suspended; /* data fifos need to remain suspended */
-
- uint txpend16165war;
-
/* packet queue */
- uint qvalid; /* DirFrmQValid and BcMcFrmQValid */
-
- /* Regulatory power limits */
- s8 txpwr_local_max; /* regulatory local txpwr max */
- u8 txpwr_local_constraint; /* local power contraint in dB */
-
-
- struct ampdu_info *ampdu; /* ampdu module handler */
- struct antsel_info *asi; /* antsel module handler */
- struct brcms_cm_info *cmi; /* channel manager module handler */
+ uint qvalid;
- uint vars_size; /* size of vars, free vars on detach */
-
- u16 vendorid; /* PCI vendor id */
- u16 deviceid; /* PCI device id */
- uint ucode_rev; /* microcode revision */
+ struct ampdu_info *ampdu;
+ struct antsel_info *asi;
+ struct brcms_cm_info *cmi;
- u32 machwcap; /* MAC capabilities, BMAC shadow */
+ u16 vendorid;
+ u16 deviceid;
+ uint ucode_rev;
- u8 perm_etheraddr[ETH_ALEN]; /* original sprom local ethernet address */
+ u8 perm_etheraddr[ETH_ALEN];
- bool bandlocked; /* disable auto multi-band switching */
- bool bandinit_pending; /* track band init in auto band */
+ bool bandlocked;
+ bool bandinit_pending;
- bool radio_monitor; /* radio timer is running */
- bool going_down; /* down path intermediate variable */
+ bool radio_monitor;
+ bool going_down;
- bool mpc; /* enable minimum power consumption */
- u8 mpc_dlycnt; /* # of watchdog cnt before turn disable radio */
- u8 mpc_offcnt; /* # of watchdog cnt that radio is disabled */
- u8 mpc_delay_off; /* delay radio disable by # of watchdog cnt */
- u8 prev_non_delay_mpc; /* prev state brcms_c_is_non_delay_mpc */
+ bool mpc;
+ u8 mpc_dlycnt;
+ u8 mpc_offcnt;
+ u8 mpc_delay_off;
+ u8 prev_non_delay_mpc;
- /* timer for watchdog routine */
struct brcms_timer *wdtimer;
- /* timer for hw radio button monitor routine */
struct brcms_timer *radio_timer;
/* promiscuous */
- bool monitor; /* monitor (MPDU sniffing) mode */
- bool bcnmisc_ibss; /* bcns promisc mode override for IBSS */
- bool bcnmisc_scan; /* bcns promisc mode override for scan */
- bool bcnmisc_monitor; /* bcns promisc mode override for monitor */
+ bool monitor;
+ bool bcnmisc_monitor;
/* driver feature */
- bool _rifs; /* enable per-packet rifs */
- s8 sgi_tx; /* sgi tx */
+ bool _rifs;
/* AP-STA synchronization, power save */
- u8 bcn_li_bcn; /* beacon listen interval in # beacons */
- u8 bcn_li_dtim; /* beacon listen interval in # dtims */
+ u8 bcn_li_bcn;
+ u8 bcn_li_dtim;
- bool WDarmed; /* watchdog timer is armed */
- u32 WDlast; /* last time wlc_watchdog() was called */
+ bool WDarmed;
+ u32 WDlast;
/* WME */
- ac_bitmap_t wme_dp; /* Discard (oldest first) policy per AC */
- u16 edcf_txop[AC_COUNT]; /* current txop for each ac */
-
- /*
- * WME parameter info element, which on STA contains parameters in use
- * locally, and on AP contains parameters advertised to STA in beacons
- * and assoc responses.
- */
- struct wme_param_ie wme_param_ie;
- u16 wme_retries[AC_COUNT]; /* per-AC retry limits */
-
- u16 tx_prec_map; /* Precedence map based on HW FIFO space */
- u16 fifo2prec_map[NFIFO]; /* pointer to fifo2_prec map based on WME */
-
- /*
- * BSS Configurations set of BSS configurations, idx 0 is default and
- * always valid
- */
- struct brcms_bss_cfg *bsscfg[BRCMS_MAXBSSCFG];
- struct brcms_bss_cfg *cfg; /* the primary bsscfg (can be AP or STA) */
+ u16 edcf_txop[AC_COUNT];
+
+ u16 wme_retries[AC_COUNT];
+ u16 tx_prec_map;
+ u16 fifo2prec_map[NFIFO];
+
+ struct brcms_bss_cfg *bsscfg;
/* tx queue */
- struct brcms_txq_info *tx_queues; /* common TX Queue list */
-
- /* security */
- struct wsec_key *wsec_keys[WSEC_MAX_KEYS]; /* dynamic key storage */
- /* default key storage */
- struct wsec_key *wsec_def_keys[BRCMS_DEFAULT_KEYS];
- bool wsec_swkeys; /* indicates that all keys should be
- * treated as sw keys (used for debugging)
- */
+ struct brcms_txq_info *tx_queues;
+
struct modulecb *modulecb;
- u8 mimoft; /* SIGN or 11N */
- s8 cck_40txbw; /* 11N, cck tx b/w override when in 40MHZ mode */
- s8 ofdm_40txbw; /* 11N, ofdm tx b/w override when in 40MHZ mode */
- s8 mimo_40txbw; /* 11N, mimo tx b/w override when in 40MHZ mode */
- /* HT CAP IE being advertised by this node: */
- struct ieee80211_ht_cap ht_cap;
+ u8 mimoft;
+ s8 cck_40txbw;
+ s8 ofdm_40txbw;
+ s8 mimo_40txbw;
- struct brcms_bss_info *default_bss; /* configured BSS parameters */
+ struct brcms_bss_info *default_bss;
- u16 mc_fid_counter; /* BC/MC FIFO frame ID counter */
+ u16 mc_fid_counter;
- /* saved country for leaving 802.11d auto-country mode */
char country_default[BRCM_CNTRY_BUF_SZ];
- /* initial country for 802.11d auto-country mode */
char autocountry_default[BRCM_CNTRY_BUF_SZ];
- u16 prb_resp_timeout; /* do not send prb resp if request older than this,
- * 0 = disable
- */
-
- wlc_rateset_t sup_rates_override; /* use only these rates in 11g supported rates if
- * specifed
- */
+ u16 prb_resp_timeout;
- chanspec_t home_chanspec; /* shared home chanspec */
+ u16 home_chanspec;
/* PHY parameters */
- chanspec_t chanspec; /* target operational channel */
- u16 usr_fragthresh; /* user configured fragmentation threshold */
- u16 fragthresh[NFIFO]; /* per-fifo fragmentation thresholds */
- u16 RTSThresh; /* 802.11 dot11RTSThreshold */
- u16 SRL; /* 802.11 dot11ShortRetryLimit */
- u16 LRL; /* 802.11 dot11LongRetryLimit */
- u16 SFBL; /* Short Frame Rate Fallback Limit */
- u16 LFBL; /* Long Frame Rate Fallback Limit */
+ u16 chanspec;
+ u16 usr_fragthresh;
+ u16 fragthresh[NFIFO];
+ u16 RTSThresh;
+ u16 SRL;
+ u16 LRL;
+ u16 SFBL;
+ u16 LFBL;
/* network config */
- bool shortslot; /* currently using 11g ShortSlot timing */
- s8 shortslot_override; /* 11g ShortSlot override */
- bool include_legacy_erp; /* include Legacy ERP info elt ID 47 as well as g ID 42 */
+ bool shortslot;
+ s8 shortslot_override;
+ bool include_legacy_erp;
struct brcms_protection *protection;
- s8 PLCPHdr_override; /* 802.11b Preamble Type override */
+ s8 PLCPHdr_override;
struct brcms_stf *stf;
- ratespec_t bcn_rspec; /* save bcn ratespec purpose */
+ u32 bcn_rspec;
uint tempsense_lasttime;
- u16 tx_duty_cycle_ofdm; /* maximum allowed duty cycle for OFDM */
- u16 tx_duty_cycle_cck; /* maximum allowed duty cycle for CCK */
+ u16 tx_duty_cycle_ofdm;
+ u16 tx_duty_cycle_cck;
- u16 next_bsscfg_ID;
-
- struct brcms_txq_info *pkt_queue; /* txq for transmit packets */
- u32 mpc_dur; /* total time (ms) in mpc mode except for the
- * portion since radio is turned off last time
- */
- u32 mpc_laston_ts; /* timestamp (ms) when radio is turned off last
- * time
- */
+ struct brcms_txq_info *pkt_queue;
struct wiphy *wiphy;
+ struct scb pri_scb;
};
/* antsel module specific state */
@@ -782,244 +619,117 @@ struct antsel_info {
struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */
};
-/* BSS configuration state */
+/*
+ * BSS configuration state
+ *
+ * wlc: wlc to which this bsscfg belongs to.
+ * up: is this configuration up operational
+ * enable: is this configuration enabled
+ * associated: is BSS in ASSOCIATED state
+ * BSS: infraustructure or adhoc
+ * 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; /* wlc to which this bsscfg belongs to. */
- bool up; /* is this configuration up operational */
- bool enable; /* is this configuration enabled */
- bool associated; /* is BSS in ASSOCIATED state */
- bool BSS; /* infraustructure or adhac */
- bool dtim_programmed;
-
- u8 SSID_len; /* the length of SSID */
- u8 SSID[IEEE80211_MAX_SSID_LEN]; /* SSID string */
- struct scb *bcmc_scb[MAXBANDS]; /* one bcmc_scb per band */
- s8 _idx; /* the index of this bsscfg,
- * assigned at wlc_bsscfg_alloc()
- */
- /* MAC filter */
- uint nmac; /* # of entries on maclist array */
- int macmode; /* allow/deny stations on maclist array */
- struct ether_addr *maclist; /* list of source MAC addrs to match */
-
- /* security */
- u32 wsec; /* wireless security bitvec */
- s16 auth; /* 802.11 authentication: Open, Shared Key, WPA */
- s16 openshared; /* try Open auth first, then Shared Key */
- bool wsec_restrict; /* drop unencrypted packets if wsec is enabled */
- bool eap_restrict; /* restrict data until 802.1X auth succeeds */
- u16 WPA_auth; /* WPA: authenticated key management */
- bool wpa2_preauth; /* default is true, wpa_cap sets value */
- bool wsec_portopen; /* indicates keys are plumbed */
- /* global txiv for WPA_NONE, tkip and aes */
- struct wsec_iv wpa_none_txiv;
- int wsec_index; /* 0-3: default tx key, -1: not set */
- /* default key storage: */
- struct wsec_key *bss_def_keys[BRCMS_DEFAULT_KEYS];
-
- /* TKIP countermeasures */
- bool tkip_countermeasures; /* flags TKIP no-assoc period */
- u32 tk_cm_dt; /* detect timer */
- u32 tk_cm_bt; /* blocking timer */
- u32 tk_cm_bt_tmstmp; /* Timestamp when TKIP BT is activated */
- bool tk_cm_activate; /* activate countermeasures after EAPOL-Key sent */
-
- u8 BSSID[ETH_ALEN]; /* BSSID (associated) */
- u8 cur_etheraddr[ETH_ALEN]; /* h/w address */
- u16 bcmc_fid; /* the last BCMC FID queued to TX_BCMC_FIFO */
- u16 bcmc_fid_shm; /* the last BCMC FID written to shared mem */
-
- u32 flags; /* BSSCFG flags; see below */
-
- u8 *bcn; /* AP beacon */
- uint bcn_len; /* AP beacon length */
- bool ar_disassoc; /* disassociated in associated recreation */
-
- int auth_atmptd; /* auth type (open/shared) attempted */
-
- pmkid_cand_t pmkid_cand[MAXPMKID]; /* PMKID candidate list */
- uint npmkid_cand; /* num PMKID candidates */
- pmkid_t pmkid[MAXPMKID]; /* PMKID cache */
- uint npmkid; /* num cached PMKIDs */
-
- struct brcms_bss_info *current_bss; /* BSS parms in ASSOCIATED state */
-
- /* PM states */
- bool PMawakebcn; /* bcn recvd during current waking state */
- bool PMpending; /* waiting for tx status with PM indicated set */
- bool priorPMstate; /* Detecting PM state transitions */
- bool PSpoll; /* whether there is an outstanding PS-Poll frame */
-
- /* BSSID entry in RCMTA, use the wsec key management infrastructure to
- * manage the RCMTA entries.
- */
- struct wsec_key *rcmta;
-
- /* 'unique' ID of this bsscfg, assigned at bsscfg allocation */
- u16 ID;
-
- uint txrspecidx; /* index into tx rate circular buffer */
- ratespec_t txrspec[NTXRATE][2]; /* circular buffer of prev MPDUs tx rates */
+ struct brcms_c_info *wlc;
+ bool up;
+ bool enable;
+ bool associated;
+ bool BSS;
+ u8 SSID_len;
+ u8 SSID[IEEE80211_MAX_SSID_LEN];
+ u8 BSSID[ETH_ALEN];
+ u8 cur_etheraddr[ETH_ALEN];
+ struct brcms_bss_info *current_bss;
};
-#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))
-
-#define IS_MBAND_UNLOCKED(wlc) \
- ((NBANDS(wlc) > 1) && !(wlc)->bandlocked)
-
-#define BRCMS_BAND_PI_RADIO_CHANSPEC wlc_phy_chanspec_get(wlc->band->pi)
-
-/* sum the individual fifo tx pending packet counts */
-#define TXPKTPENDTOT(wlc) ((wlc)->core->txpktpend[0] + (wlc)->core->txpktpend[1] + \
- (wlc)->core->txpktpend[2] + (wlc)->core->txpktpend[3])
-#define TXPKTPENDGET(wlc, fifo) ((wlc)->core->txpktpend[(fifo)])
-#define TXPKTPENDINC(wlc, fifo, val) ((wlc)->core->txpktpend[(fifo)] += (val))
-#define TXPKTPENDDEC(wlc, fifo, val) ((wlc)->core->txpktpend[(fifo)] -= (val))
-#define TXPKTPENDCLR(wlc, fifo) ((wlc)->core->txpktpend[(fifo)] = 0)
-#define TXAVAIL(wlc, fifo) (*(wlc)->core->txavail[(fifo)])
-#define GETNEXTTXP(wlc, _queue) \
- dma_getnexttxp((wlc)->hw->di[(_queue)], DMA_RANGE_TRANSMITTED)
-
-#define BRCMS_IS_MATCH_SSID(wlc, ssid1, ssid2, len1, len2) \
- ((len1 == len2) && !memcmp(ssid1, ssid2, len1))
-
-extern void brcms_c_fatal_error(struct brcms_c_info *wlc);
-extern void brcms_b_rpc_watchdog(struct brcms_c_info *wlc);
-extern void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p);
-extern bool brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs,
- u32 frm_tx2);
extern void brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo,
struct sk_buff *p,
bool commit, s8 txpktpend);
extern void brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo,
s8 txpktpend);
-extern void brcms_c_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
- uint prec);
-extern void brcms_c_info_init(struct brcms_c_info *wlc, int unit);
+extern void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb,
+ struct sk_buff *sdu, uint prec);
extern void brcms_c_print_txstatus(struct tx_status *txs);
-extern int brcms_c_xmtfifo_sz_get(struct brcms_c_info *wlc, uint fifo,
- uint *blocks);
-extern void brcms_c_write_template_ram(struct brcms_c_info *wlc, int offset,
- int len, void *buf);
-extern void brcms_c_write_hw_bcntemplates(struct brcms_c_info *wlc, void *bcn,
- int len, bool both);
-extern void brcms_c_pllreq(struct brcms_c_info *wlc, bool set, mbool req_bit);
-extern void brcms_c_reset_bmac_done(struct brcms_c_info *wlc);
+extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
+ uint *blocks);
#if defined(BCMDBG)
-extern void brcms_c_print_rxh(struct d11rxhdr *rxh);
extern void brcms_c_print_txdesc(struct d11txh *txh);
#else
#define brcms_c_print_txdesc(a)
#endif
-extern void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit);
-extern void brcms_c_coredisable(struct brcms_hardware *wlc_hw);
-
-extern bool brcms_c_valid_rate(struct brcms_c_info *wlc, ratespec_t rate,
- int band, bool verbose);
-extern void brcms_c_ap_upd(struct brcms_c_info *wlc);
-
-/* helper functions */
-extern void brcms_c_shm_ssid_upd(struct brcms_c_info *wlc,
- struct brcms_bss_cfg *cfg);
extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config);
-
extern void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc,
bool promisc);
-extern void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc);
-extern void brcms_c_mac_promisc(struct brcms_c_info *wlc);
-extern void brcms_c_txflowcontrol(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi,
- bool on, int prio);
-extern void brcms_c_txflowcontrol_override(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi,
- bool on, uint override);
-extern bool brcms_c_txflowcontrol_prio_isset(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi,
- int prio);
extern void brcms_c_send_q(struct brcms_c_info *wlc);
extern int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu,
uint *fifo);
-
-extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, ratespec_t ratespec,
+extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
uint mac_len);
-extern ratespec_t brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc,
- ratespec_t rspec,
+extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc,
+ u32 rspec,
bool use_rspec, u16 mimo_ctlchbw);
extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
- ratespec_t rts_rate,
- ratespec_t frame_rate,
+ u32 rts_rate,
+ u32 frame_rate,
u8 rts_preamble_type,
u8 frame_preamble_type, uint frame_len,
bool ba);
-
-extern void brcms_c_tbtt(struct brcms_c_info *wlc);
extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
struct ieee80211_sta *sta,
void (*dma_callback_fn));
-
-extern void brcms_c_reprate_init(struct brcms_c_info *wlc);
-extern void brcms_c_bsscfg_reprate_init(struct brcms_bss_cfg *bsscfg);
-
-/* Shared memory access */
-extern void brcms_c_write_shm(struct brcms_c_info *wlc, uint offset, u16 v);
-extern u16 brcms_c_read_shm(struct brcms_c_info *wlc, uint offset);
-extern void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset,
- const void *buf, int len);
-
extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
-extern void brcms_c_bss_update_beacon(struct brcms_c_info *wlc,
- struct brcms_bss_cfg *bsscfg);
-
extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend);
-extern void brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
- struct brcms_bss_cfg *cfg,
- bool suspend);
-extern bool brcms_c_ismpc(struct brcms_c_info *wlc);
-extern bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc);
-extern void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc);
-extern bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q,
- void *pkt, int prec);
-extern bool brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
- struct sk_buff *pkt, int prec, bool head);
-extern u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, ratespec_t rspec);
-extern void brcms_c_compute_plcp(struct brcms_c_info *wlc, ratespec_t rate,
- uint length, u8 *plcp);
-extern uint brcms_c_calc_frame_time(struct brcms_c_info *wlc,
- ratespec_t ratespec,
- u8 preamble_type, uint mac_len);
-
-extern void brcms_c_set_chanspec(struct brcms_c_info *wlc,
- chanspec_t chanspec);
-
-extern bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit);
-
-extern int brcms_c_set_nmode(struct brcms_c_info *wlc, s32 nmode);
-extern void brcms_c_mimops_action_ht_send(struct brcms_c_info *wlc,
- struct brcms_bss_cfg *bsscfg,
- u8 mimops_mode);
-
-extern void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot);
-extern void brcms_c_set_bssid(struct brcms_bss_cfg *cfg);
-extern void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend);
-
-extern void brcms_c_set_ratetable(struct brcms_c_info *wlc);
-extern int brcms_c_set_mac(struct brcms_bss_cfg *cfg);
+extern int brcms_c_set_nmode(struct brcms_c_info *wlc);
extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
- ratespec_t bcn_rate);
-extern void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc,
- uint frame_len);
-extern ratespec_t brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc,
- wlc_rateset_t *rs);
-extern void brcms_c_radio_disable(struct brcms_c_info *wlc);
-extern void brcms_c_bcn_li_upd(struct brcms_c_info *wlc);
-extern void brcms_c_set_home_chanspec(struct brcms_c_info *wlc,
- chanspec_t chanspec);
-extern bool brcms_c_ps_allowed(struct brcms_c_info *wlc);
-extern bool brcms_c_stay_awake(struct brcms_c_info *wlc);
-extern void brcms_c_wme_initparams_sta(struct brcms_c_info *wlc,
- struct wme_param_ie *pe);
+ u32 bcn_rate);
+extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw,
+ u8 antsel_type);
+extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw,
+ u16 chanspec,
+ bool mute, struct txpwr_limits *txpwr);
+extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset,
+ u16 v);
+extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset);
+extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask,
+ u16 val, int bands);
+extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags);
+extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val);
+extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw);
+extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw);
+extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw);
+extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
+ u32 override_bit);
+extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
+ u32 override_bit);
+extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw,
+ int offset, int len, void *buf);
+extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate);
+extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw,
+ uint offset, const void *buf, int len,
+ u32 sel);
+extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset,
+ void *buf, int len, u32 sel);
+extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode);
+extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw);
+extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk);
+extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk);
+extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on);
+extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant);
+extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw,
+ u8 stf_mode);
+extern void brcms_c_init_scb(struct scb *scb);
#endif /* _BRCM_MAIN_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/nicpci.c b/drivers/staging/brcm80211/brcmsmac/nicpci.c
index 3d71c590fcef..0bcb26792046 100644
--- a/drivers/staging/brcm80211/brcmsmac/nicpci.c
+++ b/drivers/staging/brcm80211/brcmsmac/nicpci.c
@@ -127,6 +127,18 @@
/* PCIE protocol TLP diagnostic registers */
#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */
+/* Sonics to PCI translation types */
+#define SBTOPCI_PREF 0x4 /* prefetch enable */
+#define SBTOPCI_BURST 0x8 /* burst enable */
+#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */
+
+#define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */
+
+/* PCI core index in SROM shadow area */
+#define SRSH_PI_OFFSET 0 /* first word */
+#define SRSH_PI_MASK 0xf000 /* bit 15:12 */
+#define SRSH_PI_SHIFT 12 /* bit 15:12 */
+
/* Sonics side: PCI core and host control registers */
struct sbpciregs {
u32 control; /* PCI control */
@@ -194,8 +206,8 @@ struct sbpcieregs {
struct pcicore_info {
union {
- struct sbpcieregs *pcieregs;
- struct sbpciregs *pciregs;
+ struct sbpcieregs __iomem *pcieregs;
+ struct sbpciregs __iomem *pciregs;
} regs; /* Memory mapped register to the core */
struct si_pub *sih; /* System interconnect handle */
@@ -211,52 +223,30 @@ struct pcicore_info {
bool pmecap; /* Capable of generating PME */
};
-/* debug/trace */
-#define PCI_ERROR(args)
-#define PCIE_PUB(sih) \
- (((sih)->bustype == PCI_BUS) && \
- ((sih)->buscoretype == PCIE_CORE_ID))
-
-/* routines to access mdio slave device registers */
-static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk);
-static int pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr,
- bool write, uint *val);
-static int pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint readdr,
- uint val);
-static int pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint readdr,
- uint *ret_val);
-
-static void pcie_extendL1timer(struct pcicore_info *pi, bool extend);
-static void pcie_clkreq_upd(struct pcicore_info *pi, uint state);
-
-static void pcie_war_aspm_clkreq(struct pcicore_info *pi);
-static void pcie_war_serdes(struct pcicore_info *pi);
-static void pcie_war_noplldown(struct pcicore_info *pi);
-static void pcie_war_polarity(struct pcicore_info *pi);
-static void pcie_war_pci_setup(struct pcicore_info *pi);
-
#define PCIE_ASPM(sih) \
- ((PCIE_PUB(sih)) && \
+ (((sih)->buscoretype == PCIE_CORE_ID) && \
(((sih)->buscorerev >= 3) && \
((sih)->buscorerev <= 5)))
/* delay needed between the mdio control/ mdiodata register data access */
-#define PR28829_DELAY() udelay(10)
+static void pr28829_delay(void)
+{
+ udelay(10);
+}
/* Initialize the PCI core.
* It's caller's responsibility to make sure that this is done only once
*/
-void *pcicore_init(struct si_pub *sih, void *pdev, void *regs)
+struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev,
+ void __iomem *regs)
{
struct pcicore_info *pi;
/* alloc struct pcicore_info */
pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC);
- if (pi == NULL) {
- PCI_ERROR(("pci_attach: malloc failed!\n"));
+ if (pi == NULL)
return NULL;
- }
pi->sih = sih;
pi->dev = pdev;
@@ -273,7 +263,7 @@ void *pcicore_init(struct si_pub *sih, void *pdev, void *regs)
return pi;
}
-void pcicore_deinit(void *pch)
+void pcicore_deinit(struct pcicore_info *pch)
{
kfree(pch);
}
@@ -281,7 +271,7 @@ void pcicore_deinit(void *pch)
/* return cap_offset if requested capability exists in the PCI config space */
/* Note that it's caller's responsibility to make sure it's a pci bus */
u8
-pcicore_find_pci_capability(void *dev, u8 req_cap_id,
+pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id,
unsigned char *buf, u32 *buflen)
{
u8 cap_id;
@@ -344,7 +334,7 @@ end:
/* ***** Register Access API */
static uint
-pcie_readreg(struct sbpcieregs *pcieregs, uint addrtype, uint offset)
+pcie_readreg(struct sbpcieregs __iomem *pcieregs, uint addrtype, uint offset)
{
uint retval = 0xFFFFFFFF;
@@ -364,8 +354,8 @@ pcie_readreg(struct sbpcieregs *pcieregs, uint addrtype, uint offset)
return retval;
}
-static uint
-pcie_writereg(struct sbpcieregs *pcieregs, uint addrtype, uint offset, uint val)
+static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype,
+ uint offset, uint val)
{
switch (addrtype) {
case PCIE_CONFIGREGS:
@@ -384,7 +374,7 @@ pcie_writereg(struct sbpcieregs *pcieregs, uint addrtype, uint offset, uint val)
static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
{
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
uint mdiodata, i = 0;
uint pcie_serdes_spinwait = 200;
@@ -394,19 +384,18 @@ static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
(blk << 4));
W_REG(&pcieregs->mdiodata, mdiodata);
- PR28829_DELAY();
+ pr28829_delay();
/* retry till the transaction is complete */
while (i < pcie_serdes_spinwait) {
if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE)
break;
+
udelay(1000);
i++;
}
- if (i >= pcie_serdes_spinwait) {
- PCI_ERROR(("pcie_mdiosetblock: timed out\n"));
+ if (i >= pcie_serdes_spinwait)
return false;
- }
return true;
}
@@ -415,7 +404,7 @@ static int
pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
uint *val)
{
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
uint mdiodata;
uint i = 0;
uint pcie_serdes_spinwait = 10;
@@ -445,13 +434,13 @@ pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
W_REG(&pcieregs->mdiodata, mdiodata);
- PR28829_DELAY();
+ pr28829_delay();
/* retry till the transaction is complete */
while (i < pcie_serdes_spinwait) {
if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) {
if (!write) {
- PR28829_DELAY();
+ pr28829_delay();
*val = (R_REG(&pcieregs->mdiodata) &
MDIODATA_MASK);
}
@@ -463,8 +452,7 @@ pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
i++;
}
- PCI_ERROR(("pcie_mdioop: timed out op: %d\n", write));
- /* Disable mdio access to SERDES */
+ /* Timed out. Disable mdio access to SERDES. */
W_REG(&pcieregs->mdiocontrol, 0);
return 1;
}
@@ -485,9 +473,8 @@ pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val)
}
/* ***** Support functions ***** */
-static u8 pcie_clkreq(void *pch, u32 mask, u32 val)
+static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val)
{
- struct pcicore_info *pi = pch;
u32 reg_val;
u8 offset;
@@ -515,9 +502,9 @@ static void pcie_extendL1timer(struct pcicore_info *pi, bool extend)
{
u32 w;
struct si_pub *sih = pi->sih;
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
- if (!PCIE_PUB(sih) || sih->buscorerev < 7)
+ if (sih->buscoretype != PCIE_CORE_ID || sih->buscorerev < 7)
return;
w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
@@ -537,30 +524,30 @@ static void pcie_clkreq_upd(struct pcicore_info *pi, uint state)
switch (state) {
case SI_DOATTACH:
if (PCIE_ASPM(sih))
- pcie_clkreq((void *)pi, 1, 0);
+ pcie_clkreq(pi, 1, 0);
break;
case SI_PCIDOWN:
if (sih->buscorerev == 6) { /* turn on serdes PLL down */
ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_addr),
+ offsetof(struct chipcregs, chipcontrol_addr),
~0, 0);
ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data),
+ offsetof(struct chipcregs, chipcontrol_data),
~0x40, 0);
} else if (pi->pcie_pr42767) {
- pcie_clkreq((void *)pi, 1, 1);
+ pcie_clkreq(pi, 1, 1);
}
break;
case SI_PCIUP:
if (sih->buscorerev == 6) { /* turn off serdes PLL down */
ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_addr),
+ offsetof(struct chipcregs, chipcontrol_addr),
~0, 0);
ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data),
+ offsetof(struct chipcregs, chipcontrol_data),
~0x40, 0x40);
} else if (PCIE_ASPM(sih)) { /* disable clkreq */
- pcie_clkreq((void *)pi, 1, 0);
+ pcie_clkreq(pi, 1, 0);
}
break;
}
@@ -594,9 +581,10 @@ static void pcie_war_polarity(struct pcicore_info *pi)
*/
static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
{
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
struct si_pub *sih = pi->sih;
- u16 val16, *reg16;
+ u16 val16;
+ u16 __iomem *reg16;
u32 w;
if (!PCIE_ASPM(sih))
@@ -654,8 +642,9 @@ static void pcie_war_serdes(struct pcicore_info *pi)
/* Needs to happen when coming out of 'standby'/'hibernate' */
static void pcie_misc_config_fixup(struct pcicore_info *pi)
{
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
- u16 val16, *reg16;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
+ u16 val16;
+ u16 __iomem *reg16;
reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG];
val16 = R_REG(reg16);
@@ -670,11 +659,11 @@ static void pcie_misc_config_fixup(struct pcicore_info *pi)
/* Needs to happen when coming out of 'standby'/'hibernate' */
static void pcie_war_noplldown(struct pcicore_info *pi)
{
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
- u16 *reg16;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
+ u16 __iomem *reg16;
/* turn off serdes PLL down */
- ai_corereg(pi->sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol),
+ ai_corereg(pi->sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol),
CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
/* clear srom shadow backdoor */
@@ -686,7 +675,7 @@ static void pcie_war_noplldown(struct pcicore_info *pi)
static void pcie_war_pci_setup(struct pcicore_info *pi)
{
struct si_pub *sih = pi->sih;
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
u32 w;
if (sih->buscorerev == 0 || sih->buscorerev == 1) {
@@ -730,14 +719,14 @@ static void pcie_war_pci_setup(struct pcicore_info *pi)
}
/* ***** Functions called during driver state changes ***** */
-void pcicore_attach(void *pch, char *pvars, int state)
+void pcicore_attach(struct pcicore_info *pi, int state)
{
- struct pcicore_info *pi = pch;
struct si_pub *sih = pi->sih;
+ u32 bfl2 = (u32)getintvar(sih, BRCMS_SROM_BOARDFLAGS2);
/* Determine if this board needs override */
if (PCIE_ASPM(sih)) {
- if ((u32)getintvar(pvars, "boardflags2") & BFL2_PCIEWAR_OVR)
+ if (bfl2 & BFL2_PCIEWAR_OVR)
pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB;
else
pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB;
@@ -754,21 +743,17 @@ void pcicore_attach(void *pch, char *pvars, int state)
}
-void pcicore_hwup(void *pch)
+void pcicore_hwup(struct pcicore_info *pi)
{
- struct pcicore_info *pi = pch;
-
- if (!pi || !PCIE_PUB(pi->sih))
+ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
return;
pcie_war_pci_setup(pi);
}
-void pcicore_up(void *pch, int state)
+void pcicore_up(struct pcicore_info *pi, int state)
{
- struct pcicore_info *pi = pch;
-
- if (!pi || !PCIE_PUB(pi->sih))
+ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
return;
/* Restore L1 timer for better performance */
@@ -780,9 +765,8 @@ void pcicore_up(void *pch, int state)
/* When the device is going to enter D3 state
* (or the system is going to enter S3/S4 states)
*/
-void pcicore_sleep(void *pch)
+void pcicore_sleep(struct pcicore_info *pi)
{
- struct pcicore_info *pi = pch;
u32 w;
if (!pi || !PCIE_ASPM(pi->sih))
@@ -795,11 +779,9 @@ void pcicore_sleep(void *pch)
pi->pcie_pr42767 = false;
}
-void pcicore_down(void *pch, int state)
+void pcicore_down(struct pcicore_info *pi, int state)
{
- struct pcicore_info *pi = pch;
-
- if (!pi || !PCIE_PUB(pi->sih))
+ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
return;
pcie_clkreq_upd(pi, state);
@@ -809,20 +791,12 @@ void pcicore_down(void *pch, int state)
}
/* precondition: current core is sii->buscoretype */
-void pcicore_fixcfg(void *pch, void *regs)
+static void pcicore_fixcfg(struct pcicore_info *pi, u16 __iomem *reg16)
{
- struct pcicore_info *pi = pch;
- struct si_info *sii = SI_INFO(pi->sih);
- struct sbpciregs *pciregs = regs;
- struct sbpcieregs *pcieregs = regs;
- u16 val16, *reg16 = NULL;
+ struct si_info *sii = (struct si_info *)(pi->sih);
+ u16 val16;
uint pciidx;
- /* check 'pi' is correct and fix it if not */
- if (sii->pub.buscoretype == PCIE_CORE_ID)
- reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
- else if (sii->pub.buscoretype == PCI_CORE_ID)
- reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
pciidx = ai_coreidx(&sii->pub);
val16 = R_REG(reg16);
if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) {
@@ -832,16 +806,27 @@ void pcicore_fixcfg(void *pch, void *regs)
}
}
+void
+pcicore_fixcfg_pci(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs)
+{
+ pcicore_fixcfg(pi, &pciregs->sprom[SRSH_PI_OFFSET]);
+}
+
+void pcicore_fixcfg_pcie(struct pcicore_info *pi,
+ struct sbpcieregs __iomem *pcieregs)
+{
+ pcicore_fixcfg(pi, &pcieregs->sprom[SRSH_PI_OFFSET]);
+}
+
/* precondition: current core is pci core */
-void pcicore_pci_setup(void *pch, void *regs)
+void
+pcicore_pci_setup(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs)
{
- struct pcicore_info *pi = pch;
- struct sbpciregs *pciregs = regs;
u32 w;
OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST);
- if (SI_INFO(pi->sih)->pub.buscorerev >= 11) {
+ if (((struct si_info *)(pi->sih))->pub.buscorerev >= 11) {
OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
w = R_REG(&pciregs->clkrun);
W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL);
diff --git a/drivers/staging/brcm80211/brcmsmac/nicpci.h b/drivers/staging/brcm80211/brcmsmac/nicpci.h
index f71f842a2156..58aa80dc3329 100644
--- a/drivers/staging/brcm80211/brcmsmac/nicpci.h
+++ b/drivers/staging/brcm80211/brcmsmac/nicpci.h
@@ -58,28 +58,25 @@
/* bar0 + 12K accesses chipc core registers */
#define PCI_16KB0_CCREGS_OFFSET (12 * 1024)
-#define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */
+struct sbpciregs;
+struct sbpcieregs;
-/* Sonics to PCI translation types */
-#define SBTOPCI_PREF 0x4 /* prefetch enable */
-#define SBTOPCI_BURST 0x8 /* burst enable */
-#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */
-
-/* PCI core index in SROM shadow area */
-#define SRSH_PI_OFFSET 0 /* first word */
-#define SRSH_PI_MASK 0xf000 /* bit 15:12 */
-#define SRSH_PI_SHIFT 12 /* bit 15:12 */
-
-extern void *pcicore_init(struct si_pub *sih, void *pdev, void *regs);
-extern void pcicore_deinit(void *pch);
-extern void pcicore_attach(void *pch, char *pvars, int state);
-extern void pcicore_hwup(void *pch);
-extern void pcicore_up(void *pch, int state);
-extern void pcicore_sleep(void *pch);
-extern void pcicore_down(void *pch, int state);
-extern u8 pcicore_find_pci_capability(void *dev, u8 req_cap_id,
- unsigned char *buf, u32 *buflen);
-extern void pcicore_fixcfg(void *pch, void *regs);
-extern void pcicore_pci_setup(void *pch, void *regs);
+extern struct pcicore_info *pcicore_init(struct si_pub *sih,
+ struct pci_dev *pdev,
+ void __iomem *regs);
+extern void pcicore_deinit(struct pcicore_info *pch);
+extern void pcicore_attach(struct pcicore_info *pch, int state);
+extern void pcicore_hwup(struct pcicore_info *pch);
+extern void pcicore_up(struct pcicore_info *pch, int state);
+extern void pcicore_sleep(struct pcicore_info *pch);
+extern void pcicore_down(struct pcicore_info *pch, int state);
+extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id,
+ unsigned char *buf, u32 *buflen);
+extern void pcicore_fixcfg_pci(struct pcicore_info *pch,
+ struct sbpciregs __iomem *pciregs);
+extern void pcicore_fixcfg_pcie(struct pcicore_info *pch,
+ struct sbpcieregs __iomem *pciregs);
+extern void pcicore_pci_setup(struct pcicore_info *pch,
+ struct sbpciregs __iomem *pciregs);
#endif /* _BRCM_NICPCI_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/otp.c b/drivers/staging/brcm80211/brcmsmac/otp.c
index 4a70180eba5d..edf551561fd8 100644
--- a/drivers/staging/brcm80211/brcmsmac/otp.c
+++ b/drivers/staging/brcm80211/brcmsmac/otp.c
@@ -25,10 +25,14 @@
#define OTPS_GUP_MASK 0x00000f00
#define OTPS_GUP_SHIFT 8
-#define OTPS_GUP_HW 0x00000100 /* h/w subregion is programmed */
-#define OTPS_GUP_SW 0x00000200 /* s/w subregion is programmed */
-#define OTPS_GUP_CI 0x00000400 /* chipid/pkgopt subregion is programmed */
-#define OTPS_GUP_FUSE 0x00000800 /* fuse subregion is programmed */
+/* h/w subregion is programmed */
+#define OTPS_GUP_HW 0x00000100
+/* s/w subregion is programmed */
+#define OTPS_GUP_SW 0x00000200
+/* chipid/pkgopt subregion is programmed */
+#define OTPS_GUP_CI 0x00000400
+/* fuse subregion is programmed */
+#define OTPS_GUP_FUSE 0x00000800
/* Fields in otpprog in rev >= 21 */
#define OTPP_COL_MASK 0x000000ff
@@ -60,28 +64,21 @@
#define MAXNUMRDES 9 /* Maximum OTP redundancy entries */
-/* OTP common function type */
-typedef int (*otp_status_t) (void *oh);
-typedef int (*otp_size_t) (void *oh);
-typedef void *(*otp_init_t) (struct si_pub *sih);
-typedef u16(*otp_read_bit_t) (void *oh, chipcregs_t *cc, uint off);
-typedef int (*otp_read_region_t) (struct si_pub *sih, int region, u16 *data,
- uint *wlen);
-typedef int (*otp_nvread_t) (void *oh, char *data, uint *len);
+/* Fixed size subregions sizes in words */
+#define OTPGU_CI_SZ 2
+
+struct otpinfo;
/* OTP function struct */
struct otp_fn_s {
- otp_size_t size;
- otp_read_bit_t read_bit;
- otp_init_t init;
- otp_read_region_t read_region;
- otp_nvread_t nvread;
- otp_status_t status;
+ int (*init)(struct si_pub *sih, struct otpinfo *oi);
+ int (*read_region)(struct otpinfo *oi, int region, u16 *data,
+ uint *wlen);
};
struct otpinfo {
uint ccrev; /* chipc revision */
- struct otp_fn_s *fn; /* OTP functions */
+ const struct otp_fn_s *fn; /* OTP functions */
struct si_pub *sih; /* Saved sb handle */
/* IPX OTP section */
@@ -100,23 +97,6 @@ struct otpinfo {
int otpgu_base; /* offset to General Use Region */
};
-static struct otpinfo otpinfo;
-
-/*
- * IPX OTP Code
- *
- * Exported functions:
- * ipxotp_status()
- * ipxotp_size()
- * ipxotp_init()
- * ipxotp_read_bit()
- * ipxotp_read_region()
- * ipxotp_nvread()
- *
- */
-
-#define HWSW_RGN(rgn) (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
-
/* OTP layout */
/* CC revs 21, 24 and 27 OTP General Use Region word offset */
#define REVA4_OTPGU_BASE 12
@@ -152,60 +132,15 @@ static struct otpinfo otpinfo;
#define OTP4315_SWREG_SZ 178 /* 178 bytes */
#define OTP_SZ_FU_144 (144/8) /* 144 bits */
-static int ipxotp_status(void *oh)
+static u16
+ipxotp_otpr(struct otpinfo *oi, struct chipcregs __iomem *cc, uint wn)
{
- struct otpinfo *oi = (struct otpinfo *) oh;
- return (int)(oi->status);
-}
-
-/* Return size in bytes */
-static int ipxotp_size(void *oh)
-{
- struct otpinfo *oi = (struct otpinfo *) oh;
- return (int)oi->wsize * 2;
-}
-
-static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
-{
- struct otpinfo *oi;
-
- oi = (struct otpinfo *) oh;
-
return R_REG(&cc->sromotp[wn]);
}
-static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
-{
- struct otpinfo *oi = (struct otpinfo *) oh;
- uint k, row, col;
- u32 otpp, st;
-
- row = off / oi->cols;
- col = off % oi->cols;
-
- otpp = OTPP_START_BUSY |
- ((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
- ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
- ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
- W_REG(&cc->otpprog, otpp);
-
- for (k = 0;
- ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
- && (k < OTPP_TRIES); k++)
- ;
- if (k >= OTPP_TRIES) {
- return 0xffff;
- }
- if (st & OTPP_READERR) {
- return 0xffff;
- }
- st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
-
- return (int)st;
-}
-
-/* Calculate max HW/SW region byte size by subtracting fuse region and checksum size,
- * osizew is oi->wsize (OTP size - GU size) in words
+/*
+ * Calculate max HW/SW region byte size by subtracting fuse region
+ * and checksum size, osizew is oi->wsize (OTP size - GU size) in words
*/
static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
{
@@ -226,17 +161,23 @@ static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
return ret;
}
-static void _ipxotp_init(struct otpinfo *oi, chipcregs_t *cc)
+static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
{
uint k;
u32 otpp, st;
- /* record word offset of General Use Region for various chipcommon revs */
+ /*
+ * record word offset of General Use Region
+ * for various chipcommon revs
+ */
if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
|| oi->sih->ccrev == 27) {
oi->otpgu_base = REVA4_OTPGU_BASE;
} else if (oi->sih->ccrev == 36) {
- /* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */
+ /*
+ * OTP size greater than equal to 2KB (128 words),
+ * otpgu_base is similar to rev23
+ */
if (oi->wsize >= 128)
oi->otpgu_base = REVB8_OTPGU_BASE;
else
@@ -254,9 +195,8 @@ static void _ipxotp_init(struct otpinfo *oi, chipcregs_t *cc)
((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
&& (k < OTPP_TRIES); k++)
;
- if (k >= OTPP_TRIES) {
+ if (k >= OTPP_TRIES)
return;
- }
/* Read OTP lock bits and subregion programmed indication bits */
oi->status = R_REG(&cc->otpstatus);
@@ -272,8 +212,9 @@ static void _ipxotp_init(struct otpinfo *oi, chipcregs_t *cc)
}
/*
- * h/w region base and fuse region limit are fixed to the top and
- * the bottom of the general use region. Everything else can be flexible.
+ * h/w region base and fuse region limit are fixed to
+ * the top and the bottom of the general use region.
+ * Everything else can be flexible.
*/
oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
oi->hwlim = oi->wsize;
@@ -297,28 +238,24 @@ static void _ipxotp_init(struct otpinfo *oi, chipcregs_t *cc)
oi->flim = oi->wsize;
}
-static void *ipxotp_init(struct si_pub *sih)
+static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
{
uint idx;
- chipcregs_t *cc;
- struct otpinfo *oi;
+ struct chipcregs __iomem *cc;
/* Make sure we're running IPX OTP */
if (!OTPTYPE_IPX(sih->ccrev))
- return NULL;
+ return -EBADE;
/* Make sure OTP is not disabled */
if (ai_is_otp_disabled(sih))
- return NULL;
-
- /* OTP is always powered */
- oi = &otpinfo;
+ return -EBADE;
/* Check for otp size */
switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
case 0:
/* Nothing there */
- return NULL;
+ return -EBADE;
case 1: /* 32x64 */
oi->rows = 32;
oi->cols = 64;
@@ -341,7 +278,7 @@ static void *ipxotp_init(struct si_pub *sih)
break;
default:
/* Don't know the geometry */
- return NULL;
+ return -EBADE;
}
/* Retrieve OTP region info */
@@ -352,14 +289,14 @@ static void *ipxotp_init(struct si_pub *sih)
ai_setcoreidx(sih, idx);
- return (void *)oi;
+ return 0;
}
-static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
+static int
+ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen)
{
- struct otpinfo *oi = (struct otpinfo *) oh;
uint idx;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint base, i, sz;
/* Validate region selection */
@@ -433,68 +370,23 @@ static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
/* Read the data */
for (i = 0; i < sz; i++)
- data[i] = ipxotp_otpr(oh, cc, base + i);
+ data[i] = ipxotp_otpr(oi, cc, base + i);
ai_setcoreidx(oi->sih, idx);
*wlen = sz;
return 0;
}
-static int ipxotp_nvread(void *oh, char *data, uint *len)
-{
- return -ENOTSUPP;
-}
-
-static struct otp_fn_s ipxotp_fn = {
- (otp_size_t) ipxotp_size,
- (otp_read_bit_t) ipxotp_read_bit,
-
- (otp_init_t) ipxotp_init,
- (otp_read_region_t) ipxotp_read_region,
- (otp_nvread_t) ipxotp_nvread,
-
- (otp_status_t) ipxotp_status
+static const struct otp_fn_s ipxotp_fn = {
+ (int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init,
+ (int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region,
};
-/*
- * otp_status()
- * otp_size()
- * otp_read_bit()
- * otp_init()
- * otp_read_region()
- * otp_nvread()
- */
-
-int otp_status(void *oh)
+static int otp_init(struct si_pub *sih, struct otpinfo *oi)
{
- struct otpinfo *oi = (struct otpinfo *) oh;
- return oi->fn->status(oh);
-}
+ int ret;
-int otp_size(void *oh)
-{
- struct otpinfo *oi = (struct otpinfo *) oh;
-
- return oi->fn->size(oh);
-}
-
-u16 otp_read_bit(void *oh, uint offset)
-{
- struct otpinfo *oi = (struct otpinfo *) oh;
- uint idx = ai_coreidx(oi->sih);
- chipcregs_t *cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
- u16 readBit = (u16) oi->fn->read_bit(oh, cc, offset);
- ai_setcoreidx(oi->sih, idx);
- return readBit;
-}
-
-void *otp_init(struct si_pub *sih)
-{
- struct otpinfo *oi;
- void *ret = NULL;
-
- oi = &otpinfo;
memset(oi, 0, sizeof(struct otpinfo));
oi->ccrev = sih->ccrev;
@@ -502,21 +394,20 @@ void *otp_init(struct si_pub *sih)
if (OTPTYPE_IPX(oi->ccrev))
oi->fn = &ipxotp_fn;
- if (oi->fn == NULL) {
- return NULL;
- }
+ if (oi->fn == NULL)
+ return -EBADE;
oi->sih = sih;
- ret = (oi->fn->init) (sih);
+ ret = (oi->fn->init) (sih, oi);
return ret;
}
int
-otp_read_region(struct si_pub *sih, int region, u16 *data,
- uint *wlen) {
- void *oh;
+otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) {
+ struct otpinfo otpinfo;
+ struct otpinfo *oi = &otpinfo;
int err = 0;
if (ai_is_otp_disabled(sih)) {
@@ -524,22 +415,12 @@ otp_read_region(struct si_pub *sih, int region, u16 *data,
goto out;
}
- oh = otp_init(sih);
- if (oh == NULL) {
- err = -EBADE;
+ err = otp_init(sih, oi);
+ if (err)
goto out;
- }
- err = (((struct otpinfo *) oh)->fn->read_region)
- (oh, region, data, wlen);
+ err = ((oi)->fn->read_region)(oi, region, data, wlen);
out:
return err;
}
-
-int otp_nvread(void *oh, char *data, uint *len)
-{
- struct otpinfo *oi = (struct otpinfo *) oh;
-
- return oi->fn->nvread(oh, data, len);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/otp.h b/drivers/staging/brcm80211/brcmsmac/otp.h
index f6d3a56acf1e..6b6d31cf9569 100644
--- a/drivers/staging/brcm80211/brcmsmac/otp.h
+++ b/drivers/staging/brcm80211/brcmsmac/otp.h
@@ -24,24 +24,13 @@
#define OTP_SW_RGN 2
#define OTP_CI_RGN 4
#define OTP_FUSE_RGN 8
-#define OTP_ALL_RGN 0xf /* From h/w region to end of OTP including checksum */
+/* From h/w region to end of OTP including checksum */
+#define OTP_ALL_RGN 0xf
/* OTP Size */
#define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */
-/* Fixed size subregions sizes in words */
-#define OTPGU_CI_SZ 2
-
-/* OTP usage */
-#define OTP4325_FM_DISABLED_OFFSET 188
-
-/* Exported functions */
-extern int otp_status(void *oh);
-extern int otp_size(void *oh);
-extern u16 otp_read_bit(void *oh, uint offset);
-extern void *otp_init(struct si_pub *sih);
extern int otp_read_region(struct si_pub *sih, int region, u16 *data,
uint *wlen);
-extern int otp_nvread(void *oh, char *data, uint *len);
#endif /* _BRCM_OTP_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c
index 17012fbe9c97..a3149254cbcd 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c
@@ -13,8 +13,9 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-
+#include <linux/kernel.h>
#include <linux/delay.h>
+#include <linux/bitops.h>
#include <brcm_hw_ids.h>
#include <chipcommon.h>
@@ -27,14 +28,32 @@
#include "phy_lcn.h"
#include "phyreg_n.h"
-u32 phyhal_msg_level = PHYHAL_ERROR;
+#define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || \
+ (radioid == BCM2056_ID) || \
+ (radioid == BCM2057_ID))
+
+#define VALID_LCN_RADIO(radioid) (radioid == BCM2064_ID)
+
+#define VALID_RADIO(pi, radioid) ( \
+ (ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
+ (ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
+
+/* basic mux operation - can be optimized on several architectures */
+#define MUX(pred, true, false) ((pred) ? (true) : (false))
+
+/* modulo inc/dec - assumes x E [0, bound - 1] */
+#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
+
+/* modulo inc/dec, bound = 2^k */
+#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
+#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
struct chan_info_basic {
u16 chan;
u16 freq;
};
-static struct chan_info_basic chan_info_all[] = {
+static const struct chan_info_basic chan_info_all[] = {
{1, 2412},
{2, 2417},
{3, 2422},
@@ -93,20 +112,6 @@ static struct chan_info_basic chan_info_all[] = {
{216, 50800}
};
-u16 ltrn_list[PHY_LTRN_LIST_LEN] = {
- 0x18f9, 0x0d01, 0x00e4, 0xdef4, 0x06f1, 0x0ffc,
- 0xfa27, 0x1dff, 0x10f0, 0x0918, 0xf20a, 0xe010,
- 0x1417, 0x1104, 0xf114, 0xf2fa, 0xf7db, 0xe2fc,
- 0xe1fb, 0x13ee, 0xff0d, 0xe91c, 0x171a, 0x0318,
- 0xda00, 0x03e8, 0x17e6, 0xe9e4, 0xfff3, 0x1312,
- 0xe105, 0xe204, 0xf725, 0xf206, 0xf1ec, 0x11fc,
- 0x14e9, 0xe0f0, 0xf2f6, 0x09e8, 0x1010, 0x1d01,
- 0xfad9, 0x0f04, 0x060f, 0xde0c, 0x001c, 0x0dff,
- 0x1807, 0xf61a, 0xe40e, 0x0f16, 0x05f9, 0x18ec,
- 0x0a1b, 0xff1e, 0x2600, 0xffe2, 0x0ae5, 0x1814,
- 0x0507, 0x0fea, 0xe4f2, 0xf6e6
-};
-
const u8 ofdm_rate_lookup[] = {
BRCM_RATE_48M,
@@ -119,66 +124,7 @@ const u8 ofdm_rate_lookup[] = {
BRCM_RATE_9M
};
-#define PHY_WREG_LIMIT 24
-
-static void wlc_set_phy_uninitted(struct brcms_phy *pi);
-static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi);
-static void wlc_phy_timercb_phycal(void *arg);
-
-static bool wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr,
- s8 *pwr_ant);
-
-static void wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi,
- uint delay);
-
-static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm);
-static void wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason,
- u8 ch);
-
-static void wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi,
- struct txpwr_limits *tp, chanspec_t);
-static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi);
-
-static s8 wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan,
- u32 band, u8 rate);
-static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band);
-static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi);
-static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi);
-
-char *phy_getvar(struct brcms_phy *pi, const char *name)
-{
- char *vars = pi->vars;
- char *s;
- int len;
-
- if (!name)
- return NULL;
-
- len = strlen(name);
- if (len == 0)
- return NULL;
-
- for (s = vars; s && *s;) {
- if ((memcmp(s, name, len) == 0) && (s[len] == '='))
- return &s[len + 1];
-
- while (*s++)
- ;
- }
-
- return NULL;
-}
-
-int phy_getintvar(struct brcms_phy *pi, const char *name)
-{
- char *val;
-
- val = PHY_GETVAR(pi, name);
- if (val == NULL)
- return 0;
-
- return simple_strtoul(val, NULL, 0);
-}
+#define PHY_WREG_LIMIT 24
void wlc_phyreg_enter(struct brcms_phy_pub *pih)
{
@@ -203,7 +149,7 @@ void wlc_radioreg_enter(struct brcms_phy_pub *pih)
void wlc_radioreg_exit(struct brcms_phy_pub *pih)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
- volatile u16 dummy;
+ u16 dummy;
dummy = R_REG(&pi->regs->phyversion);
pi->phy_wreg = 0;
@@ -217,12 +163,10 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
if ((addr == RADIO_IDCODE))
return 0xffff;
- if (NORADIO_ENAB(pi->pubpi))
- return NORADIO_IDCODE & 0xffff;
-
switch (pi->pubpi.phy_type) {
case PHY_TYPE_N:
- CASECHECK(PHYTYPE, PHY_TYPE_N);
+ if (!CONF_HAS(PHYTYPE, PHY_TYPE_N))
+ break;
if (NREV_GE(pi->pubpi.phy_rev, 7))
addr |= RADIO_2057_READ_OFF;
else
@@ -230,7 +174,8 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
break;
case PHY_TYPE_LCN:
- CASECHECK(PHYTYPE, PHY_TYPE_LCN);
+ if (!CONF_HAS(PHYTYPE, PHY_TYPE_LCN))
+ break;
addr |= RADIO_2064_READ_OFF;
break;
@@ -262,9 +207,6 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
if ((D11REV_GE(pi->sh->corerev, 24)) ||
(D11REV_IS(pi->sh->corerev, 22)
&& (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
@@ -276,11 +218,9 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
W_REG(&pi->regs->phy4wdatalo, val);
}
- if (pi->sh->bustype == PCI_BUS) {
- if (++pi->phy_wreg >= pi->phy_wreg_limit) {
- (void)R_REG(&pi->regs->maccontrol);
- pi->phy_wreg = 0;
- }
+ if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+ (void)R_REG(&pi->regs->maccontrol);
+ pi->phy_wreg = 0;
}
}
@@ -288,9 +228,6 @@ static u32 read_radio_id(struct brcms_phy *pi)
{
u32 id;
- if (NORADIO_ENAB(pi->pubpi))
- return NORADIO_IDCODE;
-
if (D11REV_GE(pi->sh->corerev, 24)) {
u32 b0, b1, b2;
@@ -316,9 +253,6 @@ void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
u16 rval;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
rval = read_radio_reg(pi, addr);
write_radio_reg(pi, addr, (rval & val));
}
@@ -327,9 +261,6 @@ void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
u16 rval;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
rval = read_radio_reg(pi, addr);
write_radio_reg(pi, addr, (rval | val));
}
@@ -338,9 +269,6 @@ void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask)
{
u16 rval;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
rval = read_radio_reg(pi, addr);
write_radio_reg(pi, addr, (rval ^ mask));
}
@@ -349,9 +277,6 @@ void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
{
u16 rval;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
rval = read_radio_reg(pi, addr);
write_radio_reg(pi, addr, (rval & ~mask) | (val & mask));
}
@@ -363,7 +288,7 @@ void write_phy_channel_reg(struct brcms_phy *pi, uint val)
u16 read_phy_reg(struct brcms_phy *pi, u16 addr)
{
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
regs = pi->regs;
@@ -375,30 +300,27 @@ u16 read_phy_reg(struct brcms_phy *pi, u16 addr)
void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
regs = pi->regs;
-#ifdef __mips__
+#ifdef CONFIG_BCM47XX
W_REG_FLUSH(&regs->phyregaddr, addr);
W_REG(&regs->phyregdata, val);
if (addr == 0x72)
(void)R_REG(&regs->phyregdata);
#else
- W_REG((u32 *)(&regs->phyregaddr),
- addr | (val << 16));
- if (pi->sh->bustype == PCI_BUS) {
- if (++pi->phy_wreg >= pi->phy_wreg_limit) {
- pi->phy_wreg = 0;
- (void)R_REG(&regs->phyversion);
- }
+ W_REG((u32 __iomem *)(&regs->phyregaddr), addr | (val << 16));
+ if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+ pi->phy_wreg = 0;
+ (void)R_REG(&regs->phyversion);
}
#endif
}
void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
regs = pi->regs;
@@ -410,7 +332,7 @@ void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
regs = pi->regs;
@@ -422,7 +344,7 @@ void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
{
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
regs = pi->regs;
@@ -464,9 +386,8 @@ static void wlc_set_phy_uninitted(struct brcms_phy *pi)
}
pi->radiopwr = 0xffff;
for (i = 0; i < STATIC_NUM_RF; i++) {
- for (j = 0; j < STATIC_NUM_BB; j++) {
+ for (j = 0; j < STATIC_NUM_BB; j++)
pi->stats_11b_txpower[i][j] = -1;
- }
}
}
@@ -475,9 +396,8 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
struct shared_phy *sh;
sh = kzalloc(sizeof(struct shared_phy), GFP_ATOMIC);
- if (sh == NULL) {
+ if (sh == NULL)
return NULL;
- }
sh->sih = shp->sih;
sh->physhim = shp->physhim;
@@ -495,7 +415,6 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
sh->boardvendor = shp->boardvendor;
sh->boardflags = shp->boardflags;
sh->boardflags2 = shp->boardflags2;
- sh->bustype = shp->bustype;
sh->buscorerev = shp->buscorerev;
sh->fast_timer = PHY_SW_TIMER_FAST;
@@ -507,9 +426,40 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
return sh;
}
+static void wlc_phy_timercb_phycal(struct brcms_phy *pi)
+{
+ uint delay = 5;
+
+ if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+ if (!pi->sh->up) {
+ wlc_phy_cal_perical_mphase_reset(pi);
+ return;
+ }
+
+ if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
+
+ delay = 1000;
+ wlc_phy_cal_perical_mphase_restart(pi);
+ } else
+ wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
+ wlapi_add_timer(pi->phycal_timer, delay, 0);
+ return;
+ }
+
+}
+
+static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi)
+{
+ u32 ver;
+
+ ver = read_radio_id(pi);
+
+ return ver;
+}
+
struct brcms_phy_pub *
-wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
- char *vars, struct wiphy *wiphy)
+wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
+ int bandtype, struct wiphy *wiphy)
{
struct brcms_phy *pi;
u32 sflags = 0;
@@ -522,42 +472,35 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
else
sflags = ai_core_sflags(sh->sih, 0, 0);
- if (BAND_5G(bandtype)) {
- if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) {
+ if (bandtype == BRCM_BAND_5G) {
+ if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0)
return NULL;
- }
}
pi = sh->phy_head;
if ((sflags & SISF_DB_PHY) && pi) {
-
wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
pi->refcnt++;
return &pi->pubpi_ro;
}
pi = kzalloc(sizeof(struct brcms_phy), GFP_ATOMIC);
- if (pi == NULL) {
+ if (pi == NULL)
return NULL;
- }
pi->wiphy = wiphy;
- pi->regs = (d11regs_t *) regs;
+ pi->regs = regs;
pi->sh = sh;
pi->phy_init_por = true;
pi->phy_wreg_limit = PHY_WREG_LIMIT;
- pi->vars = vars;
-
pi->txpwr_percent = 100;
pi->do_initcal = true;
pi->phycal_tempdelta = 0;
- if (BAND_2G(bandtype) && (sflags & SISF_2G_PHY)) {
-
+ if (bandtype == BRCM_BAND_2G && (sflags & SISF_2G_PHY))
pi->pubpi.coreflags = SICF_GMODE;
- }
wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
phyversion = R_REG(&pi->regs->phyversion);
@@ -572,28 +515,26 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
- if (!VALID_PHYTYPE(pi->pubpi.phy_type)) {
+ if (!pi->pubpi.phy_type == PHY_TYPE_N &&
+ !pi->pubpi.phy_type == PHY_TYPE_LCN)
goto err;
- }
- if (BAND_5G(bandtype)) {
- if (!ISNPHY(pi)) {
- goto err;
- }
- } else {
- if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
+
+ if (bandtype == BRCM_BAND_5G) {
+ if (!ISNPHY(pi))
goto err;
- }
+ } else if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
+ goto err;
}
wlc_phy_anacore((struct brcms_phy_pub *) pi, ON);
idcode = wlc_phy_get_radio_ver(pi);
pi->pubpi.radioid =
- (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
+ (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
pi->pubpi.radiorev =
- (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
+ (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
pi->pubpi.radiover =
- (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
+ (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
if (!VALID_RADIO(pi, pi->pubpi.radioid))
goto err;
@@ -602,8 +543,8 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
wlc_set_phy_uninitted(pi);
pi->bw = WL_CHANSPEC_BW_20;
- pi->radio_chanspec =
- BAND_2G(bandtype) ? CH20MHZ_CHSPEC(1) : CH20MHZ_CHSPEC(36);
+ pi->radio_chanspec = (bandtype == BRCM_BAND_2G) ?
+ ch20mhz_chspec(1) : ch20mhz_chspec(36);
pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
pi->rxiq_antsel = ANT_RX_DIV_DEF;
@@ -625,7 +566,7 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
pi->phy_txcore_enable_temp =
- PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
+ PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
pi->phy_tempsense_offset = 0;
pi->phy_txcore_heatedup = false;
@@ -648,11 +589,10 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
if (ISNPHY(pi)) {
pi->phycal_timer = wlapi_init_timer(pi->sh->physhim,
- wlc_phy_timercb_phycal,
- pi, "phycal");
- if (!pi->phycal_timer) {
+ wlc_phy_timercb_phycal,
+ pi, "phycal");
+ if (!pi->phycal_timer)
goto err;
- }
if (!wlc_phy_attach_nphy(pi))
goto err;
@@ -661,21 +601,17 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
if (!wlc_phy_attach_lcnphy(pi))
goto err;
- } else {
-
}
pi->refcnt++;
pi->next = pi->sh->phy_head;
sh->phy_head = pi;
- pi->vars = (char *)&pi->vars;
-
memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(struct brcms_phy_pub));
return &pi->pubpi_ro;
- err:
+err:
kfree(pi);
return NULL;
}
@@ -685,12 +621,11 @@ void wlc_phy_detach(struct brcms_phy_pub *pih)
struct brcms_phy *pi = (struct brcms_phy *) pih;
if (pih) {
- if (--pi->refcnt) {
+ if (--pi->refcnt)
return;
- }
if (pi->phycal_timer) {
- wlapi_free_timer(pi->sh->physhim, pi->phycal_timer);
+ wlapi_free_timer(pi->phycal_timer);
pi->phycal_timer = NULL;
}
@@ -700,7 +635,7 @@ void wlc_phy_detach(struct brcms_phy_pub *pih)
pi->sh->phy_head->next = NULL;
if (pi->pi_fptr.detach)
- (pi->pi_fptr.detach) (pi);
+ (pi->pi_fptr.detach)(pi);
kfree(pi);
}
@@ -731,29 +666,6 @@ u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih)
return pi->pubpi.coreflags;
}
-static void wlc_phy_timercb_phycal(void *arg)
-{
- struct brcms_phy *pi = (struct brcms_phy *) arg;
- uint delay = 5;
-
- if (PHY_PERICAL_MPHASE_PENDING(pi)) {
- if (!pi->sh->up) {
- wlc_phy_cal_perical_mphase_reset(pi);
- return;
- }
-
- if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
-
- delay = 1000;
- wlc_phy_cal_perical_mphase_restart(pi);
- } else
- wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
- wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
- return;
- }
-
-}
-
void wlc_phy_anacore(struct brcms_phy_pub *pih, bool on)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
@@ -862,10 +774,10 @@ void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate)
pi->sh->up = newstate;
}
-void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec)
+void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec)
{
u32 mc;
- initfn_t phy_init = NULL;
+ void (*phy_init)(struct brcms_phy *) = NULL;
struct brcms_phy *pi = (struct brcms_phy *) pih;
if (pi->init_in_progress)
@@ -879,9 +791,8 @@ void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec)
if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init"))
return;
- if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
+ if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN))
pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
- }
if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA),
"HW error SISF_FCLKA\n"))
@@ -889,9 +800,8 @@ void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec)
phy_init = pi->pi_fptr.init;
- if (phy_init == NULL) {
+ if (phy_init == NULL)
return;
- }
wlc_phy_anacore(pih, ON);
@@ -903,7 +813,7 @@ void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec)
wlc_phy_switch_radio((struct brcms_phy_pub *) pi, ON);
- (*phy_init) (pi);
+ (*phy_init)(pi);
pi->phy_init_por = false;
@@ -921,7 +831,7 @@ void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec)
void wlc_phy_cal_init(struct brcms_phy_pub *pih)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
- initfn_t cal_init = NULL;
+ void (*cal_init)(struct brcms_phy *) = NULL;
if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0,
"HW error: MAC enabled during phy cal\n"))
@@ -930,7 +840,7 @@ void wlc_phy_cal_init(struct brcms_phy_pub *pih)
if (!pi->initialized) {
cal_init = pi->pi_fptr.calinit;
if (cal_init)
- (*cal_init) (pi);
+ (*cal_init)(pi);
pi->initialized = true;
}
@@ -942,7 +852,7 @@ int wlc_phy_down(struct brcms_phy_pub *pih)
int callbacks = 0;
if (pi->phycal_timer
- && !wlapi_del_timer(pi->sh->physhim, pi->phycal_timer))
+ && !wlapi_del_timer(pi->phycal_timer))
callbacks++;
pi->nphy_iqcal_chanspec_2G = 0;
@@ -951,15 +861,6 @@ int wlc_phy_down(struct brcms_phy_pub *pih)
return callbacks;
}
-static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi)
-{
- u32 ver;
-
- ver = read_radio_id(pi);
-
- return ver;
-}
-
void
wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
@@ -990,11 +891,9 @@ void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val)
}
if (width == 32) {
-
write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16));
write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
} else {
-
write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
}
}
@@ -1025,15 +924,12 @@ wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
}
if (tbl_width == 32) {
-
write_phy_reg(pi, tblDataHi,
(u16) (ptbl_32b[idx] >> 16));
write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]);
} else if (tbl_width == 16) {
-
write_phy_reg(pi, tblDataLo, ptbl_16b[idx]);
} else {
-
write_phy_reg(pi, tblDataLo, ptbl_8b[idx]);
}
}
@@ -1064,14 +960,11 @@ wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
}
if (tbl_width == 32) {
-
ptbl_32b[idx] = read_phy_reg(pi, tblDataLo);
ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16);
} else if (tbl_width == 16) {
-
ptbl_16b[idx] = read_phy_reg(pi, tblDataLo);
} else {
-
ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo);
}
}
@@ -1084,10 +977,9 @@ wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
uint i = 0;
do {
- if (radioregs[i].do_init) {
+ if (radioregs[i].do_init)
write_radio_reg(pi, radioregs[i].address,
(u16) radioregs[i].init);
- }
i++;
} while (radioregs[i].address != 0xffff);
@@ -1096,7 +988,8 @@ wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
}
uint
-wlc_phy_init_radio_regs(struct brcms_phy *pi, struct radio_regs *radioregs,
+wlc_phy_init_radio_regs(struct brcms_phy *pi,
+ const struct radio_regs *radioregs,
u16 core_offset)
{
uint i = 0;
@@ -1131,8 +1024,8 @@ wlc_phy_init_radio_regs(struct brcms_phy *pi, struct radio_regs *radioregs,
void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
{
-#define DUMMY_PKT_LEN 20
- d11regs_t *regs = pi->regs;
+#define DUMMY_PKT_LEN 20
+ struct d11regs __iomem *regs = pi->regs;
int i, count;
u8 ofdmpkt[DUMMY_PKT_LEN] = {
0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
@@ -1156,9 +1049,8 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
W_REG(&regs->wepctl, 0);
W_REG(&regs->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
- if (ISNPHY(pi) || ISLCNPHY(pi)) {
+ if (ISNPHY(pi) || ISLCNPHY(pi))
W_REG(&regs->txe_phyctl1, 0x1A02);
- }
W_REG(&regs->txe_wm_0, 0);
W_REG(&regs->txe_wm_1, 0);
@@ -1185,16 +1077,14 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
i = 0;
count = ofdm ? 30 : 250;
while ((i++ < count)
- && (R_REG(&regs->txe_status) & (1 << 7))) {
+ && (R_REG(&regs->txe_status) & (1 << 7)))
udelay(10);
- }
i = 0;
while ((i++ < 10)
- && ((R_REG(&regs->txe_status) & (1 << 10)) == 0)) {
+ && ((R_REG(&regs->txe_status) & (1 << 10)) == 0))
udelay(10);
- }
i = 0;
@@ -1207,28 +1097,26 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
}
}
-void wlc_phy_hold_upd(struct brcms_phy_pub *pih, mbool id, bool set)
+void wlc_phy_hold_upd(struct brcms_phy_pub *pih, u32 id, bool set)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
- if (set) {
+ if (set)
mboolset(pi->measure_hold, id);
- } else {
+ else
mboolclr(pi->measure_hold, id);
- }
return;
}
-void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, mbool flags)
+void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, u32 flags)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
- if (mute) {
+ if (mute)
mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE);
- } else {
+ else
mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE);
- }
if (!mute && (flags & PHY_MUTE_FOR_PREISM))
pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer;
@@ -1257,19 +1145,10 @@ static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi)
void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
-
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
- {
- uint mc;
-
- mc = R_REG(&pi->regs->maccontrol);
- }
+ (void)R_REG(&pi->regs->maccontrol);
if (ISNPHY(pi)) {
wlc_phy_switch_radio_nphy(pi, on);
-
} else if (ISLCNPHY(pi)) {
if (on) {
and_phy_reg(pi, 0x44c,
@@ -1311,26 +1190,25 @@ void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw)
pi->bw = bw;
}
-void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, chanspec_t newch)
+void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
pi->radio_chanspec = newch;
}
-chanspec_t wlc_phy_chanspec_get(struct brcms_phy_pub *ppi)
+u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
return pi->radio_chanspec;
}
-void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, chanspec_t chanspec)
+void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
u16 m_cur_channel;
- chansetfn_t chanspec_set = NULL;
-
+ void (*chanspec_set)(struct brcms_phy *, u16) = NULL;
m_cur_channel = CHSPEC_CHANNEL(chanspec);
if (CHSPEC_IS5G(chanspec))
m_cur_channel |= D11_CURCHANNEL_5G;
@@ -1340,7 +1218,7 @@ void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, chanspec_t chanspec)
chanspec_set = pi->pi_fptr.chanset;
if (chanspec_set)
- (*chanspec_set) (pi, chanspec);
+ (*chanspec_set)(pi, chanspec);
}
@@ -1360,17 +1238,16 @@ int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq)
return range;
}
-int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, chanspec_t chanspec)
+int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, u16 chanspec)
{
int range = -1;
uint channel = CHSPEC_CHANNEL(chanspec);
uint freq = wlc_phy_channel2freq(channel);
- if (ISNPHY(pi)) {
+ if (ISNPHY(pi))
range = wlc_phy_get_chan_freq_range_nphy(pi, channel);
- } else if (ISLCNPHY(pi)) {
+ else if (ISLCNPHY(pi))
range = wlc_phy_chanspec_freq2bandrange_lpssn(freq);
- }
return range;
}
@@ -1396,13 +1273,13 @@ int wlc_phy_channel2freq(uint channel)
void
wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
- chanvec_t *channels)
+ struct brcms_chanvec *channels)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
uint i;
uint channel;
- memset(channels, 0, sizeof(chanvec_t));
+ memset(channels, 0, sizeof(struct brcms_chanvec));
for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
channel = chan_info_all[i].chan;
@@ -1417,17 +1294,17 @@ wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
}
}
-chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
+u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
uint i;
uint channel;
- chanspec_t chspec;
+ u16 chspec;
for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
channel = chan_info_all[i].chan;
- if (ISNPHY(pi) && IS40MHZ(pi)) {
+ if (ISNPHY(pi) && pi->bw == WL_CHANSPEC_BW_40) {
uint j;
for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) {
@@ -1439,16 +1316,15 @@ chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
if (j == ARRAY_SIZE(chan_info_all))
continue;
- channel = UPPER_20_SB(channel);
- chspec =
- channel | WL_CHANSPEC_BW_40 |
- WL_CHANSPEC_CTL_SB_LOWER;
+ channel = upper_20_sb(channel);
+ chspec = channel | WL_CHANSPEC_BW_40 |
+ WL_CHANSPEC_CTL_SB_LOWER;
if (band == BRCM_BAND_2G)
chspec |= WL_CHANSPEC_BAND_2G;
else
chspec |= WL_CHANSPEC_BAND_5G;
} else
- chspec = CH20MHZ_CHSPEC(channel);
+ chspec = ch20mhz_chspec(channel);
if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
&& (channel <= LAST_REF5_CHANNUM))
@@ -1459,7 +1335,7 @@ chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
return chspec;
}
- return (chanspec_t) INVCHANSPEC;
+ return (u16) INVCHANSPEC;
}
int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override)
@@ -1528,7 +1404,7 @@ int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override)
int i;
if (qdbm > 127)
- return 5;
+ return -EINVAL;
for (i = 0; i < TXP_NUM_RATES; i++)
pi->tx_user_target[i] = (u8) qdbm;
@@ -1539,10 +1415,8 @@ int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override)
if (!SCAN_INPROG_PHY(pi)) {
bool suspend;
- suspend =
- (0 ==
- (R_REG(&pi->regs->maccontrol) &
- MCTL_EN_MAC));
+ suspend = (0 == (R_REG(&pi->regs->maccontrol) &
+ MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
@@ -1584,9 +1458,8 @@ wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint channel, u8 *min_pwr,
txp_rate_idx = TXP_FIRST_OFDM;
for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
- if (channel == chan_info_all[i].chan) {
+ if (channel == chan_info_all[i].chan)
break;
- }
}
if (pi->hwtxpwr) {
@@ -1620,7 +1493,8 @@ wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan,
pactrl = 0;
max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES :
- ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1);
+ ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 +
+ 1) : (TXP_LAST_OFDM + 1);
for (rate = 0; rate < max_num_rate; rate++) {
@@ -1659,6 +1533,46 @@ u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi)
return pi->tx_power_max;
}
+static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi)
+{
+ if (ISLCNPHY(pi))
+ return wlc_lcnphy_vbatsense(pi, 0);
+ else
+ return 0;
+}
+
+static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi)
+{
+ if (ISLCNPHY(pi))
+ return wlc_lcnphy_tempsense_degree(pi, 0);
+ else
+ return 0;
+}
+
+static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band)
+{
+ u8 i;
+ s8 temp, vbat;
+
+ for (i = 0; i < TXP_NUM_RATES; i++)
+ pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
+
+ vbat = wlc_phy_env_measure_vbat(pi);
+ temp = wlc_phy_env_measure_temperature(pi);
+
+}
+
+static s8
+wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
+ u8 rate)
+{
+ s8 offset = 0;
+
+ if (!pi->user_txpwr_at_rfport)
+ return offset;
+ return offset;
+}
+
void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
{
u8 maxtxpwr, mintxpwr, rate, pactrl;
@@ -1669,17 +1583,17 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
u8 tx_pwr_max_rate_ind = 0;
u8 max_num_rate;
u8 start_rate = 0;
- chanspec_t chspec;
+ u16 chspec;
u32 band = CHSPEC2BAND(pi->radio_chanspec);
- initfn_t txpwr_recalc_fn = NULL;
+ void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL;
chspec = pi->radio_chanspec;
if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE)
target_chan = CHSPEC_CHANNEL(chspec);
else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
- target_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec));
+ target_chan = upper_20_sb(CHSPEC_CHANNEL(chspec));
else
- target_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec));
+ target_chan = lower_20_sb(CHSPEC_CHANNEL(chspec));
pactrl = 0;
if (ISLCNPHY(pi)) {
@@ -1690,8 +1604,8 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
for (i = TXP_FIRST_SISO_MCS_20;
i <= TXP_LAST_SISO_MCS_20; i++) {
pi->tx_srom_max_rate_2g[i - 8] =
- pi->tx_srom_max_2g -
- ((offset_mcs & 0xf) * 2);
+ pi->tx_srom_max_2g -
+ ((offset_mcs & 0xf) * 2);
offset_mcs >>= 4;
}
} else {
@@ -1699,19 +1613,16 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
for (i = TXP_FIRST_SISO_MCS_20;
i <= TXP_LAST_SISO_MCS_20; i++) {
pi->tx_srom_max_rate_2g[i - 8] =
- pi->tx_srom_max_2g -
- ((offset_mcs & 0xf) * 2);
+ pi->tx_srom_max_2g -
+ ((offset_mcs & 0xf) * 2);
offset_mcs >>= 4;
}
}
}
-#if WL11N
+
max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
((ISLCNPHY(pi)) ?
(TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1)));
-#else
- max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : (TXP_LAST_OFDM + 1));
-#endif
wlc_phy_upd_env_txpwr_rate_limits(pi, band);
@@ -1719,35 +1630,32 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
tx_pwr_target[rate] = pi->tx_user_target[rate];
- if (pi->user_txpwr_at_rfport) {
+ if (pi->user_txpwr_at_rfport)
tx_pwr_target[rate] +=
- wlc_user_txpwr_antport_to_rfport(pi, target_chan,
- band, rate);
- }
+ wlc_user_txpwr_antport_to_rfport(pi,
+ target_chan,
+ band,
+ rate);
- {
+ wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi,
+ target_chan,
+ &mintxpwr, &maxtxpwr, rate);
- wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi,
- target_chan,
- &mintxpwr, &maxtxpwr, rate);
+ maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
- maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
-
- maxtxpwr =
- (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
+ maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
- maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
+ maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
- maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
+ maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
- if (pi->txpwr_percent <= 100)
- maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
+ if (pi->txpwr_percent <= 100)
+ maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
- tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
- }
+ tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
tx_pwr_target[rate] =
- min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
+ min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
if (tx_pwr_target[rate] > tx_pwr_max)
tx_pwr_max_rate_ind = rate;
@@ -1764,23 +1672,22 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
pi->tx_power_target[rate] = tx_pwr_target[rate];
- if (!pi->hwpwrctrl || ISNPHY(pi)) {
+ if (!pi->hwpwrctrl || ISNPHY(pi))
pi->tx_power_offset[rate] =
- pi->tx_power_max - pi->tx_power_target[rate];
- } else {
+ pi->tx_power_max - pi->tx_power_target[rate];
+ else
pi->tx_power_offset[rate] =
- pi->tx_power_target[rate] - pi->tx_power_min;
- }
+ pi->tx_power_target[rate] - pi->tx_power_min;
}
txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc;
if (txpwr_recalc_fn)
- (*txpwr_recalc_fn) (pi);
+ (*txpwr_recalc_fn)(pi);
}
-void
+static void
wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
- chanspec_t chanspec)
+ u16 chanspec)
{
u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM];
u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL;
@@ -1815,7 +1722,7 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
txpwr_ptr1 = txpwr->mcs_40_siso;
txpwr_ptr2 = txpwr->ofdm_40_siso;
rate_start_index =
- WL_TX_POWER_OFDM40_SISO_FIRST;
+ WL_TX_POWER_OFDM40_SISO_FIRST;
break;
case 3:
@@ -1825,18 +1732,21 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
break;
}
- for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; rate2++) {
+ for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
+ rate2++) {
tmp_txpwr_limit[rate2] = 0;
tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
- txpwr_ptr1[rate2];
+ txpwr_ptr1[rate2];
}
- wlc_phy_mcs_to_ofdm_powers_nphy(tmp_txpwr_limit, 0,
- BRCMS_NUM_RATES_OFDM - 1, BRCMS_NUM_RATES_OFDM);
+ wlc_phy_mcs_to_ofdm_powers_nphy(
+ tmp_txpwr_limit, 0,
+ BRCMS_NUM_RATES_OFDM -
+ 1, BRCMS_NUM_RATES_OFDM);
for (rate1 = rate_start_index, rate2 = 0;
rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++)
pi->txpwr_limit[rate1] =
- min(txpwr_ptr2[rate2],
- tmp_txpwr_limit[rate2]);
+ min(txpwr_ptr2[rate2],
+ tmp_txpwr_limit[rate2]);
}
for (k = 0; k < 4; k++) {
@@ -1866,19 +1776,22 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST;
break;
}
- for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; rate2++) {
+ for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
+ rate2++) {
tmp_txpwr_limit[rate2] = 0;
tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
- txpwr_ptr1[rate2];
+ txpwr_ptr1[rate2];
}
- wlc_phy_ofdm_to_mcs_powers_nphy(tmp_txpwr_limit, 0,
- BRCMS_NUM_RATES_OFDM - 1, BRCMS_NUM_RATES_OFDM);
+ wlc_phy_ofdm_to_mcs_powers_nphy(
+ tmp_txpwr_limit, 0,
+ BRCMS_NUM_RATES_OFDM -
+ 1, BRCMS_NUM_RATES_OFDM);
for (rate1 = rate_start_index, rate2 = 0;
rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
rate1++, rate2++)
pi->txpwr_limit[rate1] =
- min(txpwr_ptr2[rate2],
- tmp_txpwr_limit[rate2]);
+ min(txpwr_ptr2[rate2],
+ tmp_txpwr_limit[rate2]);
}
for (k = 0; k < 2; k++) {
@@ -1922,10 +1835,10 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32;
pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] =
- min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
- pi->txpwr_limit[WL_TX_POWER_MCS_32]);
+ min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
+ pi->txpwr_limit[WL_TX_POWER_MCS_32]);
pi->txpwr_limit[WL_TX_POWER_MCS_32] =
- pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
+ pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
}
}
@@ -1975,7 +1888,7 @@ void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end)
void
wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr,
- chanspec_t chanspec)
+ u16 chanspec)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
@@ -2016,9 +1929,8 @@ void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt)
void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
{
int j;
- if (ISNPHY(pi)) {
+ if (ISNPHY(pi))
return;
- }
if (!pi->sh->clk)
return;
@@ -2040,9 +1952,9 @@ void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
const u8 ucode_ofdm_rates[] = {
0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
};
- offset = wlapi_bmac_rate_shm_offset(pi->sh->physhim,
- ucode_ofdm_rates[j -
- TXP_FIRST_OFDM]);
+ offset = wlapi_bmac_rate_shm_offset(
+ pi->sh->physhim,
+ ucode_ofdm_rates[j - TXP_FIRST_OFDM]);
wlapi_bmac_write_shm(pi->sh->physhim, offset + 6,
pi->tx_power_offset[j]);
wlapi_bmac_write_shm(pi->sh->physhim, offset + 14,
@@ -2056,11 +1968,11 @@ void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++)
pi->tx_power_offset[i] =
- (u8) roundup(pi->tx_power_offset[i], 8);
+ (u8) roundup(pi->tx_power_offset[i], 8);
wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET,
- (u16) ((pi->
- tx_power_offset[TXP_FIRST_OFDM]
- + 7) >> 3));
+ (u16)
+ ((pi->tx_power_offset[TXP_FIRST_OFDM]
+ + 7) >> 3));
}
}
@@ -2068,48 +1980,38 @@ bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
- if (ISNPHY(pi)) {
+ if (ISNPHY(pi))
return pi->nphy_txpwrctrl;
- } else {
+ else
return pi->hwpwrctrl;
- }
}
void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
- bool cur_hwpwrctrl = pi->hwpwrctrl;
bool suspend;
- if (!pi->hwpwrctrl_capable) {
+ if (!pi->hwpwrctrl_capable)
return;
- }
pi->hwpwrctrl = hwpwrctrl;
pi->nphy_txpwrctrl = hwpwrctrl;
pi->txpwrctrl = hwpwrctrl;
if (ISNPHY(pi)) {
- suspend =
- (0 ==
- (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
- if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF)
wlc_phy_txpwr_fixpower_nphy(pi);
- } else {
-
+ else
mod_phy_reg(pi, 0x1e7, (0x7f << 0),
pi->saved_txpwr_idx);
- }
if (!suspend)
wlapi_enable_mac(pi->sh->physhim);
- } else if (hwpwrctrl != cur_hwpwrctrl) {
-
- return;
}
}
@@ -2125,8 +2027,6 @@ void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi)
}
}
-static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi);
-
static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi)
{
s16 tx0_status, tx1_status;
@@ -2137,42 +2037,31 @@ static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi)
estPower1 = read_phy_reg(pi, 0x118);
estPower2 = read_phy_reg(pi, 0x119);
- if ((estPower1 & (0x1 << 8))
- == (0x1 << 8)) {
- pwr0 = (u8) (estPower1 & (0xff << 0))
- >> 0;
- } else {
+ if ((estPower1 & (0x1 << 8)) == (0x1 << 8))
+ pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0;
+ else
pwr0 = 0x80;
- }
- if ((estPower2 & (0x1 << 8))
- == (0x1 << 8)) {
- pwr1 = (u8) (estPower2 & (0xff << 0))
- >> 0;
- } else {
+ if ((estPower2 & (0x1 << 8)) == (0x1 << 8))
+ pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0;
+ else
pwr1 = 0x80;
- }
tx0_status = read_phy_reg(pi, 0x1ed);
tx1_status = read_phy_reg(pi, 0x1ee);
- if ((tx0_status & (0x1 << 15))
- == (0x1 << 15)) {
- adj_pwr0 = (u8) (tx0_status & (0xff << 0))
- >> 0;
- } else {
+ if ((tx0_status & (0x1 << 15)) == (0x1 << 15))
+ adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0;
+ else
adj_pwr0 = 0x80;
- }
- if ((tx1_status & (0x1 << 15))
- == (0x1 << 15)) {
- adj_pwr1 = (u8) (tx1_status & (0xff << 0))
- >> 0;
- } else {
+ if ((tx1_status & (0x1 << 15)) == (0x1 << 15))
+ adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0;
+ else
adj_pwr1 = 0x80;
- }
- est_pwr =
- (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | adj_pwr1);
+ est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) |
+ adj_pwr1);
+
return est_pwr;
}
@@ -2193,7 +2082,7 @@ wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power,
power->flags |= (WL_TX_POWER_F_MIMO);
if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
power->flags |=
- (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
+ (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
} else if (ISLCNPHY(pi)) {
power->rf_cores = 1;
power->flags |= (WL_TX_POWER_F_SISO);
@@ -2256,16 +2145,18 @@ wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power,
power->tx_power_max[1] = pi->tx_power_max;
power->tx_power_max_rate_ind[0] =
- pi->tx_power_max_rate_ind;
+ pi->tx_power_max_rate_ind;
power->tx_power_max_rate_ind[1] =
- pi->tx_power_max_rate_ind;
+ pi->tx_power_max_rate_ind;
if (wlc_phy_tpc_isenabled_lcnphy(pi))
power->flags |=
- (WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
+ (WL_TX_POWER_F_HW |
+ WL_TX_POWER_F_ENABLED);
else
power->flags &=
- ~(WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
+ ~(WL_TX_POWER_F_HW |
+ WL_TX_POWER_F_ENABLED);
wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0],
(s8 *) &power->est_Pout_cck);
@@ -2304,16 +2195,13 @@ void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val)
BRCM_BAND_ALL);
}
- if (ISNPHY(pi)) {
-
+ if (ISNPHY(pi))
return;
- }
if (!pi->sh->clk)
return;
- suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
@@ -2357,10 +2245,127 @@ wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant)
pwr_ant[i] = cmplx_pwr_dbm[i];
}
pi->nphy_noise_index =
- MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+ MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
return true;
}
+static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm)
+{
+ if (!pi->phynoise_state)
+ return;
+
+ if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
+ if (pi->phynoise_chan_watchdog == channel) {
+ pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
+ noise_dbm;
+ pi->sh->phy_noise_index =
+ MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
+ }
+ pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
+ }
+
+ if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL)
+ pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
+
+}
+
+static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi)
+{
+ u32 cmplx_pwr[PHY_CORE_MAX];
+ s8 noise_dbm_ant[PHY_CORE_MAX];
+ u16 lo, hi;
+ u32 cmplx_pwr_tot = 0;
+ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+ u8 idx, core;
+
+ memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
+ memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
+
+ for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2,
+ core++) {
+ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
+ hi = wlapi_bmac_read_shm(pi->sh->physhim,
+ M_PWRIND_MAP(idx + 1));
+ cmplx_pwr[core] = (hi << 16) + lo;
+ cmplx_pwr_tot += cmplx_pwr[core];
+ if (cmplx_pwr[core] == 0)
+ noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
+ else
+ cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
+ }
+
+ if (cmplx_pwr_tot != 0)
+ wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
+
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+ pi->nphy_noise_win[core][pi->nphy_noise_index] =
+ noise_dbm_ant[core];
+
+ if (noise_dbm_ant[core] > noise_dbm)
+ noise_dbm = noise_dbm_ant[core];
+ }
+ pi->nphy_noise_index =
+ MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+
+ return noise_dbm;
+
+}
+
+void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih)
+{
+ struct brcms_phy *pi = (struct brcms_phy *) pih;
+ u16 jssi_aux;
+ u8 channel = 0;
+ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+
+ if (ISLCNPHY(pi)) {
+ u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
+ u16 lo, hi;
+ s32 pwr_offset_dB, gain_dB;
+ u16 status_0, status_1;
+
+ jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+ channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
+ hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
+ cmplx_pwr0 = (hi << 16) + lo;
+
+ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
+ hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
+ cmplx_pwr1 = (hi << 16) + lo;
+ cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
+
+ status_0 = 0x44;
+ status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
+ if ((cmplx_pwr > 0 && cmplx_pwr < 500)
+ && ((status_1 & 0xc000) == 0x4000)) {
+
+ wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
+ pi->pubpi.phy_corenum);
+ pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
+ if (pwr_offset_dB > 127)
+ pwr_offset_dB -= 256;
+
+ noise_dbm += (s8) (pwr_offset_dB - 30);
+
+ gain_dB = (status_0 & 0x1ff);
+ noise_dbm -= (s8) (gain_dB);
+ } else {
+ noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
+ }
+ } else if (ISNPHY(pi)) {
+
+ jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+ channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+ noise_dbm = wlc_phy_noise_read_shmem(pi);
+ }
+
+ wlc_phy_noise_cb(pi, channel, noise_dbm);
+
+}
+
static void
wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
{
@@ -2369,20 +2374,13 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
bool sampling_in_progress = (pi->phynoise_state != 0);
bool wait_for_intr = true;
- if (NORADIO_ENAB(pi->pubpi)) {
- return;
- }
-
switch (reason) {
case PHY_NOISE_SAMPLE_MON:
-
pi->phynoise_chan_watchdog = ch;
pi->phynoise_state |= PHY_NOISE_STATE_MON;
-
break;
case PHY_NOISE_SAMPLE_EXTERNAL:
-
pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL;
break;
@@ -2398,15 +2396,13 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
if (pi->phy_fixed_noise) {
if (ISNPHY(pi)) {
pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] =
- PHY_NOISE_FIXED_VAL_NPHY;
+ PHY_NOISE_FIXED_VAL_NPHY;
pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] =
- PHY_NOISE_FIXED_VAL_NPHY;
+ PHY_NOISE_FIXED_VAL_NPHY;
pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
PHY_NOISE_WINDOW_SZ);
-
noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
} else {
-
noise_dbm = PHY_NOISE_FIXED_VAL;
}
@@ -2469,15 +2465,14 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
wlapi_enable_mac(pi->sh->physhim);
for (i = 0; i < pi->pubpi.phy_corenum; i++)
- cmplx_pwr[i] =
- (est[i].i_pwr +
- est[i].q_pwr) >> log_num_samps;
+ cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >>
+ log_num_samps;
wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
for (i = 0; i < pi->pubpi.phy_corenum; i++) {
pi->nphy_noise_win[i][pi->nphy_noise_index] =
- noise_dbm_ant[i];
+ noise_dbm_ant[i];
if (noise_dbm_ant[i] > noise_dbm)
noise_dbm = noise_dbm_ant[i];
@@ -2489,7 +2484,7 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
}
}
- done:
+done:
if (!wait_for_intr)
wlc_phy_noise_cb(pi, ch, noise_dbm);
@@ -2505,124 +2500,7 @@ void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *pih)
wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel);
}
-static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm)
-{
- if (!pi->phynoise_state)
- return;
-
- if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
- if (pi->phynoise_chan_watchdog == channel) {
- pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
- noise_dbm;
- pi->sh->phy_noise_index =
- MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
- }
- pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
- }
-
- if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) {
- pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
- }
-
-}
-
-static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi)
-{
- u32 cmplx_pwr[PHY_CORE_MAX];
- s8 noise_dbm_ant[PHY_CORE_MAX];
- u16 lo, hi;
- u32 cmplx_pwr_tot = 0;
- s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
- u8 idx, core;
-
- memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
- memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
-
- for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, core++) {
- lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
- hi = wlapi_bmac_read_shm(pi->sh->physhim,
- M_PWRIND_MAP(idx + 1));
- cmplx_pwr[core] = (hi << 16) + lo;
- cmplx_pwr_tot += cmplx_pwr[core];
- if (cmplx_pwr[core] == 0) {
- noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
- } else
- cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
- }
-
- if (cmplx_pwr_tot != 0)
- wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
-
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- pi->nphy_noise_win[core][pi->nphy_noise_index] =
- noise_dbm_ant[core];
-
- if (noise_dbm_ant[core] > noise_dbm)
- noise_dbm = noise_dbm_ant[core];
- }
- pi->nphy_noise_index =
- MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
-
- return noise_dbm;
-
-}
-
-void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih)
-{
- struct brcms_phy *pi = (struct brcms_phy *) pih;
- u16 jssi_aux;
- u8 channel = 0;
- s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
-
- if (ISLCNPHY(pi)) {
- u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
- u16 lo, hi;
- s32 pwr_offset_dB, gain_dB;
- u16 status_0, status_1;
-
- jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
- channel = jssi_aux & D11_CURCHANNEL_MAX;
-
- lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
- hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
- cmplx_pwr0 = (hi << 16) + lo;
-
- lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
- hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
- cmplx_pwr1 = (hi << 16) + lo;
- cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
-
- status_0 = 0x44;
- status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
- if ((cmplx_pwr > 0 && cmplx_pwr < 500)
- && ((status_1 & 0xc000) == 0x4000)) {
-
- wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
- pi->pubpi.phy_corenum);
- pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
- if (pwr_offset_dB > 127)
- pwr_offset_dB -= 256;
-
- noise_dbm += (s8) (pwr_offset_dB - 30);
-
- gain_dB = (status_0 & 0x1ff);
- noise_dbm -= (s8) (gain_dB);
- } else {
- noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
- }
- } else if (ISNPHY(pi)) {
-
- jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
- channel = jssi_aux & D11_CURCHANNEL_MAX;
-
- noise_dbm = wlc_phy_noise_read_shmem(pi);
- }
-
- wlc_phy_noise_cb(pi, channel, noise_dbm);
-
-}
-
-s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
+static const s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
8,
8,
8,
@@ -2678,27 +2556,21 @@ void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core)
}
}
-void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, void *ctx)
+int wlc_phy_rssi_compute(struct brcms_phy_pub *pih,
+ struct d11rxhdr *rxh)
{
- struct brcms_d11rxhdr *wlc_rxhdr = (struct brcms_d11rxhdr *) ctx;
- struct d11rxhdr *rxh = &wlc_rxhdr->rxhdr;
- int rssi = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_JSSI_MASK;
+ int rssi = rxh->PhyRxStatus_1 & PRXS1_JSSI_MASK;
uint radioid = pih->radioid;
struct brcms_phy *pi = (struct brcms_phy *) pih;
- if (NORADIO_ENAB(pi->pubpi)) {
- rssi = BRCMS_RSSI_INVALID;
- goto end;
- }
-
if ((pi->sh->corerev >= 11)
- && !(le16_to_cpu(rxh->RxStatus2) & RXS_PHYRXST_VALID)) {
+ && !(rxh->RxStatus2 & RXS_PHYRXST_VALID)) {
rssi = BRCMS_RSSI_INVALID;
goto end;
}
if (ISLCNPHY(pi)) {
- u8 gidx = (le16_to_cpu(rxh->PhyRxStatus_2) & 0xFC00) >> 10;
+ u8 gidx = (rxh->PhyRxStatus_2 & 0xFC00) >> 10;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
if (rssi > 127)
@@ -2715,16 +2587,15 @@ void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, void *ctx)
}
if (ISLCNPHY(pi)) {
-
if (rssi > 127)
rssi -= 256;
} else if (radioid == BCM2055_ID || radioid == BCM2056_ID
|| radioid == BCM2057_ID) {
- rssi = wlc_phy_rssi_compute_nphy(pi, wlc_rxhdr);
+ rssi = wlc_phy_rssi_compute_nphy(pi, rxh);
}
- end:
- wlc_rxhdr->rssi = (s8) rssi;
+end:
+ return rssi;
}
void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih)
@@ -2757,28 +2628,22 @@ void wlc_phy_watchdog(struct brcms_phy_pub *pih)
if (!pi->watchdog_override)
return;
- if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) {
+ if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)))
wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi,
PHY_NOISE_SAMPLE_MON,
CHSPEC_CHANNEL(pi->
radio_chanspec));
- }
- if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) {
+ if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5)
pi->phynoise_state = 0;
- }
if ((!pi->phycal_txpower) ||
((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) {
- if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) {
+ if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi))
pi->phycal_txpower = pi->sh->now;
- }
}
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
|| ASSOC_INPROG_PHY(pi)))
return;
@@ -2800,8 +2665,9 @@ void wlc_phy_watchdog(struct brcms_phy_pub *pih)
((pi->sh->now - pi->phy_lastcal) >=
pi->sh->glacial_timer)) {
if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi)))
- wlc_lcnphy_calib_modes(pi,
- LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
+ wlc_lcnphy_calib_modes(
+ pi,
+ LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
if (!
(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
|| ASSOC_INPROG_PHY(pi)
@@ -2819,13 +2685,12 @@ void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi)
uint i;
uint k;
- for (i = 0; i < MA_WINDOW_SZ; i++) {
+ for (i = 0; i < MA_WINDOW_SZ; i++)
pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff);
- }
if (ISLCNPHY(pi)) {
for (i = 0; i < MA_WINDOW_SZ; i++)
pi->sh->phy_noise_window[i] =
- PHY_NOISE_FIXED_VAL_LCNPHY;
+ PHY_NOISE_FIXED_VAL_LCNPHY;
}
pi->sh->phy_noise_index = 0;
@@ -2848,72 +2713,9 @@ wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag)
*eps_real -= 0x2000;
}
-static const fixed AtanTbl[] = {
- 2949120,
- 1740967,
- 919879,
- 466945,
- 234379,
- 117304,
- 58666,
- 29335,
- 14668,
- 7334,
- 3667,
- 1833,
- 917,
- 458,
- 229,
- 115,
- 57,
- 29
-};
-
-void wlc_phy_cordic(fixed theta, cs32 *val)
-{
- fixed angle, valtmp;
- unsigned iter;
- int signx = 1;
- int signtheta;
-
- val[0].i = CORDIC_AG;
- val[0].q = 0;
- angle = 0;
-
- signtheta = (theta < 0) ? -1 : 1;
- theta =
- ((theta + FIXED(180) * signtheta) % FIXED(360)) -
- FIXED(180) * signtheta;
-
- if (FLOAT(theta) > 90) {
- theta -= FIXED(180);
- signx = -1;
- } else if (FLOAT(theta) < -90) {
- theta += FIXED(180);
- signx = -1;
- }
-
- for (iter = 0; iter < CORDIC_NI; iter++) {
- if (theta > angle) {
- valtmp = val[0].i - (val[0].q >> iter);
- val[0].q = (val[0].i >> iter) + val[0].q;
- val[0].i = valtmp;
- angle += AtanTbl[iter];
- } else {
- valtmp = val[0].i + (val[0].q >> iter);
- val[0].q = -(val[0].i >> iter) + val[0].q;
- val[0].i = valtmp;
- angle -= AtanTbl[iter];
- }
- }
-
- val[0].i = val[0].i * signx;
- val[0].q = val[0].q * signx;
-}
-
void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi)
{
- wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
+ wlapi_del_timer(pi->phycal_timer);
pi->cal_type_override = PHY_PERICAL_AUTO;
pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
@@ -2928,10 +2730,10 @@ wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay)
(pi->nphy_perical != PHY_PERICAL_MANUAL))
return;
- wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
+ wlapi_del_timer(pi->phycal_timer);
pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
- wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
+ wlapi_add_timer(pi->phycal_timer, delay, 0);
}
void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
@@ -2954,11 +2756,12 @@ void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
case PHY_PERICAL_PHYINIT:
if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
- if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+ if (PHY_PERICAL_MPHASE_PENDING(pi))
wlc_phy_cal_perical_mphase_reset(pi);
- }
- wlc_phy_cal_perical_mphase_schedule(pi,
- PHY_PERICAL_INIT_DELAY);
+
+ wlc_phy_cal_perical_mphase_schedule(
+ pi,
+ PHY_PERICAL_INIT_DELAY);
}
break;
@@ -2966,17 +2769,16 @@ void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
case PHY_PERICAL_START_IBSS:
case PHY_PERICAL_UP_BSS:
if ((pi->nphy_perical == PHY_PERICAL_MPHASE) &&
- PHY_PERICAL_MPHASE_PENDING(pi)) {
+ PHY_PERICAL_MPHASE_PENDING(pi))
wlc_phy_cal_perical_mphase_reset(pi);
- }
pi->first_cal_after_assoc = true;
pi->cal_type_override = PHY_PERICAL_FULL;
- if (pi->phycal_tempdelta) {
+ if (pi->phycal_tempdelta)
pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi);
- }
+
wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL);
break;
@@ -2984,26 +2786,24 @@ void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
if (pi->phycal_tempdelta) {
nphy_currtemp = wlc_phy_tempsense_nphy(pi);
delta_temp =
- (nphy_currtemp > pi->nphy_lastcal_temp) ?
- nphy_currtemp - pi->nphy_lastcal_temp :
- pi->nphy_lastcal_temp - nphy_currtemp;
+ (nphy_currtemp > pi->nphy_lastcal_temp) ?
+ nphy_currtemp - pi->nphy_lastcal_temp :
+ pi->nphy_lastcal_temp - nphy_currtemp;
if ((delta_temp < (s16) pi->phycal_tempdelta) &&
(pi->nphy_txiqlocal_chanspec ==
- pi->radio_chanspec)) {
+ pi->radio_chanspec))
do_periodic_cal = false;
- } else {
+ else
pi->nphy_lastcal_temp = nphy_currtemp;
- }
}
if (do_periodic_cal) {
-
if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
-
if (!PHY_PERICAL_MPHASE_PENDING(pi))
- wlc_phy_cal_perical_mphase_schedule(pi,
- PHY_PERICAL_WDOG_DELAY);
+ wlc_phy_cal_perical_mphase_schedule(
+ pi,
+ PHY_PERICAL_WDOG_DELAY);
} else if (pi->nphy_perical == PHY_PERICAL_SPHASE)
wlc_phy_cal_perical_nphy_run(pi,
PHY_PERICAL_AUTO);
@@ -3025,7 +2825,7 @@ u8 wlc_phy_nbits(s32 value)
s32 abs_val;
u8 nbits = 0;
- abs_val = ABS(value);
+ abs_val = abs(value);
while ((abs_val >> nbits) > 0)
nbits++;
@@ -3040,7 +2840,7 @@ void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
pi->sh->hw_phyrxchain = rxchain;
pi->sh->phytxchain = txchain;
pi->sh->phyrxchain = rxchain;
- pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
+ pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain);
}
void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
@@ -3049,10 +2849,10 @@ void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
pi->sh->phytxchain = txchain;
- if (ISNPHY(pi)) {
+ if (ISNPHY(pi))
wlc_phy_rxcore_setstate_nphy(pih, rxchain);
- }
- pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
+
+ pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain);
}
void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain)
@@ -3095,17 +2895,17 @@ u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih)
return active_bitmap;
}
-s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, chanspec_t chanspec)
+s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
u8 siso_mcs_id, cdd_mcs_id;
siso_mcs_id =
- (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
- TXP_FIRST_MCS_20_SISO;
+ (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
+ TXP_FIRST_MCS_20_SISO;
cdd_mcs_id =
- (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
- TXP_FIRST_MCS_20_CDD;
+ (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
+ TXP_FIRST_MCS_20_CDD;
if (pi->tx_power_target[siso_mcs_id] >
(pi->tx_power_target[cdd_mcs_id] + 12))
@@ -3133,12 +2933,13 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
}
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpiocontrol), ~0x0,
- 0x0);
+ offsetof(struct chipcregs, gpiocontrol),
+ ~0x0, 0x0);
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpioout), 0x40, 0x40);
+ offsetof(struct chipcregs, gpioout), 0x40,
+ 0x40);
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpioouten), 0x40,
+ offsetof(struct chipcregs, gpioouten), 0x40,
0x40);
} else {
mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
@@ -3146,56 +2947,18 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpioout), 0x40, 0x00);
+ offsetof(struct chipcregs, gpioout), 0x40,
+ 0x00);
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpioouten), 0x40, 0x0);
+ offsetof(struct chipcregs, gpioouten), 0x40,
+ 0x0);
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpiocontrol), ~0x0,
- 0x40);
+ offsetof(struct chipcregs, gpiocontrol),
+ ~0x0, 0x40);
}
}
}
-static s8
-wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
- u8 rate)
-{
- s8 offset = 0;
-
- if (!pi->user_txpwr_at_rfport)
- return offset;
- return offset;
-}
-
-static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi)
-{
- if (ISLCNPHY(pi))
- return wlc_lcnphy_vbatsense(pi, 0);
- else
- return 0;
-}
-
-static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi)
-{
- if (ISLCNPHY(pi))
- return wlc_lcnphy_tempsense_degree(pi, 0);
- else
- return 0;
-}
-
-static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band)
-{
- u8 i;
- s8 temp, vbat;
-
- for (i = 0; i < TXP_NUM_RATES; i++)
- pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
-
- vbat = wlc_phy_env_measure_vbat(pi);
- temp = wlc_phy_env_measure_temperature(pi);
-
-}
-
void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc)
{
return;
@@ -3208,7 +2971,7 @@ wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset)
*ofdmoffset = 0;
}
-s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, chanspec_t chanspec)
+s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec)
{
return rssi;
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h b/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h
index e27d9e95a2dc..96e15163222b 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h
@@ -103,6 +103,9 @@
#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];
@@ -126,42 +129,44 @@ struct txpwr_limits {
struct tx_power {
u32 flags;
- chanspec_t chanspec; /* txpwr report for this channel */
- chanspec_t 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 */
- u8 tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */
- u8 user_limit[WL_TX_POWER_RATES]; /* User limit */
- u8 reg_limit[WL_TX_POWER_RATES]; /* Regulatory power limit */
- u8 board_limit[WL_TX_POWER_RATES]; /* Max power board can support (SROM) */
- u8 target[WL_TX_POWER_RATES]; /* Latest target power */
+ 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 */
+ 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 chanvec {
+struct brcms_chanvec {
u8 vec[MAXCHANNEL / NBBY];
};
struct shared_phy_params {
struct si_pub *sih;
- void *physhim;
+ struct phy_shim_info *physhim;
uint unit;
uint corerev;
- uint bustype;
uint buscorerev;
- char *vars;
u16 vid;
u16 did;
uint chip;
@@ -177,8 +182,9 @@ struct shared_phy_params {
extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp);
-extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, void *regs,
- int bandtype, char *vars, struct wiphy *wiphy);
+extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh,
+ struct d11regs __iomem *regs,
+ int bandtype, struct wiphy *wiphy);
extern void wlc_phy_detach(struct brcms_phy_pub *ppi);
extern bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype,
@@ -189,7 +195,7 @@ extern u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih);
extern void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate);
extern void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate);
-extern void wlc_phy_init(struct brcms_phy_pub *ppi, chanspec_t chanspec);
+extern void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec);
extern void wlc_phy_watchdog(struct brcms_phy_pub *ppi);
extern int wlc_phy_down(struct brcms_phy_pub *ppi);
extern u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih);
@@ -197,14 +203,15 @@ extern void wlc_phy_cal_init(struct brcms_phy_pub *ppi);
extern void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init);
extern void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi,
- chanspec_t chanspec);
-extern chanspec_t wlc_phy_chanspec_get(struct brcms_phy_pub *ppi);
+ u16 chanspec);
+extern u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi);
extern void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi,
- chanspec_t newch);
+ u16 newch);
extern u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi);
extern void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw);
-extern void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, void *ctx);
+extern int wlc_phy_rssi_compute(struct brcms_phy_pub *pih,
+ struct d11rxhdr *rxh);
extern void wlc_phy_por_inform(struct brcms_phy_pub *ppi);
extern void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi);
extern bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi);
@@ -220,9 +227,9 @@ extern void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi);
extern void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
bool wide_filter);
extern void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
- chanvec_t *channels);
-extern chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi,
- uint band);
+ struct brcms_chanvec *channels);
+extern u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi,
+ uint band);
extern void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan,
u8 *_min_, u8 *_max_, int rate);
@@ -232,7 +239,7 @@ extern void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi,
uint band, s32 *, s32 *, u32 *);
extern void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi,
struct txpwr_limits *,
- chanspec_t chanspec);
+ u16 chanspec);
extern int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm,
bool *override);
extern int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm,
@@ -254,7 +261,7 @@ extern void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain,
u8 *rxchain);
extern u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih);
extern s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih,
- chanspec_t chanspec);
+ u16 chanspec);
extern void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val);
extern void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason);
@@ -264,8 +271,8 @@ extern void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi);
extern void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val);
extern void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi);
-extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, mbool id, bool val);
-extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, mbool flags);
+extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val);
+extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags);
extern void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type);
@@ -289,6 +296,6 @@ extern void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi);
extern const u8 *wlc_phy_get_ofdm_rate_lookup(void);
extern s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi,
- u8 mcs_offset);
+ u8 mcs_offset);
extern s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset);
-#endif /* _BRCM_PHY_HAL_H_ */
+#endif /* _BRCM_PHY_HAL_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h b/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h
index a01b01ccd9ff..bea85241a244 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h
@@ -23,53 +23,26 @@
#define PHY_VERSION { 1, 82, 8, 0 }
-#define PHYHAL_ERROR 0x0001
-#define PHYHAL_TRACE 0x0002
-#define PHYHAL_INFORM 0x0004
-
-extern u32 phyhal_msg_level;
-
-#define PHY_INFORM_ON() (phyhal_msg_level & PHYHAL_INFORM)
-#define PHY_THERMAL_ON() (phyhal_msg_level & PHYHAL_THERMAL)
-#define PHY_CAL_ON() (phyhal_msg_level & PHYHAL_CAL)
-
-#ifdef BOARD_TYPE
-#define BOARDTYPE(_type) BOARD_TYPE
-#else
-#define BOARDTYPE(_type) _type
-#endif
-
#define LCNXN_BASEREV 16
+struct phy_shim_info;
+
struct brcms_phy_srom_fem {
- u8 tssipos; /* TSSI positive slope, 1: positive, 0: negative */
- u8 extpagain; /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
- u8 pdetrange; /* support 32 combinations of different Pdet dynamic ranges */
- u8 triso; /* TR switch isolation */
- u8 antswctrllut; /* antswctrl lookup table configuration: 32 possible choices */
+ /* TSSI positive slope, 1: positive, 0: negative */
+ u8 tssipos;
+ /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
+ u8 extpagain;
+ /* support 32 combinations of different Pdet dynamic ranges */
+ u8 pdetrange;
+ /* TR switch isolation */
+ u8 triso;
+ /* antswctrl lookup table configuration: 32 possible choices */
+ u8 antswctrllut;
};
-typedef void (*initfn_t) (struct brcms_phy *);
-typedef void (*chansetfn_t) (struct brcms_phy *, chanspec_t);
-typedef int (*longtrnfn_t) (struct brcms_phy *, int);
-typedef void (*txiqccgetfn_t) (struct brcms_phy *, u16 *, u16 *);
-typedef void (*txiqccsetfn_t) (struct brcms_phy *, u16, u16);
-typedef u16(*txloccgetfn_t) (struct brcms_phy *);
-typedef void (*radioloftgetfn_t) (struct brcms_phy *, u8 *, u8 *, u8 *,
- u8 *);
-typedef s32(*rxsigpwrfn_t) (struct brcms_phy *, s32);
-typedef void (*detachfn_t) (struct brcms_phy *);
-
-#undef ISNPHY
-#undef ISLCNPHY
#define ISNPHY(pi) PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N)
#define ISLCNPHY(pi) PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_LCN)
-#define ISPHY_11N_CAP(pi) (ISNPHY(pi) || ISLCNPHY(pi))
-
-#define IS20MHZ(pi) ((pi)->bw == WL_CHANSPEC_BW_20)
-#define IS40MHZ(pi) ((pi)->bw == WL_CHANSPEC_BW_40)
-
#define PHY_GET_RFATTN(rfgain) ((rfgain) & 0x0f)
#define PHY_GET_PADMIX(rfgain) (((rfgain) & 0x10) >> 4)
#define PHY_GET_RFGAINID(rfattn, padmix, width) ((rfattn) + ((padmix)*(width)))
@@ -203,7 +176,9 @@ typedef void (*detachfn_t) (struct brcms_phy *);
#define PHY_PERICAL_WDOG_DELAY 5
#define MPHASE_TXCAL_NUMCMDS 2
-#define PHY_PERICAL_MPHASE_PENDING(pi) (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE)
+
+#define PHY_PERICAL_MPHASE_PENDING(pi) \
+ (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE)
enum {
MPHASE_CAL_STATE_IDLE = 0,
@@ -248,47 +223,29 @@ enum phy_cal_mode {
#define CORDIC_AG 39797
#define CORDIC_NI 18
#define FIXED(X) ((s32)((X) << 16))
-#define FLOAT(X) (((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1))
+
+#define FLOAT(X) \
+ (((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1))
#define PHY_CHAIN_TX_DISABLE_TEMP 115
#define PHY_HYSTERESIS_DELTATEMP 5
-#define PHY_BITSCNT(x) brcmu_bitcount((u8 *)&(x), sizeof(u8))
-
-#define MOD_PHY_REG(pi, phy_type, reg_name, field, value) \
- mod_phy_reg(pi, phy_type##_##reg_name, phy_type##_##reg_name##_##field##_MASK, \
- (value) << phy_type##_##reg_name##_##field##_##SHIFT);
-#define READ_PHY_REG(pi, phy_type, reg_name, field) \
- ((read_phy_reg(pi, phy_type##_##reg_name) & phy_type##_##reg_name##_##field##_##MASK)\
- >> phy_type##_##reg_name##_##field##_##SHIFT)
+#define SCAN_INPROG_PHY(pi) \
+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN))
-#define VALID_PHYTYPE(phytype) (((uint)phytype == PHY_TYPE_N) || \
- ((uint)phytype == PHY_TYPE_LCN))
+#define PLT_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT))
-#define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || (radioid == BCM2056_ID) || \
- (radioid == BCM2057_ID))
-#define VALID_LCN_RADIO(radioid) (radioid == BCM2064_ID)
+#define ASSOC_INPROG_PHY(pi) \
+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC))
-#define VALID_RADIO(pi, radioid) (\
- (ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
- (ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
+#define SCAN_RM_IN_PROGRESS(pi) \
+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM))
-#define SCAN_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN))
-#define RM_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_RM))
-#define PLT_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT))
-#define ASSOC_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC))
-#define SCAN_RM_IN_PROGRESS(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM))
-#define PHY_MUTED(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE))
-#define PUB_NOT_ASSOC(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC))
+#define PHY_MUTED(pi) \
+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE))
-#if defined(EXT_CBALL)
-#define NORADIO_ENAB(pub) ((pub).radioid == NORADIO_ID)
-#else
-#define NORADIO_ENAB(pub) 0
-#endif
-
-#define PHY_LTRN_LIST_LEN 64
-extern u16 ltrn_list[PHY_LTRN_LIST_LEN];
+#define PUB_NOT_ASSOC(pi) \
+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC))
struct phy_table_info {
uint table;
@@ -532,7 +489,7 @@ struct shared_phy {
struct brcms_phy *phy_head;
uint unit;
struct si_pub *sih;
- void *physhim;
+ struct phy_shim_info *physhim;
uint corerev;
u32 machwcap;
bool up;
@@ -549,7 +506,6 @@ struct shared_phy {
uint boardvendor;
u32 boardflags;
u32 boardflags2;
- uint bustype;
uint buscorerev;
uint fast_timer;
uint slow_timer;
@@ -579,41 +535,39 @@ struct brcms_phy_pub {
};
struct phy_func_ptr {
- initfn_t init;
- initfn_t calinit;
- chansetfn_t chanset;
- initfn_t txpwrrecalc;
- longtrnfn_t longtrn;
- txiqccgetfn_t txiqccget;
- txiqccsetfn_t txiqccset;
- txloccgetfn_t txloccget;
- radioloftgetfn_t radioloftget;
- initfn_t carrsuppr;
- rxsigpwrfn_t rxsigpwr;
- detachfn_t detach;
+ void (*init)(struct brcms_phy *);
+ void (*calinit)(struct brcms_phy *);
+ void (*chanset)(struct brcms_phy *, u16 chanspec);
+ void (*txpwrrecalc)(struct brcms_phy *);
+ int (*longtrn)(struct brcms_phy *, int);
+ void (*txiqccget)(struct brcms_phy *, u16 *, u16 *);
+ void (*txiqccset)(struct brcms_phy *, u16, u16);
+ u16 (*txloccget)(struct brcms_phy *);
+ void (*radioloftget)(struct brcms_phy *, u8 *, u8 *, u8 *, u8 *);
+ void (*carrsuppr)(struct brcms_phy *);
+ s32 (*rxsigpwr)(struct brcms_phy *, s32);
+ void (*detach)(struct brcms_phy *);
};
struct brcms_phy {
struct brcms_phy_pub pubpi_ro;
struct shared_phy *sh;
struct phy_func_ptr pi_fptr;
- void *pi_ptr;
union {
struct brcms_phy_lcnphy *pi_lcnphy;
} u;
bool user_txpwr_at_rfport;
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
struct brcms_phy *next;
- char *vars;
struct brcms_phy_pub pubpi;
bool do_initcal;
bool phytest_on;
bool ofdm_rateset_war;
bool bf_preempt_4306;
- chanspec_t radio_chanspec;
+ u16 radio_chanspec;
u8 antsel_type;
u16 bw;
u8 txpwr_percent;
@@ -629,7 +583,7 @@ struct brcms_phy {
int phynoise_chan_watchdog;
bool phynoise_polling;
bool disable_percal;
- mbool measure_hold;
+ u32 measure_hold;
s16 txpa_2g[PWRTBL_NUM_COEFF];
s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF];
@@ -723,7 +677,7 @@ struct brcms_phy {
u16 mintxbias;
u16 mintxmag;
struct lo_complex_abgphy_info gphy_locomp_iq
- [STATIC_NUM_RF][STATIC_NUM_BB];
+ [STATIC_NUM_RF][STATIC_NUM_BB];
s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB];
u16 gain_table[TX_GAIN_TABLE_LENGTH];
bool loopback_gain;
@@ -840,11 +794,11 @@ struct brcms_phy {
u8 mphase_txcal_cmdidx;
u8 mphase_txcal_numcmds;
u16 mphase_txcal_bestcoeffs[11];
- chanspec_t nphy_txiqlocal_chanspec;
- chanspec_t nphy_iqcal_chanspec_2G;
- chanspec_t nphy_iqcal_chanspec_5G;
- chanspec_t nphy_rssical_chanspec_2G;
- chanspec_t nphy_rssical_chanspec_5G;
+ u16 nphy_txiqlocal_chanspec;
+ u16 nphy_iqcal_chanspec_2G;
+ u16 nphy_iqcal_chanspec_5G;
+ u16 nphy_rssical_chanspec_2G;
+ u16 nphy_rssical_chanspec_5G;
struct wlapi_timer *phycal_timer;
bool use_int_tx_iqlo_cal_nphy;
bool internal_tx_iqlo_cal_tapoff_intpa_nphy;
@@ -937,9 +891,9 @@ struct brcms_phy {
struct wiphy *wiphy;
};
-struct _cs32 {
- fixed q;
- fixed i;
+struct cs32 {
+ s32 q;
+ s32 i;
};
struct radio_regs {
@@ -964,29 +918,6 @@ struct lcnphy_radio_regs {
u8 do_init_g;
};
-extern struct lcnphy_radio_regs lcnphy_radio_regs_2064[];
-extern struct lcnphy_radio_regs lcnphy_radio_regs_2066[];
-extern struct radio_regs regs_2055[], regs_SYN_2056[], regs_TX_2056[],
- regs_RX_2056[];
-extern struct radio_regs regs_SYN_2056_A1[], regs_TX_2056_A1[],
- regs_RX_2056_A1[];
-extern struct radio_regs regs_SYN_2056_rev5[], regs_TX_2056_rev5[],
- regs_RX_2056_rev5[];
-extern struct radio_regs regs_SYN_2056_rev6[], regs_TX_2056_rev6[],
- regs_RX_2056_rev6[];
-extern struct radio_regs regs_SYN_2056_rev7[], regs_TX_2056_rev7[],
- regs_RX_2056_rev7[];
-extern struct radio_regs regs_SYN_2056_rev8[], regs_TX_2056_rev8[],
- regs_RX_2056_rev8[];
-extern struct radio_20xx_regs regs_2057_rev4[], regs_2057_rev5[],
- regs_2057_rev5v1[];
-extern struct radio_20xx_regs regs_2057_rev7[], regs_2057_rev8[];
-
-extern char *phy_getvar(struct brcms_phy *pi, const char *name);
-extern int phy_getintvar(struct brcms_phy *pi, const char *name);
-#define PHY_GETVAR(pi, name) phy_getvar(pi, name)
-#define PHY_GETINTVAR(pi, name) phy_getintvar(pi, name)
-
extern u16 read_phy_reg(struct brcms_phy *pi, u16 addr);
extern void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
extern void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
@@ -1022,14 +953,13 @@ extern void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val);
extern void write_phy_channel_reg(struct brcms_phy *pi, uint val);
extern void wlc_phy_txpower_update_shm(struct brcms_phy *pi);
-extern void wlc_phy_cordic(fixed theta, cs32 *val);
extern u8 wlc_phy_nbits(s32 value);
extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core);
extern uint wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
struct radio_20xx_regs *radioregs);
extern uint wlc_phy_init_radio_regs(struct brcms_phy *pi,
- struct radio_regs *radioregs,
+ const struct radio_regs *radioregs,
u16 core_offset);
extern void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi);
@@ -1053,14 +983,14 @@ extern void wlc_phy_cal_init_nphy(struct brcms_phy *pi);
extern void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi);
extern void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi,
- chanspec_t chanspec);
+ u16 chanspec);
extern void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi,
- chanspec_t chanspec);
+ u16 chanspec);
extern void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi,
- chanspec_t chanspec);
+ u16 chanspec);
extern int wlc_phy_channel2freq(uint channel);
extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint);
-extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, chanspec_t);
+extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, u16 chanspec);
extern void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode);
extern s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi);
@@ -1142,13 +1072,17 @@ extern void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi,
bool enable);
extern void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode);
-#define wlc_phy_write_table_nphy(pi, pti) wlc_phy_write_table(pi, pti, 0x72, \
- 0x74, 0x73)
-#define wlc_phy_read_table_nphy(pi, pti) wlc_phy_read_table(pi, pti, 0x72, \
- 0x74, 0x73)
-#define wlc_nphy_table_addr(pi, id, off) wlc_phy_table_addr((pi), (id), (off), \
- 0x72, 0x74, 0x73)
-#define wlc_nphy_table_data_write(pi, w, v) wlc_phy_table_data_write((pi), (w), (v))
+#define wlc_phy_write_table_nphy(pi, pti) \
+ wlc_phy_write_table(pi, pti, 0x72, 0x74, 0x73)
+
+#define wlc_phy_read_table_nphy(pi, pti) \
+ wlc_phy_read_table(pi, pti, 0x72, 0x74, 0x73)
+
+#define wlc_nphy_table_addr(pi, id, off) \
+ wlc_phy_table_addr((pi), (id), (off), 0x72, 0x74, 0x73)
+
+#define wlc_nphy_table_data_write(pi, w, v) \
+ wlc_phy_table_data_write((pi), (w), (v))
extern void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o,
u32 w, void *d);
@@ -1160,7 +1094,7 @@ extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32,
(pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec)))
#define BRCMS_PHY_WAR_PR51571(pi) \
- if (((pi)->sh->bustype == PCI_BUS) && NREV_LT((pi)->pubpi.phy_rev, 3)) \
+ if (NREV_LT((pi)->pubpi.phy_rev, 3)) \
(void)R_REG(&(pi)->regs->maccontrol)
extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype);
@@ -1219,7 +1153,7 @@ extern void wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf,
extern void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi);
extern int wlc_phy_rssi_compute_nphy(struct brcms_phy *pi,
- struct brcms_d11rxhdr *wlc_rxh);
+ struct d11rxhdr *rxh);
#define NPHY_TESTPATTERN_BPHY_EVM 0
#define NPHY_TESTPATTERN_BPHY_RFCS 1
@@ -1229,7 +1163,7 @@ extern void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs);
void wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset,
s8 *ofdmoffset);
extern s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi,
- chanspec_t chanspec);
+ u16 chanspec);
extern bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih);
#endif /* _BRCM_PHY_INT_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c
index 6a3fbe67302f..a63aa99d9810 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -14,7 +14,9 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/kernel.h>
#include <linux/delay.h>
+#include <linux/cordic.h>
#include <pmu.h>
#include <d11.h>
@@ -67,6 +69,14 @@
#define LCN_TEMPSENSE_OFFSET 80812
#define LCN_TEMPSENSE_DEN 2647
+#define LCN_BW_LMT 200
+#define LCN_CUR_LMT 1250
+#define LCN_MULT 1
+#define LCN_VCO_DIV 30
+#define LCN_OFFSET 680
+#define LCN_FACT 490
+#define LCN_CUR_DIV 2640
+
#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
(0 + 8)
#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
@@ -79,15 +89,15 @@
#define wlc_lcnphy_enable_tx_gain_override(pi) \
wlc_lcnphy_set_tx_gain_override(pi, true)
-#define wlc_lcnphy_disable_tx_gain_override(pi) \
+#define wlc_lcnphy_disable_tx_gain_override(pi) \
wlc_lcnphy_set_tx_gain_override(pi, false)
#define wlc_lcnphy_iqcal_active(pi) \
(read_phy_reg((pi), 0x451) & \
- ((0x1 << 15) | (0x1 << 14)))
+ ((0x1 << 15) | (0x1 << 14)))
#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
-#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
+#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
(pi->temppwrctrl_capable)
#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
(pi->hwpwrctrl_capable)
@@ -132,12 +142,12 @@
#define LCNPHY_ACI_DETECT_TIMEOUT 2
#define LCNPHY_ACI_START_DELAY 0
-#define wlc_lcnphy_tx_gain_override_enabled(pi) \
+#define wlc_lcnphy_tx_gain_override_enabled(pi) \
(0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
#define wlc_lcnphy_total_tx_frames(pi) \
- wlapi_bmac_read_shm((pi)->sh->physhim, \
- M_UCODE_MACSTAT + offsetof(struct macstat, txallfrm))
+ wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + \
+ offsetof(struct macstat, txallfrm))
struct lcnphy_txgains {
u16 gm_gain;
@@ -198,7 +208,7 @@ static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
sizeof(tbl_iqcal_gainparams_lcnphy_2G) /
- sizeof(*tbl_iqcal_gainparams_lcnphy_2G),
+ sizeof(*tbl_iqcal_gainparams_lcnphy_2G),
};
static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = {
@@ -548,7 +558,7 @@ struct chan_info_2064_lcnphy {
u8 rxrf_rxrf_spare1;
};
-static struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = {
+static const struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = {
{1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
{2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
{3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
@@ -565,7 +575,7 @@ static struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = {
{14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
};
-struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = {
+static const struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = {
{0x00, 0, 0, 0, 0},
{0x01, 0x64, 0x64, 0, 0},
{0x02, 0x20, 0x20, 0, 0},
@@ -877,7 +887,7 @@ struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = {
#define LCNPHY_NUM_DIG_FILT_COEFFS 16
#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13
-u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
+static const u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
{0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64,
128, 64,},
@@ -908,7 +918,7 @@ u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
};
#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3
-u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
+static const u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
{0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0,
0x278, 0xfea0, 0x80, 0x100, 0x80,},
@@ -920,108 +930,50 @@ u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \
mod_phy_reg(pi, 0x4a4, \
- (0x1ff << 0), \
- (u16)(idx) << 0)
+ (0x1ff << 0), \
+ (u16)(idx) << 0)
#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \
mod_phy_reg(pi, 0x4a5, \
- (0x7 << 8), \
- (u16)(npt) << 8)
+ (0x7 << 8), \
+ (u16)(npt) << 8)
#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \
(read_phy_reg((pi), 0x4a4) & \
- ((0x1 << 15) | \
- (0x1 << 14) | \
- (0x1 << 13)))
+ ((0x1 << 15) | \
+ (0x1 << 14) | \
+ (0x1 << 13)))
#define wlc_lcnphy_get_tx_pwr_npt(pi) \
((read_phy_reg(pi, 0x4a5) & \
- (0x7 << 8)) >> \
- 8)
+ (0x7 << 8)) >> \
+ 8)
#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \
(read_phy_reg(pi, 0x473) & 0x1ff)
#define wlc_lcnphy_get_target_tx_pwr(pi) \
((read_phy_reg(pi, 0x4a7) & \
- (0xff << 0)) >> \
- 0)
+ (0xff << 0)) >> \
+ 0)
#define wlc_lcnphy_set_target_tx_pwr(pi, target) \
mod_phy_reg(pi, 0x4a7, \
- (0xff << 0), \
- (u16)(target) << 0)
+ (0xff << 0), \
+ (u16)(target) << 0)
+
+#define wlc_radio_2064_rcal_done(pi) \
+ (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
+
+#define tempsense_done(pi) \
+ (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
-#define wlc_radio_2064_rcal_done(pi) (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
-#define tempsense_done(pi) (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
+#define LCNPHY_IQLOCC_READ(val) \
+ ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
-#define LCNPHY_IQLOCC_READ(val) ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
#define FIXED_TXPWR 78
#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val))
-static u32 wlc_lcnphy_qdiv_roundup(u32 divident, u32 divisor,
- u8 precision);
-static void wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
- u16 ext_lna, u16 trsw,
- u16 biq2, u16 biq1,
- u16 tia, u16 lna2,
- u16 lna1);
-static void wlc_lcnphy_clear_tx_power_offsets(struct brcms_phy *pi);
-static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain);
-static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx,
- bool rx);
-static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0);
-static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi);
-static void wlc_lcnphy_get_tx_gain(struct brcms_phy *pi,
- struct lcnphy_txgains *gains);
-static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable);
-static void wlc_lcnphy_toggle_afe_pwdn(struct brcms_phy *pi);
-static void wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi,
- bool enable);
-static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi,
- struct lcnphy_txgains *target_gains);
-static bool wlc_lcnphy_rx_iq_est(struct brcms_phy *pi, u16 num_samps,
- u8 wait_time, struct lcnphy_iq_est *iq_est);
-static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps);
-static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi);
-static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode);
-static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi);
-static void wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi,
- u8 channel);
-
-static void wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
- const struct lcnphy_tx_gain_tbl_entry *g);
-
-static void wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo,
- u16 thresh, s16 *ptr, int mode);
-static int wlc_lcnphy_calc_floor(s16 coeff, int type);
-static void wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi,
- u16 *values_to_save);
-static void wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi,
- u16 *values_to_save);
-static void wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x,
- s16 coeff_y);
-static struct lcnphy_unsign16_struct wlc_lcnphy_get_cc(struct brcms_phy *pi,
- int cal_type);
-static void wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type,
- int num_levels, int step_size_lg2);
-static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi);
-
-static void wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi,
- chanspec_t chanspec);
-static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi);
-static void wlc_lcnphy_temp_adj(struct brcms_phy *pi);
-static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi);
-static void wlc_lcnphy_baseband_init(struct brcms_phy *pi);
-static void wlc_lcnphy_radio_init(struct brcms_phy *pi);
-static void wlc_lcnphy_rc_cal(struct brcms_phy *pi);
-static void wlc_lcnphy_rcal(struct brcms_phy *pi);
-static void wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi,
- bool enable);
-static int wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm,
- s16 filt_type);
-static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b);
-
void wlc_lcnphy_write_table(struct brcms_phy *pi, const struct phytbl_info *pti)
{
wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456);
@@ -1034,7 +986,7 @@ void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti)
static void
wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id,
- const void *tbl_ptr, u32 tbl_len,
+ const u16 *tbl_ptr, u32 tbl_len,
u32 tbl_width, u32 tbl_offset)
{
struct phytbl_info tab;
@@ -1048,7 +1000,7 @@ wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id,
static void
wlc_lcnphy_common_write_table(struct brcms_phy *pi, u32 tbl_id,
- const void *tbl_ptr, u32 tbl_len,
+ const u16 *tbl_ptr, u32 tbl_len,
u32 tbl_width, u32 tbl_offset)
{
@@ -1092,12 +1044,12 @@ static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
int k;
k = 0;
if (type == 0) {
- if (coeff_x < 0) {
+ if (coeff_x < 0)
k = (coeff_x - 1) / 2;
- } else {
+ else
k = coeff_x / 2;
- }
}
+
if (type == 1) {
if ((coeff_x + 1) < 0)
k = (coeff_x) / 2;
@@ -1107,20 +1059,265 @@ static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
return k;
}
-s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi)
+static void
+wlc_lcnphy_get_tx_gain(struct brcms_phy *pi, struct lcnphy_txgains *gains)
{
- s8 index;
+ u16 dac_gain, rfgain0, rfgain1;
+
+ dac_gain = read_phy_reg(pi, 0x439) >> 0;
+ gains->dac_gain = (dac_gain & 0x380) >> 7;
+
+ rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
+ rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
+
+ gains->gm_gain = rfgain0 & 0xff;
+ gains->pga_gain = (rfgain0 >> 8) & 0xff;
+ gains->pad_gain = rfgain1 & 0xff;
+}
+
+
+static void wlc_lcnphy_set_dac_gain(struct brcms_phy *pi, u16 dac_gain)
+{
+ u16 dac_ctrl;
+
+ dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
+ dac_ctrl = dac_ctrl & 0xc7f;
+ dac_ctrl = dac_ctrl | (dac_gain << 7);
+ mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
+
+}
+
+static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable)
+{
+ u16 bit = bEnable ? 1 : 0;
+
+ mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
+
+ mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
+
+ mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
+}
+
+static void
+wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi, bool enable)
+{
+ u16 ebit = enable ? 1 : 0;
+
+ mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
+
+ mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
+
+ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+ mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
+ mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
+ mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+ mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
+ } else {
+ mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
+ mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
+ mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+ }
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
+ mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
+ }
+}
+
+static void
+wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
+ u16 trsw,
+ u16 ext_lna,
+ u16 biq2,
+ u16 biq1,
+ u16 tia, u16 lna2, u16 lna1)
+{
+ u16 gain0_15, gain16_19;
+
+ gain16_19 = biq2 & 0xf;
+ gain0_15 = ((biq1 & 0xf) << 12) |
+ ((tia & 0xf) << 8) |
+ ((lna2 & 0x3) << 6) |
+ ((lna2 &
+ 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
+
+ mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
+ mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
+ mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
+
+ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+ mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
+ } else {
+ mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
+
+ mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
+
+ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+ }
+
+ mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
+
+}
+
+static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx, bool rx)
+{
+
+ mod_phy_reg(pi, 0x44d,
+ (0x1 << 1) |
+ (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
+
+ or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
+}
+
+static void wlc_lcnphy_clear_trsw_override(struct brcms_phy *pi)
+{
+
+ and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
+}
+
+static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b)
+{
+ mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
+
+ mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
+
+ mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
+
+ mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
+
+ mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
+
+ mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
+
+}
+
+static bool
+wlc_lcnphy_rx_iq_est(struct brcms_phy *pi,
+ u16 num_samps,
+ u8 wait_time, struct lcnphy_iq_est *iq_est)
+{
+ int wait_count = 0;
+ bool result = true;
+ u8 phybw40;
+ phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+ mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
+
+ mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
+
+ mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
+
+ mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
+
+ mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
+
+ mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
+
+ while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
+
+ if (wait_count > (10 * 500)) {
+ result = false;
+ goto cleanup;
+ }
+ udelay(100);
+ wait_count++;
+ }
+
+ iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
+ (u32) read_phy_reg(pi, 0x484);
+ iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
+ (u32) read_phy_reg(pi, 0x486);
+ iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
+ (u32) read_phy_reg(pi, 0x488);
+
+cleanup:
+ mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
+
+ mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
+
+ return result;
+}
+
+static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps)
+{
+#define LCNPHY_MIN_RXIQ_PWR 2
+ bool result;
+ u16 a0_new, b0_new;
+ struct lcnphy_iq_est iq_est = { 0, 0, 0 };
+ s32 a, b, temp;
+ s16 iq_nbits, qq_nbits, arsh, brsh;
+ s32 iq;
+ u32 ii, qq;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- if (txpwrctrl_off(pi))
- index = pi_lcn->lcnphy_current_index;
- else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
- index =
- (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi)
- / 2);
- else
- index = pi_lcn->lcnphy_current_index;
- return index;
+ a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
+ b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
+ mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
+
+ mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
+
+ wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
+
+ result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
+ if (!result)
+ goto cleanup;
+
+ iq = (s32) iq_est.iq_prod;
+ ii = iq_est.i_pwr;
+ qq = iq_est.q_pwr;
+
+ if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
+ result = false;
+ goto cleanup;
+ }
+
+ iq_nbits = wlc_phy_nbits(iq);
+ qq_nbits = wlc_phy_nbits(qq);
+
+ arsh = 10 - (30 - iq_nbits);
+ if (arsh >= 0) {
+ a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+ temp = (s32) (ii >> arsh);
+ if (temp == 0)
+ return false;
+ } else {
+ a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+ temp = (s32) (ii << -arsh);
+ if (temp == 0)
+ return false;
+ }
+ a /= temp;
+ brsh = qq_nbits - 31 + 20;
+ if (brsh >= 0) {
+ b = (qq << (31 - qq_nbits));
+ temp = (s32) (ii >> brsh);
+ if (temp == 0)
+ return false;
+ } else {
+ b = (qq << (31 - qq_nbits));
+ temp = (s32) (ii << -brsh);
+ if (temp == 0)
+ return false;
+ }
+ b /= temp;
+ b -= a * a;
+ b = (s32) int_sqrt((unsigned long) b);
+ b -= (1 << 10);
+ a0_new = (u16) (a & 0x3ff);
+ b0_new = (u16) (b & 0x3ff);
+cleanup:
+
+ wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
+
+ mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
+
+ mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
+
+ pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
+ pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
+
+ return result;
}
static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
@@ -1132,6 +1329,187 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
}
+static bool
+wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
+ const struct lcnphy_rx_iqcomp *iqcomp,
+ int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
+ int tx_gain_idx)
+{
+ struct lcnphy_txgains old_gains;
+ u16 tx_pwr_ctrl;
+ u8 tx_gain_index_old = 0;
+ bool result = false, tx_gain_override_old = false;
+ u16 i, Core1TxControl_old, RFOverride0_old,
+ RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
+ rfoverride3_old, rfoverride3val_old, rfoverride4_old,
+ rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
+ int tia_gain;
+ u32 received_power, rx_pwr_threshold;
+ u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
+ u16 values_to_save[11];
+ s16 *ptr;
+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+ ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+ if (NULL == ptr)
+ return false;
+ if (module == 2) {
+ while (iqcomp_sz--) {
+ if (iqcomp[iqcomp_sz].chan ==
+ CHSPEC_CHANNEL(pi->radio_chanspec)) {
+ wlc_lcnphy_set_rx_iq_comp(pi,
+ (u16)
+ iqcomp[iqcomp_sz].a,
+ (u16)
+ iqcomp[iqcomp_sz].b);
+ result = true;
+ break;
+ }
+ }
+ goto cal_done;
+ }
+
+ if (module == 1) {
+
+ tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+ for (i = 0; i < 11; i++)
+ values_to_save[i] =
+ read_radio_reg(pi, rxiq_cal_rf_reg[i]);
+ Core1TxControl_old = read_phy_reg(pi, 0x631);
+
+ or_phy_reg(pi, 0x631, 0x0015);
+
+ RFOverride0_old = read_phy_reg(pi, 0x44c);
+ RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
+ rfoverride2_old = read_phy_reg(pi, 0x4b0);
+ rfoverride2val_old = read_phy_reg(pi, 0x4b1);
+ rfoverride3_old = read_phy_reg(pi, 0x4f9);
+ rfoverride3val_old = read_phy_reg(pi, 0x4fa);
+ rfoverride4_old = read_phy_reg(pi, 0x938);
+ rfoverride4val_old = read_phy_reg(pi, 0x939);
+ afectrlovr_old = read_phy_reg(pi, 0x43b);
+ afectrlovrval_old = read_phy_reg(pi, 0x43c);
+ old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+ old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+
+ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+ if (tx_gain_override_old) {
+ wlc_lcnphy_get_tx_gain(pi, &old_gains);
+ tx_gain_index_old = pi_lcn->lcnphy_current_index;
+ }
+
+ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
+
+ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+
+ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+ write_radio_reg(pi, RADIO_2064_REG116, 0x06);
+ write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
+ write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
+ write_radio_reg(pi, RADIO_2064_REG098, 0x03);
+ write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+ mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
+ write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
+ write_radio_reg(pi, RADIO_2064_REG114, 0x01);
+ write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
+ write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
+
+ mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
+ mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
+ mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
+ mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
+ mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
+ mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
+ mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
+ mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
+ mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
+ mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+
+ mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+ mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+ wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
+ write_phy_reg(pi, 0x6da, 0xffff);
+ or_phy_reg(pi, 0x6db, 0x3);
+ wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
+ wlc_lcnphy_rx_gain_override_enable(pi, true);
+
+ tia_gain = 8;
+ rx_pwr_threshold = 950;
+ while (tia_gain > 0) {
+ tia_gain -= 1;
+ wlc_lcnphy_set_rx_gain_by_distribution(pi,
+ 0, 0, 2, 2,
+ (u16)
+ tia_gain, 1, 0);
+ udelay(500);
+
+ received_power =
+ wlc_lcnphy_measure_digital_power(pi, 2000);
+ if (received_power < rx_pwr_threshold)
+ break;
+ }
+ result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
+
+ wlc_lcnphy_stop_tx_tone(pi);
+
+ write_phy_reg(pi, 0x631, Core1TxControl_old);
+
+ write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
+ write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
+ write_phy_reg(pi, 0x4b0, rfoverride2_old);
+ write_phy_reg(pi, 0x4b1, rfoverride2val_old);
+ write_phy_reg(pi, 0x4f9, rfoverride3_old);
+ write_phy_reg(pi, 0x4fa, rfoverride3val_old);
+ write_phy_reg(pi, 0x938, rfoverride4_old);
+ write_phy_reg(pi, 0x939, rfoverride4val_old);
+ write_phy_reg(pi, 0x43b, afectrlovr_old);
+ write_phy_reg(pi, 0x43c, afectrlovrval_old);
+ write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+ write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
+
+ wlc_lcnphy_clear_trsw_override(pi);
+
+ mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+
+ for (i = 0; i < 11; i++)
+ write_radio_reg(pi, rxiq_cal_rf_reg[i],
+ values_to_save[i]);
+
+ if (tx_gain_override_old)
+ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
+ else
+ wlc_lcnphy_disable_tx_gain_override(pi);
+
+ wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+ wlc_lcnphy_rx_gain_override_enable(pi, false);
+ }
+
+cal_done:
+ kfree(ptr);
+ return result;
+}
+
+s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi)
+{
+ s8 index;
+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+ if (txpwrctrl_off(pi))
+ index = pi_lcn->lcnphy_current_index;
+ else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+ index = (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(
+ pi) / 2);
+ else
+ index = pi_lcn->lcnphy_current_index;
+ return index;
+}
+
void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel)
{
u16 afectrlovr, afectrlovrval;
@@ -1200,7 +1578,290 @@ wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi, bool enable)
wlapi_switch_macfreq(pi->sh->physhim, enable);
}
-void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, chanspec_t chanspec)
+static void
+wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec)
+{
+ u8 channel = CHSPEC_CHANNEL(chanspec);
+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+ if (channel == 14)
+ mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
+ else
+ mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
+
+ pi_lcn->lcnphy_bandedge_corr = 2;
+ if (channel == 1)
+ pi_lcn->lcnphy_bandedge_corr = 4;
+
+ if (channel == 1 || channel == 2 || channel == 3 ||
+ channel == 4 || channel == 9 ||
+ channel == 10 || channel == 11 || channel == 12) {
+ si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
+ si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
+ si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
+
+ si_pmu_pllupd(pi->sh->sih);
+ write_phy_reg(pi, 0x942, 0);
+ wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
+ pi_lcn->lcnphy_spurmod = 0;
+ mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
+
+ write_phy_reg(pi, 0x425, 0x5907);
+ } else {
+ si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
+ si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
+ si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
+
+ si_pmu_pllupd(pi->sh->sih);
+ write_phy_reg(pi, 0x942, 0);
+ wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
+
+ pi_lcn->lcnphy_spurmod = 0;
+ mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
+
+ write_phy_reg(pi, 0x425, 0x590a);
+ }
+
+ or_phy_reg(pi, 0x44a, 0x44);
+ write_phy_reg(pi, 0x44a, 0x80);
+}
+
+static void
+wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
+{
+ uint i;
+ const struct chan_info_2064_lcnphy *ci;
+ u8 rfpll_doubler = 0;
+ u8 pll_pwrup, pll_pwrup_ovr;
+ s32 qFxtal, qFref, qFvco, qFcal;
+ u8 d15, d16, f16, e44, e45;
+ u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
+ u16 loop_bw, d30, setCount;
+
+ u8 h29, h28_ten, e30, h30_ten, cp_current;
+ u16 g30, d28;
+
+ ci = &chan_info_2064_lcnphy[0];
+ rfpll_doubler = 1;
+
+ mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
+
+ write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
+ if (!rfpll_doubler) {
+ loop_bw = PLL_2064_LOOP_BW;
+ d30 = PLL_2064_D30;
+ } else {
+ loop_bw = PLL_2064_LOOP_BW_DOUBLER;
+ d30 = PLL_2064_D30_DOUBLER;
+ }
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
+ if (chan_info_2064_lcnphy[i].chan == channel)
+ break;
+
+ if (i >= ARRAY_SIZE(chan_info_2064_lcnphy))
+ return;
+
+ ci = &chan_info_2064_lcnphy[i];
+ }
+
+ write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
+
+ mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
+
+ mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
+
+ mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
+
+ mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
+ (ci->logen_rccr_rx) << 2);
+
+ mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
+
+ mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
+ (ci->pa_rxrf_lna2_freq_tune) << 4);
+
+ write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
+
+ pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
+ pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
+
+ or_radio_reg(pi, RADIO_2064_REG044, 0x07);
+
+ or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
+ e44 = 0;
+ e45 = 0;
+
+ fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
+ if (pi->xtalfreq > 26000000)
+ e44 = 1;
+ if (pi->xtalfreq > 52000000)
+ e45 = 1;
+ if (e44 == 0)
+ fcal_div = 1;
+ else if (e45 == 0)
+ fcal_div = 2;
+ else
+ fcal_div = 4;
+ fvco3 = (ci->freq * 3);
+ fref3 = 2 * fpfd;
+
+ qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
+ qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
+ qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
+ qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
+
+ write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
+
+ d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
+ write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
+ write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
+
+ d16 = (qFcal * 8 / (d15 + 1)) - 1;
+ write_radio_reg(pi, RADIO_2064_REG051, d16);
+
+ f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
+ setCount = f16 * 3 * (ci->freq) / 32 - 1;
+ mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
+ (u8) (setCount >> 8));
+
+ or_radio_reg(pi, RADIO_2064_REG053, 0x10);
+ write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
+
+ div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
+
+ div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
+ while (div_frac >= fref3) {
+ div_int++;
+ div_frac -= fref3;
+ }
+ div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
+
+ mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
+ (u8) (div_int >> 4));
+ mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
+ (u8) (div_int << 4));
+ mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
+ (u8) (div_frac >> 16));
+ write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
+ write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
+
+ write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
+
+ write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
+ write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
+ write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
+
+ h29 = LCN_BW_LMT / loop_bw;
+ d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
+ (fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
+ (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
+ + PLL_2064_LOW_END_KVCO;
+ h28_ten = (d28 * 10) / LCN_VCO_DIV;
+ e30 = (d30 - LCN_OFFSET) / LCN_FACT;
+ g30 = LCN_OFFSET + (e30 * LCN_FACT);
+ h30_ten = (g30 * 10) / LCN_CUR_DIV;
+ cp_current = ((LCN_CUR_LMT * h29 * LCN_MULT * 100) / h28_ten) / h30_ten;
+ mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
+
+ if (channel >= 1 && channel <= 5)
+ write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
+ else
+ write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
+ write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
+
+ mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
+ udelay(1);
+
+ wlc_2064_vco_cal(pi);
+
+ write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
+ write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+ write_radio_reg(pi, RADIO_2064_REG038, 3);
+ write_radio_reg(pi, RADIO_2064_REG091, 7);
+ }
+}
+
+static int
+wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type)
+{
+ s16 filt_index = -1;
+ int j;
+
+ u16 addr[] = {
+ 0x910,
+ 0x91e,
+ 0x91f,
+ 0x924,
+ 0x925,
+ 0x926,
+ 0x920,
+ 0x921,
+ 0x927,
+ 0x928,
+ 0x929,
+ 0x922,
+ 0x923,
+ 0x930,
+ 0x931,
+ 0x932
+ };
+
+ u16 addr_ofdm[] = {
+ 0x90f,
+ 0x900,
+ 0x901,
+ 0x906,
+ 0x907,
+ 0x908,
+ 0x902,
+ 0x903,
+ 0x909,
+ 0x90a,
+ 0x90b,
+ 0x904,
+ 0x905,
+ 0x90c,
+ 0x90d,
+ 0x90e
+ };
+
+ if (!is_ofdm) {
+ for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
+ if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
+ filt_index = (s16) j;
+ break;
+ }
+ }
+
+ if (filt_index != -1) {
+ for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, addr[j],
+ LCNPHY_txdigfiltcoeffs_cck
+ [filt_index][j + 1]);
+ }
+ } else {
+ for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
+ if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
+ filt_index = (s16) j;
+ break;
+ }
+ }
+
+ if (filt_index != -1) {
+ for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, addr_ofdm[j],
+ LCNPHY_txdigfiltcoeffs_ofdm
+ [filt_index][j + 1]);
+ }
+ }
+
+ return (filt_index != -1) ? 0 : -1;
+}
+
+void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
{
u8 channel = CHSPEC_CHANNEL(chanspec);
@@ -1211,10 +1872,8 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, chanspec_t chanspec)
or_phy_reg(pi, 0x44a, 0x44);
write_phy_reg(pi, 0x44a, 0x80);
- if (!NORADIO_ENAB(pi->pubpi)) {
- wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
- udelay(1000);
- }
+ wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
+ udelay(1000);
wlc_lcnphy_toggle_afe_pwdn(pi);
@@ -1237,35 +1896,13 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, chanspec_t chanspec)
}
-static void wlc_lcnphy_set_dac_gain(struct brcms_phy *pi, u16 dac_gain)
-{
- u16 dac_ctrl;
-
- dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
- dac_ctrl = dac_ctrl & 0xc7f;
- dac_ctrl = dac_ctrl | (dac_gain << 7);
- mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
-
-}
-
-static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable)
-{
- u16 bit = bEnable ? 1 : 0;
-
- mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
-
- mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
-
- mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
-}
-
static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi)
{
u16 pa_gain;
pa_gain = (read_phy_reg(pi, 0x4fb) &
LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
- LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
+ LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
return pa_gain;
}
@@ -1275,18 +1912,22 @@ static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi,
{
u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
- mod_phy_reg(pi, 0x4b5,
- (0xffff << 0),
- ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
- 0);
+ mod_phy_reg(
+ pi, 0x4b5,
+ (0xffff << 0),
+ ((target_gains->gm_gain) |
+ (target_gains->pga_gain << 8)) <<
+ 0);
mod_phy_reg(pi, 0x4fb,
(0x7fff << 0),
((target_gains->pad_gain) | (pa_gain << 8)) << 0);
- mod_phy_reg(pi, 0x4fc,
- (0xffff << 0),
- ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
- 0);
+ mod_phy_reg(
+ pi, 0x4fc,
+ (0xffff << 0),
+ ((target_gains->gm_gain) |
+ (target_gains->pga_gain << 8)) <<
+ 0);
mod_phy_reg(pi, 0x4fd,
(0x7fff << 0),
((target_gains->pad_gain) | (pa_gain << 8)) << 0);
@@ -1404,8 +2045,8 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- auxpga_vmid =
- (2 << 8) | (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
+ auxpga_vmid = (2 << 8) |
+ (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4;
auxpga_gain_temp = 2;
@@ -1531,10 +2172,9 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3);
- if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+ if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
mod_phy_reg(pi, 0x4d7,
(0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12);
- }
rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
@@ -1601,7 +2241,7 @@ void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi)
{
struct phytbl_info tab;
u32 rate_table[BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM +
- BRCMS_NUM_RATES_MCS_1_STREAM];
+ BRCMS_NUM_RATES_MCS_1_STREAM];
uint i, j;
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
return;
@@ -1694,34 +2334,28 @@ static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi)
index = FIXED_TXPWR;
- if (NORADIO_ENAB(pi->pubpi))
+ if (pi_lcn->lcnphy_tempsense_slope == 0)
return index;
- if (pi_lcn->lcnphy_tempsense_slope == 0) {
- return index;
- }
temp = (u16) wlc_lcnphy_tempsense(pi, 0);
meas_temp = LCNPHY_TEMPSENSE(temp);
- if (pi->tx_power_min != 0) {
+ if (pi->tx_power_min != 0)
delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min);
- } else {
+ else
delta_brd = 0;
- }
manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense);
temp_diff = manp - meas_temp;
if (temp_diff < 0) {
-
neg = 1;
-
temp_diff = -temp_diff;
}
delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192),
- (u32) (pi_lcn->
- lcnphy_tempsense_slope
- * 10), 0);
+ (u32) (pi_lcn->
+ lcnphy_tempsense_slope
+ * 10), 0);
if (neg)
delta_temp = -delta_temp;
@@ -1735,14 +2369,15 @@ static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi)
if (LCNREV_IS(pi->pubpi.phy_rev, 1))
tempcorrx = 4;
new_index =
- index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
+ index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
new_index += tempcorrx;
if (LCNREV_IS(pi->pubpi.phy_rev, 1))
index = 127;
- if (new_index < 0 || new_index > 126) {
+
+ if (new_index < 0 || new_index > 126)
return index;
- }
+
return new_index;
}
@@ -1792,7 +2427,7 @@ void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode)
mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0);
pi_lcn->lcnphy_tssi_tx_cnt =
- wlc_lcnphy_total_tx_frames(pi);
+ wlc_lcnphy_total_tx_frames(pi);
wlc_lcnphy_disable_tx_gain_override(pi);
pi_lcn->lcnphy_tx_power_idx_override = -1;
@@ -1805,11 +2440,105 @@ void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode)
index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index);
pi_lcn->lcnphy_current_index = (s8)
- ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
+ ((read_phy_reg(pi,
+ 0x4a9) &
+ 0xFF) / 2);
}
}
}
+static void
+wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save)
+{
+ u16 vmid;
+ int i;
+ for (i = 0; i < 20; i++)
+ values_to_save[i] =
+ read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
+
+ mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
+ mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
+
+ mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
+ mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
+
+ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+ mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+ mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+ if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+ and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
+ else
+ and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
+ or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
+
+ or_radio_reg(pi, RADIO_2064_REG036, 0x01);
+ or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
+ udelay(20);
+
+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
+ else
+ or_radio_reg(pi, RADIO_2064_REG03A, 1);
+ } else {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
+ else
+ or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
+ }
+
+ udelay(20);
+
+ write_radio_reg(pi, RADIO_2064_REG025, 0xF);
+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
+ else
+ mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
+ } else {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
+ else
+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
+ }
+
+ udelay(20);
+
+ write_radio_reg(pi, RADIO_2064_REG005, 0x8);
+ or_radio_reg(pi, RADIO_2064_REG112, 0x80);
+ udelay(20);
+
+ or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+ or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+ udelay(20);
+
+ or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+ or_radio_reg(pi, RADIO_2064_REG113, 0x10);
+ udelay(20);
+
+ write_radio_reg(pi, RADIO_2064_REG007, 0x1);
+ udelay(20);
+
+ vmid = 0x2A6;
+ mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
+ write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
+ or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+ udelay(20);
+
+ or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+ udelay(20);
+ write_radio_reg(pi, RADIO_2064_REG012, 0x02);
+ or_radio_reg(pi, RADIO_2064_REG112, 0x06);
+ write_radio_reg(pi, RADIO_2064_REG036, 0x11);
+ write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
+ write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
+ write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
+ write_radio_reg(pi, RADIO_2064_REG092, 0x15);
+}
+
static bool wlc_lcnphy_iqcal_wait(struct brcms_phy *pi)
{
uint delay_count = 0;
@@ -1826,6 +2555,20 @@ static bool wlc_lcnphy_iqcal_wait(struct brcms_phy *pi)
}
static void
+wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save)
+{
+ int i;
+
+ and_phy_reg(pi, 0x44c, 0x0 >> 11);
+
+ and_phy_reg(pi, 0x43b, 0xC);
+
+ for (i = 0; i < 20; i++)
+ write_radio_reg(pi, iqlo_loopback_rf_regs[i],
+ values_to_save[i]);
+}
+
+static void
wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
struct lcnphy_txgains *target_gains,
enum lcnphy_cal_mode cal_mode, bool keep_tone)
@@ -1837,20 +2580,23 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
int j;
u16 ncorr_override[5];
u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
- };
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000};
u16 commands_fullcal[] = {
- 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
+ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234
+ };
u16 commands_recal[] = {
- 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
+ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234
+ };
u16 command_nums_fullcal[] = {
- 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
+ 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97
+ };
u16 command_nums_recal[] = {
- 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
+ 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97
+ };
u16 *command_nums = command_nums_fullcal;
u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start;
@@ -1862,13 +2608,9 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
u16 *values_to_save;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
- if (NULL == values_to_save) {
+ if (NULL == values_to_save)
return;
- }
save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
@@ -1927,7 +2669,7 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
}
hash = (target_gains->gm_gain << 8) |
- (target_gains->pga_gain << 4) | (target_gains->pad_gain);
+ (target_gains->pga_gain << 4) | (target_gains->pad_gain);
band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
@@ -1936,11 +2678,11 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
cal_gains.gm_gain =
- tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
+ tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
cal_gains.pga_gain =
- tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
+ tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
cal_gains.pad_gain =
- tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
+ tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
memcpy(ncorr_override,
&tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
sizeof(ncorr_override));
@@ -1954,14 +2696,14 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
write_phy_reg(pi, 0x93d, 0xc0);
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
- (const void *)
lcnphy_iqcal_loft_gainladder,
ARRAY_SIZE(lcnphy_iqcal_loft_gainladder),
16, 0);
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
- (const void *)lcnphy_iqcal_ir_gainladder,
- ARRAY_SIZE(lcnphy_iqcal_ir_gainladder), 16,
+ lcnphy_iqcal_ir_gainladder,
+ ARRAY_SIZE(
+ lcnphy_iqcal_ir_gainladder), 16,
32);
if (pi->phy_tx_tone_freq) {
@@ -1985,13 +2727,12 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
command_num = command_nums[i];
if (ncorr_override[cal_type])
command_num =
- ncorr_override[cal_type] << 8 | (command_num &
- 0xff);
+ ncorr_override[cal_type] << 8 | (command_num &
+ 0xff);
write_phy_reg(pi, 0x452, command_num);
if ((cal_type == 3) || (cal_type == 4)) {
-
wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
&diq_start, 1, 16, 69);
@@ -2001,10 +2742,8 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
write_phy_reg(pi, 0x451, cal_cmds[i]);
- if (!wlc_lcnphy_iqcal_wait(pi)) {
-
+ if (!wlc_lcnphy_iqcal_wait(pi))
goto cleanup;
- }
wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
best_coeffs,
@@ -2013,16 +2752,15 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
best_coeffs,
ARRAY_SIZE(best_coeffs), 16, 64);
- if ((cal_type == 3) || (cal_type == 4)) {
+ if ((cal_type == 3) || (cal_type == 4))
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
&diq_start, 1, 16, 69);
- }
wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
pi_lcn->lcnphy_cal_results.
txiqlocal_bestcoeffs,
ARRAY_SIZE(pi_lcn->
- lcnphy_cal_results.
- txiqlocal_bestcoeffs),
+ lcnphy_cal_results.
+ txiqlocal_bestcoeffs),
16, 96);
}
@@ -2030,7 +2768,7 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
pi_lcn->lcnphy_cal_results.
txiqlocal_bestcoeffs,
ARRAY_SIZE(pi_lcn->lcnphy_cal_results.
- txiqlocal_bestcoeffs), 16, 96);
+ txiqlocal_bestcoeffs), 16, 96);
pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true;
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
@@ -2041,7 +2779,7 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
&pi_lcn->lcnphy_cal_results.
txiqlocal_bestcoeffs[5], 2, 16, 85);
- cleanup:
+cleanup:
wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save);
kfree(values_to_save);
@@ -2071,14 +2809,14 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112);
u16 SAVE_jtag_bb_afe_switch =
- read_radio_reg(pi, RADIO_2064_REG007) & 1;
+ read_radio_reg(pi, RADIO_2064_REG007) & 1;
u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
idleTssi = read_phy_reg(pi, 0x4ab);
suspend =
- (0 ==
- (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) &
- MCTL_EN_MAC));
+ (0 ==
+ (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) &
+ MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
@@ -2136,7 +2874,7 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
struct phytbl_info tab;
u32 val;
u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
- save_reg112;
+ save_reg112;
u16 values_to_save[14];
s8 index;
int i;
@@ -2152,8 +2890,7 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
for (i = 0; i < 14; i++)
values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
- suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
@@ -2236,7 +2973,7 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
auxpga_gain = 2;
}
auxpga_vmid =
- (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
+ (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
@@ -2280,17 +3017,10 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
struct brcms_phy *pi = (struct brcms_phy *) ppi;
suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
- if (NORADIO_ENAB(pi->pubpi)) {
- wlc_lcnphy_set_bbmult(pi, 0x30);
- if (!suspend)
- wlapi_enable_mac(pi->sh->physhim);
- return;
- }
-
if (!pi->hwpwrctrl_capable) {
if (CHSPEC_IS2G(pi->radio_chanspec)) {
tx_gains.gm_gain = 4;
@@ -2382,26 +3112,6 @@ wlc_lcnphy_get_radio_loft(struct brcms_phy *pi,
*fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
}
-static void
-wlc_lcnphy_get_tx_gain(struct brcms_phy *pi, struct lcnphy_txgains *gains)
-{
- u16 dac_gain;
-
- dac_gain = read_phy_reg(pi, 0x439) >> 0;
- gains->dac_gain = (dac_gain & 0x380) >> 7;
-
- {
- u16 rfgain0, rfgain1;
-
- rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
- rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
-
- gains->gm_gain = rfgain0 & 0xff;
- gains->pga_gain = (rfgain0 >> 8) & 0xff;
- gains->pad_gain = rfgain1 & 0xff;
- }
-}
-
void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b)
{
struct phytbl_info tab;
@@ -2489,16 +3199,6 @@ void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index)
}
}
-static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx, bool rx)
-{
-
- mod_phy_reg(pi, 0x44d,
- (0x1 << 1) |
- (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
-
- or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
-}
-
static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi)
{
u32 j;
@@ -2518,67 +3218,6 @@ static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi)
return;
}
-static void
-wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
- u16 trsw,
- u16 ext_lna,
- u16 biq2,
- u16 biq1,
- u16 tia, u16 lna2, u16 lna1)
-{
- u16 gain0_15, gain16_19;
-
- gain16_19 = biq2 & 0xf;
- gain0_15 = ((biq1 & 0xf) << 12) |
- ((tia & 0xf) << 8) |
- ((lna2 & 0x3) << 6) |
- ((lna2 & 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
-
- mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
- mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
- mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
-
- if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
- mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
- mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
- } else {
- mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
-
- mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
-
- mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
- }
-
- mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
-
-}
-
-static void
-wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi, bool enable)
-{
- u16 ebit = enable ? 1 : 0;
-
- mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
-
- mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
-
- if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
- mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
- mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
- mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
- mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
- } else {
- mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
- mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
- mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
- mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
- }
-}
-
void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable)
{
if (!bEnable) {
@@ -2589,9 +3228,9 @@ void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable)
and_phy_reg(pi, 0x44c,
~(u16) ((0x1 << 3) |
- (0x1 << 5) |
- (0x1 << 12) |
- (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+ (0x1 << 5) |
+ (0x1 << 12) |
+ (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
and_phy_reg(pi, 0x44d,
~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
@@ -2701,7 +3340,8 @@ void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode)
mod_phy_reg((pi), 0x410,
(0x1 << 6) |
(0x1 << 5),
- ((CHSPEC_IS2G(pi->radio_chanspec)) ? (!mode) : 0) <<
+ ((CHSPEC_IS2G(
+ pi->radio_chanspec)) ? (!mode) : 0) <<
6 | (!mode) << 5);
mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
}
@@ -2714,8 +3354,8 @@ wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val,
u8 phy_bw;
u16 num_samps, t, k;
u32 bw;
- fixed theta = 0, rot = 0;
- cs32 tone_samp;
+ s32 theta = 0, rot = 0;
+ struct cordic_iq tone_samp;
u32 data_buf[64];
u16 i_samp, q_samp;
struct phytbl_info tab;
@@ -2737,18 +3377,18 @@ wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val,
k = 1;
do {
bw = phy_bw * 1000 * k;
- num_samps = bw / ABS(f_kHz);
+ num_samps = bw / abs(f_kHz);
k++;
- } while ((num_samps * (u32) (ABS(f_kHz))) != bw);
+ } while ((num_samps * (u32) (abs(f_kHz))) != bw);
} else
num_samps = 2;
- rot = FIXED((f_kHz * 36) / phy_bw) / 100;
+ rot = ((f_kHz * 36) / phy_bw) / 100;
theta = 0;
for (t = 0; t < num_samps; t++) {
- wlc_phy_cordic(theta, &tone_samp);
+ tone_samp = cordic_calc_iq(theta);
theta += rot;
@@ -2802,10 +3442,359 @@ void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi)
wlc_lcnphy_deaf_mode(pi, false);
}
-static void wlc_lcnphy_clear_trsw_override(struct brcms_phy *pi)
+static void
+wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y)
{
+ u16 di0dq0;
+ u16 x, y, data_rf;
+ int k;
+ switch (cal_type) {
+ case 0:
+ wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
+ break;
+ case 2:
+ di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
+ wlc_lcnphy_set_tx_locc(pi, di0dq0);
+ break;
+ case 3:
+ k = wlc_lcnphy_calc_floor(coeff_x, 0);
+ y = 8 + k;
+ k = wlc_lcnphy_calc_floor(coeff_x, 1);
+ x = 8 - k;
+ data_rf = (x * 16 + y);
+ write_radio_reg(pi, RADIO_2064_REG089, data_rf);
+ k = wlc_lcnphy_calc_floor(coeff_y, 0);
+ y = 8 + k;
+ k = wlc_lcnphy_calc_floor(coeff_y, 1);
+ x = 8 - k;
+ data_rf = (x * 16 + y);
+ write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
+ break;
+ case 4:
+ k = wlc_lcnphy_calc_floor(coeff_x, 0);
+ y = 8 + k;
+ k = wlc_lcnphy_calc_floor(coeff_x, 1);
+ x = 8 - k;
+ data_rf = (x * 16 + y);
+ write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
+ k = wlc_lcnphy_calc_floor(coeff_y, 0);
+ y = 8 + k;
+ k = wlc_lcnphy_calc_floor(coeff_y, 1);
+ x = 8 - k;
+ data_rf = (x * 16 + y);
+ write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
+ break;
+ }
+}
- and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
+static struct lcnphy_unsign16_struct
+wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type)
+{
+ u16 a, b, didq;
+ u8 di0, dq0, ei, eq, fi, fq;
+ struct lcnphy_unsign16_struct cc;
+ cc.re = 0;
+ cc.im = 0;
+ switch (cal_type) {
+ case 0:
+ wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
+ cc.re = a;
+ cc.im = b;
+ break;
+ case 2:
+ didq = wlc_lcnphy_get_tx_locc(pi);
+ di0 = (((didq & 0xff00) << 16) >> 24);
+ dq0 = (((didq & 0x00ff) << 24) >> 24);
+ cc.re = (u16) di0;
+ cc.im = (u16) dq0;
+ break;
+ case 3:
+ wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+ cc.re = (u16) ei;
+ cc.im = (u16) eq;
+ break;
+ case 4:
+ wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+ cc.re = (u16) fi;
+ cc.im = (u16) fq;
+ break;
+ }
+ return cc;
+}
+
+static void
+wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
+ s16 *ptr, int mode)
+{
+ u32 curval1, curval2, stpptr, curptr, strptr, val;
+ u16 sslpnCalibClkEnCtrl, timer;
+ u16 old_sslpnCalibClkEnCtrl;
+ s16 imag, real;
+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+ timer = 0;
+ old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+
+ curval1 = R_REG(&pi->regs->psm_corectlsts);
+ ptr[130] = 0;
+ W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1));
+
+ W_REG(&pi->regs->smpl_clct_strptr, 0x7E00);
+ W_REG(&pi->regs->smpl_clct_stpptr, 0x8000);
+ udelay(20);
+ curval2 = R_REG(&pi->regs->psm_phy_hdr_param);
+ W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30);
+
+ write_phy_reg(pi, 0x555, 0x0);
+ write_phy_reg(pi, 0x5a6, 0x5);
+
+ write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
+ write_phy_reg(pi, 0x5cf, 3);
+ write_phy_reg(pi, 0x5a5, 0x3);
+ write_phy_reg(pi, 0x583, 0x0);
+ write_phy_reg(pi, 0x584, 0x0);
+ write_phy_reg(pi, 0x585, 0x0fff);
+ write_phy_reg(pi, 0x586, 0x0000);
+
+ write_phy_reg(pi, 0x580, 0x4501);
+
+ sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+ write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
+ stpptr = R_REG(&pi->regs->smpl_clct_stpptr);
+ curptr = R_REG(&pi->regs->smpl_clct_curptr);
+ do {
+ udelay(10);
+ curptr = R_REG(&pi->regs->smpl_clct_curptr);
+ timer++;
+ } while ((curptr != stpptr) && (timer < 500));
+
+ W_REG(&pi->regs->psm_phy_hdr_param, 0x2);
+ strptr = 0x7E00;
+ W_REG(&pi->regs->tplatewrptr, strptr);
+ while (strptr < 0x8000) {
+ val = R_REG(&pi->regs->tplatewrdata);
+ imag = ((val >> 16) & 0x3ff);
+ real = ((val) & 0x3ff);
+ if (imag > 511)
+ imag -= 1024;
+
+ if (real > 511)
+ real -= 1024;
+
+ if (pi_lcn->lcnphy_iqcal_swp_dis)
+ ptr[(strptr - 0x7E00) / 4] = real;
+ else
+ ptr[(strptr - 0x7E00) / 4] = imag;
+
+ if (clip_detect_algo) {
+ if (imag > thresh || imag < -thresh) {
+ strptr = 0x8000;
+ ptr[130] = 1;
+ }
+ }
+
+ strptr += 4;
+ }
+
+ write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+ W_REG(&pi->regs->psm_phy_hdr_param, curval2);
+ W_REG(&pi->regs->psm_corectlsts, curval1);
+}
+
+static void
+wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels,
+ int step_size_lg2)
+{
+ const struct lcnphy_spb_tone *phy_c1;
+ struct lcnphy_spb_tone phy_c2;
+ struct lcnphy_unsign16_struct phy_c3;
+ int phy_c4, phy_c5, k, l, j, phy_c6;
+ u16 phy_c7, phy_c8, phy_c9;
+ s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
+ s16 *ptr, phy_c17;
+ s32 phy_c18, phy_c19;
+ u32 phy_c20, phy_c21;
+ bool phy_c22, phy_c23, phy_c24, phy_c25;
+ u16 phy_c26, phy_c27;
+ u16 phy_c28, phy_c29, phy_c30;
+ u16 phy_c31;
+ u16 *phy_c32;
+ phy_c21 = 0;
+ phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
+ ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+ if (NULL == ptr)
+ return;
+
+ phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
+ if (NULL == phy_c32) {
+ kfree(ptr);
+ return;
+ }
+ phy_c26 = read_phy_reg(pi, 0x6da);
+ phy_c27 = read_phy_reg(pi, 0x6db);
+ phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
+ write_phy_reg(pi, 0x93d, 0xC0);
+
+ wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
+ write_phy_reg(pi, 0x6da, 0xffff);
+ or_phy_reg(pi, 0x6db, 0x3);
+
+ wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
+ udelay(500);
+ phy_c28 = read_phy_reg(pi, 0x938);
+ phy_c29 = read_phy_reg(pi, 0x4d7);
+ phy_c30 = read_phy_reg(pi, 0x4d8);
+ or_phy_reg(pi, 0x938, 0x1 << 2);
+ or_phy_reg(pi, 0x4d7, 0x1 << 2);
+ or_phy_reg(pi, 0x4d7, 0x1 << 3);
+ mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
+ or_phy_reg(pi, 0x4d8, 1 << 0);
+ or_phy_reg(pi, 0x4d8, 1 << 1);
+ mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
+ mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
+ phy_c1 = &lcnphy_spb_tone_3750[0];
+ phy_c4 = 32;
+
+ if (num_levels == 0) {
+ if (cal_type != 0)
+ num_levels = 4;
+ else
+ num_levels = 9;
+ }
+ if (step_size_lg2 == 0) {
+ if (cal_type != 0)
+ step_size_lg2 = 3;
+ else
+ step_size_lg2 = 8;
+ }
+
+ phy_c7 = (1 << step_size_lg2);
+ phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
+ phy_c15 = (s16) phy_c3.re;
+ phy_c16 = (s16) phy_c3.im;
+ if (cal_type == 2) {
+ if (phy_c3.re > 127)
+ phy_c15 = phy_c3.re - 256;
+ if (phy_c3.im > 127)
+ phy_c16 = phy_c3.im - 256;
+ }
+ wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+ udelay(20);
+ for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
+ phy_c23 = 1;
+ phy_c22 = 0;
+ switch (cal_type) {
+ case 0:
+ phy_c10 = 511;
+ break;
+ case 2:
+ phy_c10 = 127;
+ break;
+ case 3:
+ phy_c10 = 15;
+ break;
+ case 4:
+ phy_c10 = 15;
+ break;
+ }
+
+ phy_c9 = read_phy_reg(pi, 0x93d);
+ phy_c9 = 2 * phy_c9;
+ phy_c24 = 0;
+ phy_c5 = 7;
+ phy_c25 = 1;
+ while (1) {
+ write_radio_reg(pi, RADIO_2064_REG026,
+ (phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
+ udelay(50);
+ phy_c22 = 0;
+ ptr[130] = 0;
+ wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
+ if (ptr[130] == 1)
+ phy_c22 = 1;
+ if (phy_c22)
+ phy_c5 -= 1;
+ if ((phy_c22 != phy_c24) && (!phy_c25))
+ break;
+ if (!phy_c22)
+ phy_c5 += 1;
+ if (phy_c5 <= 0 || phy_c5 >= 7)
+ break;
+ phy_c24 = phy_c22;
+ phy_c25 = 0;
+ }
+
+ if (phy_c5 < 0)
+ phy_c5 = 0;
+ else if (phy_c5 > 7)
+ phy_c5 = 7;
+
+ for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
+ for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
+ phy_c11 = phy_c15 + k;
+ phy_c12 = phy_c16 + l;
+
+ if (phy_c11 < -phy_c10)
+ phy_c11 = -phy_c10;
+ else if (phy_c11 > phy_c10)
+ phy_c11 = phy_c10;
+ if (phy_c12 < -phy_c10)
+ phy_c12 = -phy_c10;
+ else if (phy_c12 > phy_c10)
+ phy_c12 = phy_c10;
+ wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
+ phy_c12);
+ udelay(20);
+ wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
+
+ phy_c18 = 0;
+ phy_c19 = 0;
+ for (j = 0; j < 128; j++) {
+ if (cal_type != 0)
+ phy_c6 = j % phy_c4;
+ else
+ phy_c6 = (2 * j) % phy_c4;
+
+ phy_c2.re = phy_c1[phy_c6].re;
+ phy_c2.im = phy_c1[phy_c6].im;
+ phy_c17 = ptr[j];
+ phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
+ phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
+ }
+
+ phy_c18 = phy_c18 >> 10;
+ phy_c19 = phy_c19 >> 10;
+ phy_c20 = ((phy_c18 * phy_c18) +
+ (phy_c19 * phy_c19));
+
+ if (phy_c23 || phy_c20 < phy_c21) {
+ phy_c21 = phy_c20;
+ phy_c13 = phy_c11;
+ phy_c14 = phy_c12;
+ }
+ phy_c23 = 0;
+ }
+ }
+ phy_c23 = 1;
+ phy_c15 = phy_c13;
+ phy_c16 = phy_c14;
+ phy_c7 = phy_c7 >> 1;
+ wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+ udelay(20);
+ }
+ goto cleanup;
+cleanup:
+ wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
+ wlc_lcnphy_stop_tx_tone(pi);
+ write_phy_reg(pi, 0x6da, phy_c26);
+ write_phy_reg(pi, 0x6db, phy_c27);
+ write_phy_reg(pi, 0x938, phy_c28);
+ write_phy_reg(pi, 0x4d7, phy_c29);
+ write_phy_reg(pi, 0x4d8, phy_c30);
+ write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
+
+ kfree(phy_c32);
+ kfree(ptr);
}
void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b)
@@ -2824,6 +3813,28 @@ void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b)
*b = iqcc[1];
}
+static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi)
+{
+ struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
+
+ wlc_lcnphy_set_cc(pi, 0, 0, 0);
+ wlc_lcnphy_set_cc(pi, 2, 0, 0);
+ wlc_lcnphy_set_cc(pi, 3, 0, 0);
+ wlc_lcnphy_set_cc(pi, 4, 0, 0);
+
+ wlc_lcnphy_a1(pi, 4, 0, 0);
+ wlc_lcnphy_a1(pi, 3, 0, 0);
+ wlc_lcnphy_a1(pi, 2, 3, 2);
+ wlc_lcnphy_a1(pi, 0, 5, 8);
+ wlc_lcnphy_a1(pi, 2, 2, 1);
+ wlc_lcnphy_a1(pi, 0, 4, 3);
+
+ iqcc0 = wlc_lcnphy_get_cc(pi, 0);
+ locc2 = wlc_lcnphy_get_cc(pi, 2);
+ locc3 = wlc_lcnphy_get_cc(pi, 3);
+ locc4 = wlc_lcnphy_get_cc(pi, 4);
+}
+
u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi)
{
struct phytbl_info tab;
@@ -2878,12 +3889,11 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
lcnphy_recal ? LCNPHY_CAL_RECAL :
LCNPHY_CAL_FULL), false);
} else {
-
wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
}
wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
- if ((ABS((s8) fi0) == 15) && (ABS((s8) fq0) == 15)) {
+ if ((abs((s8) fi0) == 15) && (abs((s8) fq0) == 15)) {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
target_gains.gm_gain = 255;
target_gains.pga_gain = 255;
@@ -2905,10 +3915,8 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
LCNPHY_CAL_FULL, false);
} else {
-
wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
}
-
}
wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
@@ -2927,7 +3935,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
wlc_lcnphy_read_table(pi, &tab);
val = (val & 0xfff00000) |
- ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
+ ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
wlc_lcnphy_write_table(pi, &tab);
val = didq;
@@ -2959,13 +3967,10 @@ s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode)
s16 avg = 0;
bool suspend = 0;
- if (NORADIO_ENAB(pi->pubpi))
- return -1;
-
if (mode == 1) {
suspend =
- (0 ==
- (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 ==
+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
@@ -3006,13 +4011,10 @@ u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode)
u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- if (NORADIO_ENAB(pi->pubpi))
- return -1;
-
if (mode == 1) {
suspend =
- (0 ==
- (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 ==
+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
@@ -3063,8 +4065,9 @@ s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode)
{
s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
degree =
- ((degree << 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
- / LCN_TEMPSENSE_DEN;
+ ((degree <<
+ 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
+ / LCN_TEMPSENSE_DEN;
return (s8) degree;
}
@@ -3074,13 +4077,10 @@ s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode)
s32 avg = 0;
bool suspend = 0;
- if (NORADIO_ENAB(pi->pubpi))
- return -1;
-
if (mode == 1) {
suspend =
- (0 ==
- (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 ==
+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
@@ -3093,9 +4093,8 @@ s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode)
else
avg = (s32) vbatsenseval;
- avg =
- (avg * LCN_VBAT_SCALE_NOM +
- (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
+ avg = (avg * LCN_VBAT_SCALE_NOM +
+ (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
if (mode == 1) {
if (!suspend)
@@ -3118,312 +4117,8 @@ static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode)
wlc_lcnphy_toggle_afe_pwdn(pi);
}
-static bool
-wlc_lcnphy_rx_iq_est(struct brcms_phy *pi,
- u16 num_samps,
- u8 wait_time, struct lcnphy_iq_est *iq_est)
-{
- int wait_count = 0;
- bool result = true;
- u8 phybw40;
- phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
- mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
-
- mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
-
- mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
-
- mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
-
- mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
-
- mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
-
- while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
-
- if (wait_count > (10 * 500)) {
- result = false;
- goto cleanup;
- }
- udelay(100);
- wait_count++;
- }
-
- iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
- (u32) read_phy_reg(pi, 0x484);
- iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
- (u32) read_phy_reg(pi, 0x486);
- iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
- (u32) read_phy_reg(pi, 0x488);
-
- cleanup:
- mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
-
- mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
-
- return result;
-}
-
-static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps)
-{
-#define LCNPHY_MIN_RXIQ_PWR 2
- bool result;
- u16 a0_new, b0_new;
- struct lcnphy_iq_est iq_est = { 0, 0, 0 };
- s32 a, b, temp;
- s16 iq_nbits, qq_nbits, arsh, brsh;
- s32 iq;
- u32 ii, qq;
- struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
-
- a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
- b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
- mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
-
- mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
-
- wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
-
- result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
- if (!result)
- goto cleanup;
-
- iq = (s32) iq_est.iq_prod;
- ii = iq_est.i_pwr;
- qq = iq_est.q_pwr;
-
- if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
- result = false;
- goto cleanup;
- }
-
- iq_nbits = wlc_phy_nbits(iq);
- qq_nbits = wlc_phy_nbits(qq);
-
- arsh = 10 - (30 - iq_nbits);
- if (arsh >= 0) {
- a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
- temp = (s32) (ii >> arsh);
- if (temp == 0) {
- return false;
- }
- } else {
- a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
- temp = (s32) (ii << -arsh);
- if (temp == 0) {
- return false;
- }
- }
- a /= temp;
- brsh = qq_nbits - 31 + 20;
- if (brsh >= 0) {
- b = (qq << (31 - qq_nbits));
- temp = (s32) (ii >> brsh);
- if (temp == 0) {
- return false;
- }
- } else {
- b = (qq << (31 - qq_nbits));
- temp = (s32) (ii << -brsh);
- if (temp == 0) {
- return false;
- }
- }
- b /= temp;
- b -= a * a;
- b = (s32) int_sqrt((unsigned long) b);
- b -= (1 << 10);
- a0_new = (u16) (a & 0x3ff);
- b0_new = (u16) (b & 0x3ff);
- cleanup:
-
- wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
-
- mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
-
- mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
-
- pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
- pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
-
- return result;
-}
-
-static bool
-wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
- const struct lcnphy_rx_iqcomp *iqcomp,
- int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
- int tx_gain_idx)
-{
- struct lcnphy_txgains old_gains;
- u16 tx_pwr_ctrl;
- u8 tx_gain_index_old = 0;
- bool result = false, tx_gain_override_old = false;
- u16 i, Core1TxControl_old, RFOverride0_old,
- RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
- rfoverride3_old, rfoverride3val_old, rfoverride4_old,
- rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
- int tia_gain;
- u32 received_power, rx_pwr_threshold;
- u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
- u16 values_to_save[11];
- s16 *ptr;
- struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
-
- ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
- if (NULL == ptr) {
- return false;
- }
- if (module == 2) {
- while (iqcomp_sz--) {
- if (iqcomp[iqcomp_sz].chan ==
- CHSPEC_CHANNEL(pi->radio_chanspec)) {
-
- wlc_lcnphy_set_rx_iq_comp(pi,
- (u16)
- iqcomp[iqcomp_sz].a,
- (u16)
- iqcomp[iqcomp_sz].b);
- result = true;
- break;
- }
- }
- goto cal_done;
- }
-
- if (module == 1) {
-
- tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
- wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
- for (i = 0; i < 11; i++) {
- values_to_save[i] =
- read_radio_reg(pi, rxiq_cal_rf_reg[i]);
- }
- Core1TxControl_old = read_phy_reg(pi, 0x631);
-
- or_phy_reg(pi, 0x631, 0x0015);
-
- RFOverride0_old = read_phy_reg(pi, 0x44c);
- RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
- rfoverride2_old = read_phy_reg(pi, 0x4b0);
- rfoverride2val_old = read_phy_reg(pi, 0x4b1);
- rfoverride3_old = read_phy_reg(pi, 0x4f9);
- rfoverride3val_old = read_phy_reg(pi, 0x4fa);
- rfoverride4_old = read_phy_reg(pi, 0x938);
- rfoverride4val_old = read_phy_reg(pi, 0x939);
- afectrlovr_old = read_phy_reg(pi, 0x43b);
- afectrlovrval_old = read_phy_reg(pi, 0x43c);
- old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
- old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
-
- tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
- if (tx_gain_override_old) {
- wlc_lcnphy_get_tx_gain(pi, &old_gains);
- tx_gain_index_old = pi_lcn->lcnphy_current_index;
- }
-
- wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
-
- mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
- mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
-
- mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
- mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
-
- write_radio_reg(pi, RADIO_2064_REG116, 0x06);
- write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
- write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
- write_radio_reg(pi, RADIO_2064_REG098, 0x03);
- write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
- mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
- write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
- write_radio_reg(pi, RADIO_2064_REG114, 0x01);
- write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
- write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
-
- mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
- mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
- mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
- mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
- mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
- mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
- mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
- mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
- mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
- mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
-
- mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
- mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
-
- wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
- write_phy_reg(pi, 0x6da, 0xffff);
- or_phy_reg(pi, 0x6db, 0x3);
- wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
- wlc_lcnphy_rx_gain_override_enable(pi, true);
-
- tia_gain = 8;
- rx_pwr_threshold = 950;
- while (tia_gain > 0) {
- tia_gain -= 1;
- wlc_lcnphy_set_rx_gain_by_distribution(pi,
- 0, 0, 2, 2,
- (u16)
- tia_gain, 1, 0);
- udelay(500);
-
- received_power =
- wlc_lcnphy_measure_digital_power(pi, 2000);
- if (received_power < rx_pwr_threshold)
- break;
- }
- result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
-
- wlc_lcnphy_stop_tx_tone(pi);
-
- write_phy_reg(pi, 0x631, Core1TxControl_old);
-
- write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
- write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
- write_phy_reg(pi, 0x4b0, rfoverride2_old);
- write_phy_reg(pi, 0x4b1, rfoverride2val_old);
- write_phy_reg(pi, 0x4f9, rfoverride3_old);
- write_phy_reg(pi, 0x4fa, rfoverride3val_old);
- write_phy_reg(pi, 0x938, rfoverride4_old);
- write_phy_reg(pi, 0x939, rfoverride4val_old);
- write_phy_reg(pi, 0x43b, afectrlovr_old);
- write_phy_reg(pi, 0x43c, afectrlovrval_old);
- write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
- write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
-
- wlc_lcnphy_clear_trsw_override(pi);
-
- mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
-
- for (i = 0; i < 11; i++) {
- write_radio_reg(pi, rxiq_cal_rf_reg[i],
- values_to_save[i]);
- }
-
- if (tx_gain_override_old) {
- wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
- } else
- wlc_lcnphy_disable_tx_gain_override(pi);
- wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
-
- wlc_lcnphy_rx_gain_override_enable(pi, false);
- }
-
- cal_done:
- kfree(ptr);
- return result;
-}
-
static void wlc_lcnphy_temp_adj(struct brcms_phy *pi)
{
- if (NORADIO_ENAB(pi->pubpi))
- return;
}
static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi)
@@ -3433,7 +4128,7 @@ static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi)
u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_deaf_mode(pi, true);
@@ -3463,24 +4158,21 @@ static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi)
s32 tssi, pwr, maxtargetpwr, mintargetpwr;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
pi->phy_lastcal = pi->sh->now;
pi->phy_forcecal = false;
full_cal =
- (pi_lcn->lcnphy_full_cal_channel !=
- CHSPEC_CHANNEL(pi->radio_chanspec));
+ (pi_lcn->lcnphy_full_cal_channel !=
+ CHSPEC_CHANNEL(pi->radio_chanspec));
pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
index = pi_lcn->lcnphy_current_index;
suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend) {
-
wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
wlapi_suspend_mac_and_wait(pi->sh->physhim);
}
+
wlc_lcnphy_deaf_mode(pi, true);
wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
@@ -3531,7 +4223,6 @@ void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode)
switch (mode) {
case PHY_PERICAL_CHAN:
-
break;
case PHY_FULLCAL:
wlc_lcnphy_periodic_cal(pi);
@@ -3558,7 +4249,7 @@ void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode)
case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
wlc_lcnphy_tx_power_adjustment(
- (struct brcms_phy_pub *) pi);
+ (struct brcms_phy_pub *) pi);
break;
}
}
@@ -3571,7 +4262,7 @@ void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr)
if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
(status & (0x1 << 15))) {
*ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
- >> 0) >> 1);
+ >> 0) >> 1);
if (wlc_phy_tpc_isenabled_lcnphy(pi))
cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
@@ -3591,59 +4282,6 @@ void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi)
}
-static void
-wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, chanspec_t chanspec)
-{
- u8 channel = CHSPEC_CHANNEL(chanspec);
- struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
-
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
- if (channel == 14) {
- mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
-
- } else {
- mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
-
- }
- pi_lcn->lcnphy_bandedge_corr = 2;
- if (channel == 1)
- pi_lcn->lcnphy_bandedge_corr = 4;
-
- if (channel == 1 || channel == 2 || channel == 3 ||
- channel == 4 || channel == 9 ||
- channel == 10 || channel == 11 || channel == 12) {
- si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
- si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
- si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
-
- si_pmu_pllupd(pi->sh->sih);
- write_phy_reg(pi, 0x942, 0);
- wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
- pi_lcn->lcnphy_spurmod = 0;
- mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
-
- write_phy_reg(pi, 0x425, 0x5907);
- } else {
- si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
- si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
- si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
-
- si_pmu_pllupd(pi->sh->sih);
- write_phy_reg(pi, 0x942, 0);
- wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
-
- pi_lcn->lcnphy_spurmod = 0;
- mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
-
- write_phy_reg(pi, 0x425, 0x590a);
- }
-
- or_phy_reg(pi, 0x44a, 0x44);
- write_phy_reg(pi, 0x44a, 0x80);
-}
-
void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi)
{
s8 index;
@@ -3651,570 +4289,21 @@ void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi)
struct brcms_phy *pi = (struct brcms_phy *) ppi;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
- if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && SAVE_txpwrctrl) {
+ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
+ SAVE_txpwrctrl) {
index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
index2 = (u16) (index * 2);
mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
- pi_lcn->lcnphy_current_index = (s8)
- ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
- }
-}
-
-static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b)
-{
- mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
-
- mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
-
- mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
-
- mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
-
- mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
-
- mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
-
-}
-
-void wlc_phy_init_lcnphy(struct brcms_phy *pi)
-{
- u8 phybw40;
- struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
- pi_lcn->lcnphy_cal_counter = 0;
- pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
-
- or_phy_reg(pi, 0x44a, 0x80);
- and_phy_reg(pi, 0x44a, 0x7f);
-
- wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
-
- write_phy_reg(pi, 0x60a, 160);
-
- write_phy_reg(pi, 0x46a, 25);
-
- wlc_lcnphy_baseband_init(pi);
-
- wlc_lcnphy_radio_init(pi);
-
- if (CHSPEC_IS2G(pi->radio_chanspec))
- wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi);
-
- wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
-
- si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
-
- si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
-
- if ((pi->sh->boardflags & BFL_FEM)
- && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
- wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
-
- wlc_lcnphy_agc_temp_init(pi);
-
- wlc_lcnphy_temp_adj(pi);
-
- mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
-
- udelay(100);
- mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
-
- wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
- pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
- wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
-}
-
-static void
-wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save)
-{
- u16 vmid;
- int i;
- for (i = 0; i < 20; i++) {
- values_to_save[i] =
- read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
- }
-
- mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
- mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
-
- mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
- mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
-
- mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
- mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
-
- mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
- mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
-
- if (LCNREV_IS(pi->pubpi.phy_rev, 2))
- and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
- else
- and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
- or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
-
- or_radio_reg(pi, RADIO_2064_REG036, 0x01);
- or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
- udelay(20);
-
- if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
- if (CHSPEC_IS5G(pi->radio_chanspec))
- mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
- else
- or_radio_reg(pi, RADIO_2064_REG03A, 1);
- } else {
- if (CHSPEC_IS5G(pi->radio_chanspec))
- mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
- else
- or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
- }
-
- udelay(20);
-
- write_radio_reg(pi, RADIO_2064_REG025, 0xF);
- if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
- if (CHSPEC_IS5G(pi->radio_chanspec))
- mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
- else
- mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
- } else {
- if (CHSPEC_IS5G(pi->radio_chanspec))
- mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
- else
- mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
- }
-
- udelay(20);
-
- write_radio_reg(pi, RADIO_2064_REG005, 0x8);
- or_radio_reg(pi, RADIO_2064_REG112, 0x80);
- udelay(20);
-
- or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
- or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
- udelay(20);
-
- or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
- or_radio_reg(pi, RADIO_2064_REG113, 0x10);
- udelay(20);
-
- write_radio_reg(pi, RADIO_2064_REG007, 0x1);
- udelay(20);
-
- vmid = 0x2A6;
- mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
- write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
- or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
- udelay(20);
-
- or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
- udelay(20);
- write_radio_reg(pi, RADIO_2064_REG012, 0x02);
- or_radio_reg(pi, RADIO_2064_REG112, 0x06);
- write_radio_reg(pi, RADIO_2064_REG036, 0x11);
- write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
- write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
- write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
- write_radio_reg(pi, RADIO_2064_REG092, 0x15);
-}
-
-static void
-wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
- s16 *ptr, int mode)
-{
- u32 curval1, curval2, stpptr, curptr, strptr, val;
- u16 sslpnCalibClkEnCtrl, timer;
- u16 old_sslpnCalibClkEnCtrl;
- s16 imag, real;
- struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
-
- timer = 0;
- old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-
- curval1 = R_REG(&pi->regs->psm_corectlsts);
- ptr[130] = 0;
- W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1));
-
- W_REG(&pi->regs->smpl_clct_strptr, 0x7E00);
- W_REG(&pi->regs->smpl_clct_stpptr, 0x8000);
- udelay(20);
- curval2 = R_REG(&pi->regs->psm_phy_hdr_param);
- W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30);
-
- write_phy_reg(pi, 0x555, 0x0);
- write_phy_reg(pi, 0x5a6, 0x5);
-
- write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
- write_phy_reg(pi, 0x5cf, 3);
- write_phy_reg(pi, 0x5a5, 0x3);
- write_phy_reg(pi, 0x583, 0x0);
- write_phy_reg(pi, 0x584, 0x0);
- write_phy_reg(pi, 0x585, 0x0fff);
- write_phy_reg(pi, 0x586, 0x0000);
-
- write_phy_reg(pi, 0x580, 0x4501);
-
- sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
- write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
- stpptr = R_REG(&pi->regs->smpl_clct_stpptr);
- curptr = R_REG(&pi->regs->smpl_clct_curptr);
- do {
- udelay(10);
- curptr = R_REG(&pi->regs->smpl_clct_curptr);
- timer++;
- } while ((curptr != stpptr) && (timer < 500));
-
- W_REG(&pi->regs->psm_phy_hdr_param, 0x2);
- strptr = 0x7E00;
- W_REG(&pi->regs->tplatewrptr, strptr);
- while (strptr < 0x8000) {
- val = R_REG(&pi->regs->tplatewrdata);
- imag = ((val >> 16) & 0x3ff);
- real = ((val) & 0x3ff);
- if (imag > 511) {
- imag -= 1024;
- }
- if (real > 511) {
- real -= 1024;
- }
- if (pi_lcn->lcnphy_iqcal_swp_dis)
- ptr[(strptr - 0x7E00) / 4] = real;
- else
- ptr[(strptr - 0x7E00) / 4] = imag;
- if (clip_detect_algo) {
- if (imag > thresh || imag < -thresh) {
- strptr = 0x8000;
- ptr[130] = 1;
- }
- }
- strptr += 4;
- }
-
- write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
- W_REG(&pi->regs->psm_phy_hdr_param, curval2);
- W_REG(&pi->regs->psm_corectlsts, curval1);
-}
-
-static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi)
-{
- struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
-
- wlc_lcnphy_set_cc(pi, 0, 0, 0);
- wlc_lcnphy_set_cc(pi, 2, 0, 0);
- wlc_lcnphy_set_cc(pi, 3, 0, 0);
- wlc_lcnphy_set_cc(pi, 4, 0, 0);
-
- wlc_lcnphy_a1(pi, 4, 0, 0);
- wlc_lcnphy_a1(pi, 3, 0, 0);
- wlc_lcnphy_a1(pi, 2, 3, 2);
- wlc_lcnphy_a1(pi, 0, 5, 8);
- wlc_lcnphy_a1(pi, 2, 2, 1);
- wlc_lcnphy_a1(pi, 0, 4, 3);
-
- iqcc0 = wlc_lcnphy_get_cc(pi, 0);
- locc2 = wlc_lcnphy_get_cc(pi, 2);
- locc3 = wlc_lcnphy_get_cc(pi, 3);
- locc4 = wlc_lcnphy_get_cc(pi, 4);
-}
-
-static void
-wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y)
-{
- u16 di0dq0;
- u16 x, y, data_rf;
- int k;
- switch (cal_type) {
- case 0:
- wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
- break;
- case 2:
- di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
- wlc_lcnphy_set_tx_locc(pi, di0dq0);
- break;
- case 3:
- k = wlc_lcnphy_calc_floor(coeff_x, 0);
- y = 8 + k;
- k = wlc_lcnphy_calc_floor(coeff_x, 1);
- x = 8 - k;
- data_rf = (x * 16 + y);
- write_radio_reg(pi, RADIO_2064_REG089, data_rf);
- k = wlc_lcnphy_calc_floor(coeff_y, 0);
- y = 8 + k;
- k = wlc_lcnphy_calc_floor(coeff_y, 1);
- x = 8 - k;
- data_rf = (x * 16 + y);
- write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
- break;
- case 4:
- k = wlc_lcnphy_calc_floor(coeff_x, 0);
- y = 8 + k;
- k = wlc_lcnphy_calc_floor(coeff_x, 1);
- x = 8 - k;
- data_rf = (x * 16 + y);
- write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
- k = wlc_lcnphy_calc_floor(coeff_y, 0);
- y = 8 + k;
- k = wlc_lcnphy_calc_floor(coeff_y, 1);
- x = 8 - k;
- data_rf = (x * 16 + y);
- write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
- break;
- }
-}
-
-static struct lcnphy_unsign16_struct
-wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type)
-{
- u16 a, b, didq;
- u8 di0, dq0, ei, eq, fi, fq;
- struct lcnphy_unsign16_struct cc;
- cc.re = 0;
- cc.im = 0;
- switch (cal_type) {
- case 0:
- wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
- cc.re = a;
- cc.im = b;
- break;
- case 2:
- didq = wlc_lcnphy_get_tx_locc(pi);
- di0 = (((didq & 0xff00) << 16) >> 24);
- dq0 = (((didq & 0x00ff) << 24) >> 24);
- cc.re = (u16) di0;
- cc.im = (u16) dq0;
- break;
- case 3:
- wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
- cc.re = (u16) ei;
- cc.im = (u16) eq;
- break;
- case 4:
- wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
- cc.re = (u16) fi;
- cc.im = (u16) fq;
- break;
- }
- return cc;
-}
-
-static void
-wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels,
- int step_size_lg2)
-{
- const struct lcnphy_spb_tone *phy_c1;
- struct lcnphy_spb_tone phy_c2;
- struct lcnphy_unsign16_struct phy_c3;
- int phy_c4, phy_c5, k, l, j, phy_c6;
- u16 phy_c7, phy_c8, phy_c9;
- s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
- s16 *ptr, phy_c17;
- s32 phy_c18, phy_c19;
- u32 phy_c20, phy_c21;
- bool phy_c22, phy_c23, phy_c24, phy_c25;
- u16 phy_c26, phy_c27;
- u16 phy_c28, phy_c29, phy_c30;
- u16 phy_c31;
- u16 *phy_c32;
- phy_c21 = 0;
- phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
- ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
- if (NULL == ptr) {
- return;
- }
-
- phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
- if (NULL == phy_c32) {
- kfree(ptr);
- return;
- }
- phy_c26 = read_phy_reg(pi, 0x6da);
- phy_c27 = read_phy_reg(pi, 0x6db);
- phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
- write_phy_reg(pi, 0x93d, 0xC0);
-
- wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
- write_phy_reg(pi, 0x6da, 0xffff);
- or_phy_reg(pi, 0x6db, 0x3);
-
- wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
- udelay(500);
- phy_c28 = read_phy_reg(pi, 0x938);
- phy_c29 = read_phy_reg(pi, 0x4d7);
- phy_c30 = read_phy_reg(pi, 0x4d8);
- or_phy_reg(pi, 0x938, 0x1 << 2);
- or_phy_reg(pi, 0x4d7, 0x1 << 2);
- or_phy_reg(pi, 0x4d7, 0x1 << 3);
- mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
- or_phy_reg(pi, 0x4d8, 1 << 0);
- or_phy_reg(pi, 0x4d8, 1 << 1);
- mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
- mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
- phy_c1 = &lcnphy_spb_tone_3750[0];
- phy_c4 = 32;
-
- if (num_levels == 0) {
- if (cal_type != 0) {
- num_levels = 4;
- } else {
- num_levels = 9;
- }
- }
- if (step_size_lg2 == 0) {
- if (cal_type != 0) {
- step_size_lg2 = 3;
- } else {
- step_size_lg2 = 8;
- }
- }
-
- phy_c7 = (1 << step_size_lg2);
- phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
- phy_c15 = (s16) phy_c3.re;
- phy_c16 = (s16) phy_c3.im;
- if (cal_type == 2) {
- if (phy_c3.re > 127)
- phy_c15 = phy_c3.re - 256;
- if (phy_c3.im > 127)
- phy_c16 = phy_c3.im - 256;
- }
- wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
- udelay(20);
- for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
- phy_c23 = 1;
- phy_c22 = 0;
- switch (cal_type) {
- case 0:
- phy_c10 = 511;
- break;
- case 2:
- phy_c10 = 127;
- break;
- case 3:
- phy_c10 = 15;
- break;
- case 4:
- phy_c10 = 15;
- break;
- }
-
- phy_c9 = read_phy_reg(pi, 0x93d);
- phy_c9 = 2 * phy_c9;
- phy_c24 = 0;
- phy_c5 = 7;
- phy_c25 = 1;
- while (1) {
- write_radio_reg(pi, RADIO_2064_REG026,
- (phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
- udelay(50);
- phy_c22 = 0;
- ptr[130] = 0;
- wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
- if (ptr[130] == 1)
- phy_c22 = 1;
- if (phy_c22)
- phy_c5 -= 1;
- if ((phy_c22 != phy_c24) && (!phy_c25))
- break;
- if (!phy_c22)
- phy_c5 += 1;
- if (phy_c5 <= 0 || phy_c5 >= 7)
- break;
- phy_c24 = phy_c22;
- phy_c25 = 0;
- }
-
- if (phy_c5 < 0)
- phy_c5 = 0;
- else if (phy_c5 > 7)
- phy_c5 = 7;
-
- for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
- for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
- phy_c11 = phy_c15 + k;
- phy_c12 = phy_c16 + l;
-
- if (phy_c11 < -phy_c10)
- phy_c11 = -phy_c10;
- else if (phy_c11 > phy_c10)
- phy_c11 = phy_c10;
- if (phy_c12 < -phy_c10)
- phy_c12 = -phy_c10;
- else if (phy_c12 > phy_c10)
- phy_c12 = phy_c10;
- wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
- phy_c12);
- udelay(20);
- wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
-
- phy_c18 = 0;
- phy_c19 = 0;
- for (j = 0; j < 128; j++) {
- if (cal_type != 0) {
- phy_c6 = j % phy_c4;
- } else {
- phy_c6 = (2 * j) % phy_c4;
- }
- phy_c2.re = phy_c1[phy_c6].re;
- phy_c2.im = phy_c1[phy_c6].im;
- phy_c17 = ptr[j];
- phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
- phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
- }
-
- phy_c18 = phy_c18 >> 10;
- phy_c19 = phy_c19 >> 10;
- phy_c20 =
- ((phy_c18 * phy_c18) + (phy_c19 * phy_c19));
-
- if (phy_c23 || phy_c20 < phy_c21) {
- phy_c21 = phy_c20;
- phy_c13 = phy_c11;
- phy_c14 = phy_c12;
- }
- phy_c23 = 0;
- }
- }
- phy_c23 = 1;
- phy_c15 = phy_c13;
- phy_c16 = phy_c14;
- phy_c7 = phy_c7 >> 1;
- wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
- udelay(20);
- }
- goto cleanup;
- cleanup:
- wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
- wlc_lcnphy_stop_tx_tone(pi);
- write_phy_reg(pi, 0x6da, phy_c26);
- write_phy_reg(pi, 0x6db, phy_c27);
- write_phy_reg(pi, 0x938, phy_c28);
- write_phy_reg(pi, 0x4d7, phy_c29);
- write_phy_reg(pi, 0x4d8, phy_c30);
- write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
-
- kfree(phy_c32);
- kfree(ptr);
-}
-
-static void
-wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save)
-{
- int i;
-
- and_phy_reg(pi, 0x44c, 0x0 >> 11);
-
- and_phy_reg(pi, 0x43b, 0xC);
-
- for (i = 0; i < 20; i++) {
- write_radio_reg(pi, iqlo_loopback_rf_regs[i],
- values_to_save[i]);
+ pi_lcn->lcnphy_current_index =
+ (s8)((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
}
}
static void
wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
- const struct lcnphy_tx_gain_tbl_entry *gain_table) {
+ const struct lcnphy_tx_gain_tbl_entry *gain_table)
+{
u32 j;
struct phytbl_info tab;
u32 val;
@@ -4297,6 +4386,172 @@ static void wlc_lcnphy_load_rfpower(struct brcms_phy *pi)
}
}
+static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi)
+{
+ or_phy_reg(pi, 0x805, 0x1);
+
+ mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
+
+ mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
+
+ write_phy_reg(pi, 0x414, 0x1e10);
+ write_phy_reg(pi, 0x415, 0x0640);
+
+ mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
+
+ or_phy_reg(pi, 0x44a, 0x44);
+ write_phy_reg(pi, 0x44a, 0x80);
+ mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
+
+ mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
+
+ if (!(pi->sh->boardrev < 0x1204))
+ mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
+
+ write_phy_reg(pi, 0x7d6, 0x0902);
+ mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
+
+ mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
+
+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+ mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
+
+ mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
+
+ mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
+
+ mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
+
+ mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
+
+ mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
+ mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
+ mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
+ mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
+ mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
+
+ mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
+
+ wlc_lcnphy_clear_tx_power_offsets(pi);
+ mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
+
+ }
+}
+
+static void wlc_lcnphy_rcal(struct brcms_phy *pi)
+{
+ u8 rcal_value;
+
+ and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+ or_radio_reg(pi, RADIO_2064_REG004, 0x40);
+ or_radio_reg(pi, RADIO_2064_REG120, 0x10);
+
+ or_radio_reg(pi, RADIO_2064_REG078, 0x80);
+ or_radio_reg(pi, RADIO_2064_REG129, 0x02);
+
+ or_radio_reg(pi, RADIO_2064_REG057, 0x01);
+
+ or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
+ mdelay(5);
+ SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
+
+ if (wlc_radio_2064_rcal_done(pi)) {
+ rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
+ rcal_value = rcal_value & 0x1f;
+ }
+
+ and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+ and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
+}
+
+static void wlc_lcnphy_rc_cal(struct brcms_phy *pi)
+{
+ u8 dflt_rc_cal_val;
+ u16 flt_val;
+
+ dflt_rc_cal_val = 7;
+ if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+ dflt_rc_cal_val = 11;
+ flt_val =
+ (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
+ (dflt_rc_cal_val);
+ write_phy_reg(pi, 0x933, flt_val);
+ write_phy_reg(pi, 0x934, flt_val);
+ write_phy_reg(pi, 0x935, flt_val);
+ write_phy_reg(pi, 0x936, flt_val);
+ write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
+
+ return;
+}
+
+static void wlc_radio_2064_init(struct brcms_phy *pi)
+{
+ u32 i;
+ const struct lcnphy_radio_regs *lcnphyregs = NULL;
+
+ lcnphyregs = lcnphy_radio_regs_2064;
+
+ for (i = 0; lcnphyregs[i].address != 0xffff; i++)
+ if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
+ write_radio_reg(pi,
+ ((lcnphyregs[i].address & 0x3fff) |
+ RADIO_DEFAULT_CORE),
+ (u16) lcnphyregs[i].init_a);
+ else if (lcnphyregs[i].do_init_g)
+ write_radio_reg(pi,
+ ((lcnphyregs[i].address & 0x3fff) |
+ RADIO_DEFAULT_CORE),
+ (u16) lcnphyregs[i].init_g);
+
+ write_radio_reg(pi, RADIO_2064_REG032, 0x62);
+ write_radio_reg(pi, RADIO_2064_REG033, 0x19);
+
+ write_radio_reg(pi, RADIO_2064_REG090, 0x10);
+
+ write_radio_reg(pi, RADIO_2064_REG010, 0x00);
+
+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+
+ write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
+ write_radio_reg(pi, RADIO_2064_REG061, 0x72);
+ write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
+ }
+
+ write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
+ write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
+
+ mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
+
+ mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
+
+ mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
+
+ mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
+
+ mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
+
+ write_phy_reg(pi, 0x4ea, 0x4688);
+
+ mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
+
+ mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
+
+ mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
+
+ wlc_lcnphy_set_tx_locc(pi, 0);
+
+ wlc_lcnphy_rcal(pi);
+
+ wlc_lcnphy_rc_cal(pi);
+}
+
+static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
+{
+ wlc_radio_2064_init(pi);
+}
+
static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
{
uint idx;
@@ -4306,9 +4561,8 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
phybw40 = CHSPEC_IS40(pi->radio_chanspec);
- for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) {
+ for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++)
wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
- }
if (pi->sh->boardflags & BFL_FEM_BT) {
tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
@@ -4339,39 +4593,35 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if (pi->sh->boardflags & BFL_FEM)
- wlc_lcnphy_load_tx_gain_table(pi,
- dot11lcnphy_2GHz_extPA_gaintable_rev0);
+ wlc_lcnphy_load_tx_gain_table(
+ pi,
+ dot11lcnphy_2GHz_extPA_gaintable_rev0);
else
- wlc_lcnphy_load_tx_gain_table(pi,
- dot11lcnphy_2GHz_gaintable_rev0);
+ wlc_lcnphy_load_tx_gain_table(
+ pi,
+ dot11lcnphy_2GHz_gaintable_rev0);
}
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+ const struct phytbl_info *tb;
+ int l;
+
if (CHSPEC_IS2G(pi->radio_chanspec)) {
- for (idx = 0;
- idx < dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
- idx++)
- if (pi->sh->boardflags & BFL_EXTLNA)
- wlc_lcnphy_write_table(pi,
- &dot11lcnphytbl_rx_gain_info_extlna_2G_rev2
- [idx]);
- else
- wlc_lcnphy_write_table(pi,
- &dot11lcnphytbl_rx_gain_info_2G_rev2
- [idx]);
+ l = dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
+ if (pi->sh->boardflags & BFL_EXTLNA)
+ tb = dot11lcnphytbl_rx_gain_info_extlna_2G_rev2;
+ else
+ tb = dot11lcnphytbl_rx_gain_info_2G_rev2;
} else {
- for (idx = 0;
- idx < dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
- idx++)
- if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
- wlc_lcnphy_write_table(pi,
- &dot11lcnphytbl_rx_gain_info_extlna_5G_rev2
- [idx]);
- else
- wlc_lcnphy_write_table(pi,
- &dot11lcnphytbl_rx_gain_info_5G_rev2
- [idx]);
+ l = dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
+ if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
+ tb = dot11lcnphytbl_rx_gain_info_extlna_5G_rev2;
+ else
+ tb = dot11lcnphytbl_rx_gain_info_5G_rev2;
}
+
+ for (idx = 0; idx < l; idx++)
+ wlc_lcnphy_write_table(pi, &tb[idx]);
}
if ((pi->sh->boardflags & BFL_FEM)
@@ -4379,11 +4629,13 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
else if (pi->sh->boardflags & BFL_FEM_BT) {
if (pi->sh->boardrev < 0x1250)
- wlc_lcnphy_write_table(pi,
- &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
+ wlc_lcnphy_write_table(
+ pi,
+ &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
else
- wlc_lcnphy_write_table(pi,
- &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
+ wlc_lcnphy_write_table(
+ pi,
+ &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
} else
wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
@@ -4420,9 +4672,8 @@ static void wlc_lcnphy_rev0_baseband_init(struct brcms_phy *pi)
if (0) {
afectrl1 = 0;
afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
- (pi_lcn->lcnphy_rssi_vc << 4) | (pi_lcn->
- lcnphy_rssi_gs
- << 10));
+ (pi_lcn->lcnphy_rssi_vc << 4) |
+ (pi_lcn->lcnphy_rssi_gs << 10));
write_phy_reg(pi, 0x43e, afectrl1);
}
@@ -4443,7 +4694,6 @@ static void wlc_lcnphy_rev2_baseband_init(struct brcms_phy *pi)
{
if (CHSPEC_IS5G(pi->radio_chanspec)) {
mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
-
mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
}
}
@@ -4455,9 +4705,6 @@ static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi)
u32 tableBuffer[2];
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
temp = (s16) read_phy_reg(pi, 0x4df);
pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
@@ -4484,18 +4731,15 @@ static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi)
tableBuffer[1] -= 128;
pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
- temp = (s16) (read_phy_reg(pi, 0x434)
- & (0xff << 0));
+ temp = (s16) (read_phy_reg(pi, 0x434) & (0xff << 0));
if (temp > 127)
temp -= 256;
pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
- pi_lcn->lcnphy_Med_Low_Gain_db = (read_phy_reg(pi, 0x424)
- & (0xff << 8))
- >> 8;
- pi_lcn->lcnphy_Very_Low_Gain_db = (read_phy_reg(pi, 0x425)
- & (0xff << 0))
- >> 0;
+ pi_lcn->lcnphy_Med_Low_Gain_db =
+ (read_phy_reg(pi, 0x424) & (0xff << 8)) >> 8;
+ pi_lcn->lcnphy_Very_Low_Gain_db =
+ (read_phy_reg(pi, 0x425) & (0xff << 0)) >> 0;
tab.tbl_ptr = tableBuffer;
tab.tbl_len = 2;
@@ -4509,61 +4753,6 @@ static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi)
}
-static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi)
-{
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
- or_phy_reg(pi, 0x805, 0x1);
-
- mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
-
- mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
-
- write_phy_reg(pi, 0x414, 0x1e10);
- write_phy_reg(pi, 0x415, 0x0640);
-
- mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
-
- or_phy_reg(pi, 0x44a, 0x44);
- write_phy_reg(pi, 0x44a, 0x80);
- mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
-
- mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
-
- if (!(pi->sh->boardrev < 0x1204))
- mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
-
- write_phy_reg(pi, 0x7d6, 0x0902);
- mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
-
- mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
-
- if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
- mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
-
- mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
-
- mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
-
- mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
-
- mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
-
- mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
- mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
- mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
- mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
- mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
-
- mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
-
- wlc_lcnphy_clear_tx_power_offsets(pi);
- mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
-
- }
-}
-
static void wlc_lcnphy_baseband_init(struct brcms_phy *pi)
{
@@ -4574,127 +4763,53 @@ static void wlc_lcnphy_baseband_init(struct brcms_phy *pi)
wlc_lcnphy_bu_tweaks(pi);
}
-static void wlc_radio_2064_init(struct brcms_phy *pi)
+void wlc_phy_init_lcnphy(struct brcms_phy *pi)
{
- u32 i;
- struct lcnphy_radio_regs *lcnphyregs = NULL;
-
- lcnphyregs = lcnphy_radio_regs_2064;
-
- for (i = 0; lcnphyregs[i].address != 0xffff; i++)
- if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
- write_radio_reg(pi,
- ((lcnphyregs[i].address & 0x3fff) |
- RADIO_DEFAULT_CORE),
- (u16) lcnphyregs[i].init_a);
- else if (lcnphyregs[i].do_init_g)
- write_radio_reg(pi,
- ((lcnphyregs[i].address & 0x3fff) |
- RADIO_DEFAULT_CORE),
- (u16) lcnphyregs[i].init_g);
-
- write_radio_reg(pi, RADIO_2064_REG032, 0x62);
- write_radio_reg(pi, RADIO_2064_REG033, 0x19);
-
- write_radio_reg(pi, RADIO_2064_REG090, 0x10);
-
- write_radio_reg(pi, RADIO_2064_REG010, 0x00);
-
- if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
-
- write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
- write_radio_reg(pi, RADIO_2064_REG061, 0x72);
- write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
- }
-
- write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
- write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
-
- mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
-
- mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
-
- mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
-
- mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
-
- mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
-
- write_phy_reg(pi, 0x4ea, 0x4688);
-
- mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
-
- mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
-
- mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
-
- wlc_lcnphy_set_tx_locc(pi, 0);
-
- wlc_lcnphy_rcal(pi);
+ u8 phybw40;
+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+ phybw40 = CHSPEC_IS40(pi->radio_chanspec);
- wlc_lcnphy_rc_cal(pi);
-}
+ pi_lcn->lcnphy_cal_counter = 0;
+ pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
-static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
-{
- if (NORADIO_ENAB(pi->pubpi))
- return;
+ or_phy_reg(pi, 0x44a, 0x80);
+ and_phy_reg(pi, 0x44a, 0x7f);
- wlc_radio_2064_init(pi);
-}
+ wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
-static void wlc_lcnphy_rcal(struct brcms_phy *pi)
-{
- u8 rcal_value;
+ write_phy_reg(pi, 0x60a, 160);
- if (NORADIO_ENAB(pi->pubpi))
- return;
+ write_phy_reg(pi, 0x46a, 25);
- and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+ wlc_lcnphy_baseband_init(pi);
- or_radio_reg(pi, RADIO_2064_REG004, 0x40);
- or_radio_reg(pi, RADIO_2064_REG120, 0x10);
+ wlc_lcnphy_radio_init(pi);
- or_radio_reg(pi, RADIO_2064_REG078, 0x80);
- or_radio_reg(pi, RADIO_2064_REG129, 0x02);
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi);
- or_radio_reg(pi, RADIO_2064_REG057, 0x01);
+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
- or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
- mdelay(5);
- SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
+ si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
- if (wlc_radio_2064_rcal_done(pi)) {
- rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
- rcal_value = rcal_value & 0x1f;
- }
+ si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
- and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+ if ((pi->sh->boardflags & BFL_FEM)
+ && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+ wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
- and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
-}
+ wlc_lcnphy_agc_temp_init(pi);
-static void wlc_lcnphy_rc_cal(struct brcms_phy *pi)
-{
- u8 dflt_rc_cal_val;
- u16 flt_val;
+ wlc_lcnphy_temp_adj(pi);
- if (NORADIO_ENAB(pi->pubpi))
- return;
+ mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
- dflt_rc_cal_val = 7;
- if (LCNREV_IS(pi->pubpi.phy_rev, 1))
- dflt_rc_cal_val = 11;
- flt_val =
- (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
- (dflt_rc_cal_val);
- write_phy_reg(pi, 0x933, flt_val);
- write_phy_reg(pi, 0x934, flt_val);
- write_phy_reg(pi, 0x935, flt_val);
- write_phy_reg(pi, 0x936, flt_val);
- write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
+ udelay(100);
+ mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
- return;
+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
+ pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
+ wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
}
static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
@@ -4702,39 +4817,38 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
s8 txpwr = 0;
int i;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+ struct phy_shim_info *shim = pi->sh->physhim;
if (CHSPEC_IS2G(pi->radio_chanspec)) {
u16 cckpo = 0;
u32 offset_ofdm, offset_mcs;
pi_lcn->lcnphy_tr_isolation_mid =
- (u8) PHY_GETINTVAR(pi, "triso2g");
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TRISO2G);
pi_lcn->lcnphy_rx_power_offset =
- (u8) PHY_GETINTVAR(pi, "rxpo2g");
-
- pi->txpa_2g[0] = (s16) PHY_GETINTVAR(pi, "pa0b0");
- pi->txpa_2g[1] = (s16) PHY_GETINTVAR(pi, "pa0b1");
- pi->txpa_2g[2] = (s16) PHY_GETINTVAR(pi, "pa0b2");
-
- pi_lcn->lcnphy_rssi_vf = (u8) PHY_GETINTVAR(pi, "rssismf2g");
- pi_lcn->lcnphy_rssi_vc = (u8) PHY_GETINTVAR(pi, "rssismc2g");
- pi_lcn->lcnphy_rssi_gs = (u8) PHY_GETINTVAR(pi, "rssisav2g");
-
- {
- pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
- pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
- pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
-
- pi_lcn->lcnphy_rssi_vf_hightemp =
- pi_lcn->lcnphy_rssi_vf;
- pi_lcn->lcnphy_rssi_vc_hightemp =
- pi_lcn->lcnphy_rssi_vc;
- pi_lcn->lcnphy_rssi_gs_hightemp =
- pi_lcn->lcnphy_rssi_gs;
- }
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RXPO2G);
+
+ pi->txpa_2g[0] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B0);
+ pi->txpa_2g[1] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B1);
+ pi->txpa_2g[2] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B2);
- txpwr = (s8) PHY_GETINTVAR(pi, "maxp2ga0");
+ pi_lcn->lcnphy_rssi_vf =
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMF2G);
+ pi_lcn->lcnphy_rssi_vc =
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMC2G);
+ pi_lcn->lcnphy_rssi_gs =
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISAV2G);
+
+ pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
+ pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
+ pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
+
+ pi_lcn->lcnphy_rssi_vf_hightemp = pi_lcn->lcnphy_rssi_vf;
+ pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc;
+ pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs;
+
+ txpwr = (s8)wlapi_getintvar(shim, BRCMS_SROM_MAXP2GA0);
pi->tx_srom_max_2g = txpwr;
for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
@@ -4742,79 +4856,72 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
}
- cckpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
+ cckpo = (u16)wlapi_getintvar(shim, BRCMS_SROM_CCK2GPO);
+ offset_ofdm = (u32)wlapi_getintvar(shim, BRCMS_SROM_OFDM2GPO);
if (cckpo) {
uint max_pwr_chan = txpwr;
for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
- pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
- ((cckpo & 0xf) * 2);
+ pi->tx_srom_max_rate_2g[i] =
+ max_pwr_chan - ((cckpo & 0xf) * 2);
cckpo >>= 4;
}
- offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
- pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
- ((offset_ofdm & 0xf) * 2);
+ pi->tx_srom_max_rate_2g[i] =
+ max_pwr_chan -
+ ((offset_ofdm & 0xf) * 2);
offset_ofdm >>= 4;
}
} else {
u8 opo = 0;
- opo = (u8) PHY_GETINTVAR(pi, "opo");
+ opo = (u8)wlapi_getintvar(shim, BRCMS_SROM_OPO);
- for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
+ for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++)
pi->tx_srom_max_rate_2g[i] = txpwr;
- }
-
- offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
pi->tx_srom_max_rate_2g[i] = txpwr -
- ((offset_ofdm & 0xf) * 2);
+ ((offset_ofdm & 0xf) * 2);
offset_ofdm >>= 4;
}
offset_mcs =
- ((u16) PHY_GETINTVAR(pi, "mcs2gpo1") << 16) |
- (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
+ wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO1) << 16;
+ offset_mcs |=
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO0);
pi_lcn->lcnphy_mcs20_po = offset_mcs;
for (i = TXP_FIRST_SISO_MCS_20;
i <= TXP_LAST_SISO_MCS_20; i++) {
pi->tx_srom_max_rate_2g[i] =
- txpwr - ((offset_mcs & 0xf) * 2);
+ txpwr - ((offset_mcs & 0xf) * 2);
offset_mcs >>= 4;
}
}
pi_lcn->lcnphy_rawtempsense =
- (u16) PHY_GETINTVAR(pi, "rawtempsense");
+ (u16)wlapi_getintvar(shim, BRCMS_SROM_RAWTEMPSENSE);
pi_lcn->lcnphy_measPower =
- (u8) PHY_GETINTVAR(pi, "measpower");
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_MEASPOWER);
pi_lcn->lcnphy_tempsense_slope =
- (u8) PHY_GETINTVAR(pi, "tempsense_slope");
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_SLOPE);
pi_lcn->lcnphy_hw_iqcal_en =
- (bool) PHY_GETINTVAR(pi, "hw_iqcal_en");
+ (bool)wlapi_getintvar(shim, BRCMS_SROM_HW_IQCAL_EN);
pi_lcn->lcnphy_iqcal_swp_dis =
- (bool) PHY_GETINTVAR(pi, "iqcal_swp_dis");
+ (bool)wlapi_getintvar(shim, BRCMS_SROM_IQCAL_SWP_DIS);
pi_lcn->lcnphy_tempcorrx =
- (u8) PHY_GETINTVAR(pi, "tempcorrx");
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPCORRX);
pi_lcn->lcnphy_tempsense_option =
- (u8) PHY_GETINTVAR(pi, "tempsense_option");
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_OPTION);
pi_lcn->lcnphy_freqoffset_corr =
- (u8) PHY_GETINTVAR(pi, "freqoffset_corr");
- if ((u8) getintvar(pi->vars, "aa2g") > 1)
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_FREQOFFSET_CORR);
+ if ((u8)wlapi_getintvar(shim, BRCMS_SROM_AA2G) > 1)
wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi,
- (u8) getintvar(pi->vars,
- "aa2g"));
+ (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G));
}
pi_lcn->lcnphy_cck_dig_filt_type = -1;
- if (PHY_GETVAR(pi, "cckdigfilttype")) {
- s16 temp;
- temp = (s16) PHY_GETINTVAR(pi, "cckdigfilttype");
- if (temp >= 0) {
- pi_lcn->lcnphy_cck_dig_filt_type = temp;
- }
- }
return true;
}
@@ -4834,172 +4941,6 @@ void wlc_2064_vco_cal(struct brcms_phy *pi)
mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
}
-static void
-wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
-{
- uint i;
- const struct chan_info_2064_lcnphy *ci;
- u8 rfpll_doubler = 0;
- u8 pll_pwrup, pll_pwrup_ovr;
- fixed qFxtal, qFref, qFvco, qFcal;
- u8 d15, d16, f16, e44, e45;
- u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
- u16 loop_bw, d30, setCount;
- if (NORADIO_ENAB(pi->pubpi))
- return;
- ci = &chan_info_2064_lcnphy[0];
- rfpll_doubler = 1;
-
- mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
-
- write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
- if (!rfpll_doubler) {
- loop_bw = PLL_2064_LOOP_BW;
- d30 = PLL_2064_D30;
- } else {
- loop_bw = PLL_2064_LOOP_BW_DOUBLER;
- d30 = PLL_2064_D30_DOUBLER;
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
- if (chan_info_2064_lcnphy[i].chan == channel)
- break;
-
- if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) {
- return;
- }
-
- ci = &chan_info_2064_lcnphy[i];
- }
-
- write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
-
- mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
-
- mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
-
- mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
-
- mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
- (ci->logen_rccr_rx) << 2);
-
- mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
-
- mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
- (ci->pa_rxrf_lna2_freq_tune) << 4);
-
- write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
-
- pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
- pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
-
- or_radio_reg(pi, RADIO_2064_REG044, 0x07);
-
- or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
- e44 = 0;
- e45 = 0;
-
- fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
- if (pi->xtalfreq > 26000000)
- e44 = 1;
- if (pi->xtalfreq > 52000000)
- e45 = 1;
- if (e44 == 0)
- fcal_div = 1;
- else if (e45 == 0)
- fcal_div = 2;
- else
- fcal_div = 4;
- fvco3 = (ci->freq * 3);
- fref3 = 2 * fpfd;
-
- qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
- qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
- qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
- qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
-
- write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
-
- d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
- write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
- write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
-
- d16 = (qFcal * 8 / (d15 + 1)) - 1;
- write_radio_reg(pi, RADIO_2064_REG051, d16);
-
- f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
- setCount = f16 * 3 * (ci->freq) / 32 - 1;
- mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
- (u8) (setCount >> 8));
-
- or_radio_reg(pi, RADIO_2064_REG053, 0x10);
- write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
-
- div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
-
- div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
- while (div_frac >= fref3) {
- div_int++;
- div_frac -= fref3;
- }
- div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
-
- mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
- (u8) (div_int >> 4));
- mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
- (u8) (div_int << 4));
- mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
- (u8) (div_frac >> 16));
- write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
- write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
-
- write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
-
- write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
- write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
- write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
-
- {
- u8 h29, h23, c28, d29, h28_ten, e30, h30_ten, cp_current;
- u16 c29, c38, c30, g30, d28;
- c29 = loop_bw;
- d29 = 200;
- c38 = 1250;
- h29 = d29 / c29;
- h23 = 1;
- c28 = 30;
- d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
- (fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
- (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
- + PLL_2064_LOW_END_KVCO;
- h28_ten = (d28 * 10) / c28;
- c30 = 2640;
- e30 = (d30 - 680) / 490;
- g30 = 680 + (e30 * 490);
- h30_ten = (g30 * 10) / c30;
- cp_current = ((c38 * h29 * h23 * 100) / h28_ten) / h30_ten;
- mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
- }
- if (channel >= 1 && channel <= 5)
- write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
- else
- write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
- write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
-
- mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
- udelay(1);
-
- wlc_2064_vco_cal(pi);
-
- write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
- write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
- if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
- write_radio_reg(pi, RADIO_2064_REG038, 3);
- write_radio_reg(pi, RADIO_2064_REG091, 7);
- }
-}
-
bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi)
{
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
@@ -5015,14 +4956,11 @@ void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi)
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
} else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
-
pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
wlc_lcnphy_txpower_recalc_target(pi);
-
wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
- } else
- return;
+ }
}
void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
@@ -5035,13 +4973,12 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
struct brcms_phy_lcnphy *pi_lcn;
pi->u.pi_lcnphy = kzalloc(sizeof(struct brcms_phy_lcnphy), GFP_ATOMIC);
- if (pi->u.pi_lcnphy == NULL) {
+ if (pi->u.pi_lcnphy == NULL)
return false;
- }
pi_lcn = pi->u.pi_lcnphy;
- if ((0 == (pi->sh->boardflags & BFL_NOPA)) && !NORADIO_ENAB(pi->pubpi)) {
+ if (0 == (pi->sh->boardflags & BFL_NOPA)) {
pi->hwpwrctrl = true;
pi->hwpwrctrl_capable = true;
}
@@ -5062,7 +4999,8 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
return false;
- if ((pi->sh->boardflags & BFL_FEM) && (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
+ if ((pi->sh->boardflags & BFL_FEM) &&
+ (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
if (pi_lcn->lcnphy_tempsense_option == 3) {
pi->hwpwrctrl = true;
pi->hwpwrctrl_capable = true;
@@ -5090,8 +5028,8 @@ static void wlc_lcnphy_set_rx_gain(struct brcms_phy *pi, u32 gain)
biq1 = (u16) (gain >> 16) & 0xf;
gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
- ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
- ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
+ ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
+ ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
gain16_19 = biq1;
mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
@@ -5126,18 +5064,19 @@ static u32 wlc_lcnphy_get_receive_power(struct brcms_phy *pi, s32 *gain_index)
lcnphy_23bitgaincode_table
[*gain_index]);
received_power =
- wlc_lcnphy_measure_digital_power(pi,
- pi_lcn->
- lcnphy_noise_samples);
+ wlc_lcnphy_measure_digital_power(
+ pi,
+ pi_lcn->
+ lcnphy_noise_samples);
(*gain_index)++;
}
(*gain_index)--;
} else {
wlc_lcnphy_set_rx_gain(pi, gain_code);
received_power =
- wlc_lcnphy_measure_digital_power(pi,
- pi_lcn->
- lcnphy_noise_samples);
+ wlc_lcnphy_measure_digital_power(pi,
+ pi_lcn->
+ lcnphy_noise_samples);
}
return received_power;
@@ -5150,6 +5089,8 @@ s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
input_power_db;
s32 received_power, temperature;
+ u32 power;
+ u32 msb1, msb2, val1, val2, diff1, diff2;
uint freq;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
@@ -5159,20 +5100,17 @@ s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
- {
- u32 power = (received_power * 16);
- u32 msb1, msb2, val1, val2, diff1, diff2;
- msb1 = ffs(power) - 1;
- msb2 = msb1 + 1;
- val1 = 1 << msb1;
- val2 = 1 << msb2;
- diff1 = (power - val1);
- diff2 = (val2 - power);
- if (diff1 < diff2)
- log_val = msb1;
- else
- log_val = msb2;
- }
+ power = (received_power * 16);
+ msb1 = ffs(power) - 1;
+ msb2 = msb1 + 1;
+ val1 = 1 << msb1;
+ val2 = 1 << msb2;
+ diff1 = (power - val1);
+ diff2 = (val2 - power);
+ if (diff1 < diff2)
+ log_val = msb1;
+ else
+ log_val = msb2;
log_val = log_val * 3;
@@ -5188,7 +5126,7 @@ s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
input_power_db = input_power_offset_db - desired_gain;
input_power_db =
- input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
+ input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
if ((freq > 2427) && (freq <= 2467))
@@ -5196,99 +5134,21 @@ s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
temperature = pi_lcn->lcnphy_lastsensed_temperature;
- if ((temperature - 15) < -30) {
+ if ((temperature - 15) < -30)
input_power_db =
- input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
- 7;
- } else if ((temperature - 15) < 4) {
+ input_power_db +
+ (((temperature - 10 - 25) * 286) >> 12) -
+ 7;
+ else if ((temperature - 15) < 4)
input_power_db =
- input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
- 3;
- } else {
- input_power_db =
- input_power_db + (((temperature - 10 - 25) * 286) >> 12);
- }
+ input_power_db +
+ (((temperature - 10 - 25) * 286) >> 12) -
+ 3;
+ else
+ input_power_db = input_power_db +
+ (((temperature - 10 - 25) * 286) >> 12);
wlc_lcnphy_rx_gain_override_enable(pi, 0);
return input_power_db;
}
-
-static int
-wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type)
-{
- s16 filt_index = -1;
- int j;
-
- u16 addr[] = {
- 0x910,
- 0x91e,
- 0x91f,
- 0x924,
- 0x925,
- 0x926,
- 0x920,
- 0x921,
- 0x927,
- 0x928,
- 0x929,
- 0x922,
- 0x923,
- 0x930,
- 0x931,
- 0x932
- };
-
- u16 addr_ofdm[] = {
- 0x90f,
- 0x900,
- 0x901,
- 0x906,
- 0x907,
- 0x908,
- 0x902,
- 0x903,
- 0x909,
- 0x90a,
- 0x90b,
- 0x904,
- 0x905,
- 0x90c,
- 0x90d,
- 0x90e
- };
-
- if (!is_ofdm) {
- for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
- if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
- filt_index = (s16) j;
- break;
- }
- }
-
- if (filt_index != -1) {
- for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, addr[j],
- LCNPHY_txdigfiltcoeffs_cck
- [filt_index][j + 1]);
- }
- }
- } else {
- for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
- if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
- filt_index = (s16) j;
- break;
- }
- }
-
- if (filt_index != -1) {
- for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, addr_ofdm[j],
- LCNPHY_txdigfiltcoeffs_ofdm
- [filt_index][j + 1]);
- }
- }
- }
-
- return (filt_index != -1) ? 0 : -1;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c b/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c
index f8e419239425..cd19c2f7a347 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c
@@ -14,7 +14,9 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/kernel.h>
#include <linux/delay.h>
+#include <linux/cordic.h>
#include <brcm_hw_ids.h>
#include <aiutils.h>
@@ -28,27 +30,42 @@
#include "phyreg_n.h"
#include "phytbl_n.h"
-#define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \
- read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
- ((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1))
-#define WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \
+#define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \
+ read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
+ ((core == PHY_CORE_0) ? \
+ radio_type##_##jspace##0 : \
+ radio_type##_##jspace##1))
+
+#define WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \
write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
- ((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1), value);
-#define WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \
- write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value);
-
-#define READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \
- read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
- radio_type##_##jspace##1##_##reg_name));
-#define WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \
- write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
- radio_type##_##jspace##1##_##reg_name), value);
-#define READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \
- read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
- radio_type##_##reg_name##_##jspace##1));
-#define WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \
- write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
- radio_type##_##reg_name##_##jspace##1), value);
+ ((core == PHY_CORE_0) ? \
+ radio_type##_##jspace##0 : \
+ radio_type##_##jspace##1), value)
+
+#define WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \
+ write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value)
+
+#define READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \
+ read_radio_reg(pi, ((core == PHY_CORE_0) ? \
+ radio_type##_##jspace##0##_##reg_name : \
+ radio_type##_##jspace##1##_##reg_name))
+
+#define WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \
+ write_radio_reg(pi, ((core == PHY_CORE_0) ? \
+ radio_type##_##jspace##0##_##reg_name : \
+ radio_type##_##jspace##1##_##reg_name), \
+ value)
+
+#define READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \
+ read_radio_reg(pi, ((core == PHY_CORE_0) ? \
+ radio_type##_##reg_name##_##jspace##0 : \
+ radio_type##_##reg_name##_##jspace##1))
+
+#define WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \
+ write_radio_reg(pi, ((core == PHY_CORE_0) ? \
+ radio_type##_##reg_name##_##jspace##0 : \
+ radio_type##_##reg_name##_##jspace##1), \
+ value)
#define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40
#define NPHY_ACI_CHANNEL_DELTA 5
@@ -103,9 +120,11 @@
#define NPHY_CALSANITY_RSSI_NB_MAX_POS 9
#define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9
#define NPHY_CALSANITY_RSSI_W1_MAX_POS 12
-#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - NPHY_RSSICAL_MAXREAD)
+#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - \
+ NPHY_RSSICAL_MAXREAD)
#define NPHY_CALSANITY_RSSI_W2_MAX_POS NPHY_CALSANITY_RSSI_W1_MAX_POS
-#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - NPHY_RSSICAL_MAXREAD)
+#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - \
+ NPHY_RSSICAL_MAXREAD)
#define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f)))
#define NPHY_RSSI_NB_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \
((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG))
@@ -124,11 +143,11 @@
#define NPHY_PAPD_COMP_OFF 0
#define NPHY_PAPD_COMP_ON 1
-#define NPHY_SROM_TEMPSHIFT 32
-#define NPHY_SROM_MAXTEMPOFFSET 16
-#define NPHY_SROM_MINTEMPOFFSET -16
+#define NPHY_SROM_TEMPSHIFT 32
+#define NPHY_SROM_MAXTEMPOFFSET 16
+#define NPHY_SROM_MINTEMPOFFSET -16
-#define NPHY_CAL_MAXTEMPDELTA 64
+#define NPHY_CAL_MAXTEMPDELTA 64
#define NPHY_NOISEVAR_TBLLEN40 256
#define NPHY_NOISEVAR_TBLLEN20 128
@@ -138,8 +157,24 @@
#define NPHY_ADJUSTED_MINCRSPOWER 0x1e
/* 5357 Chip specific ChipControl register bits */
-#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */
-#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */
+#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */
+#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */
+
+#define NPHY_CAL_TSSISAMPS 64
+#define NPHY_TEST_TONE_FREQ_40MHz 4000
+#define NPHY_TEST_TONE_FREQ_20MHz 2500
+
+#define MAX_205x_RCAL_WAITLOOPS 10000
+
+#define NPHY_RXCAL_TONEAMP 181
+#define NPHY_RXCAL_TONEFREQ_40MHz 4000
+#define NPHY_RXCAL_TONEFREQ_20MHz 2000
+
+#define TXFILT_SHAPING_OFDM20 0
+#define TXFILT_SHAPING_OFDM40 1
+#define TXFILT_SHAPING_CCK 2
+#define TXFILT_DEFAULT_OFDM20 3
+#define TXFILT_DEFAULT_OFDM40 4
struct nphy_iqcal_params {
u16 txlpf;
@@ -184,44 +219,42 @@ struct nphy_ipa_txrxgain {
#define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1)
-struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz[] = { {0, 0, 0, 0, 0, 100},
-{0, 0, 0, 0, 0, 50},
-{0, 0, 0, 0, 0, -1},
-{0, 0, 0, 3, 0, -1},
-{0, 0, 3, 3, 0, -1},
-{0, 2, 3, 3, 0, -1}
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz[] = {
+ {0, 0, 0, 0, 0, 100},
+ {0, 0, 0, 0, 0, 50},
+ {0, 0, 0, 0, 0, -1},
+ {0, 0, 0, 3, 0, -1},
+ {0, 0, 3, 3, 0, -1},
+ {0, 2, 3, 3, 0, -1}
};
-struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz[] = { {0, 0, 0, 0, 0, 128},
-{0, 0, 0, 0, 0, 70},
-{0, 0, 0, 0, 0, 20},
-{0, 0, 0, 3, 0, 20},
-{0, 0, 3, 3, 0, 20},
-{0, 2, 3, 3, 0, 20}
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz[] = {
+ {0, 0, 0, 0, 0, 128},
+ {0, 0, 0, 0, 0, 70},
+ {0, 0, 0, 0, 0, 20},
+ {0, 0, 0, 3, 0, 20},
+ {0, 0, 3, 3, 0, 20},
+ {0, 2, 3, 3, 0, 20}
};
-struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = {
-{0, 0, 0, 0, 0, 100},
-{0, 0, 0, 0, 0, 50},
-{0, 0, 0, 0, 0, -1},
-{0, 0, 0, 3, 0, -1},
-{0, 0, 3, 3, 0, -1},
-{0, 0, 5, 3, 0, -1}
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = {
+ {0, 0, 0, 0, 0, 100},
+ {0, 0, 0, 0, 0, 50},
+ {0, 0, 0, 0, 0, -1},
+ {0, 0, 0, 3, 0, -1},
+ {0, 0, 3, 3, 0, -1},
+ {0, 0, 5, 3, 0, -1}
};
-struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = {
-{0, 0, 0, 0, 0, 10},
-{0, 0, 0, 1, 0, 10},
-{0, 0, 1, 2, 0, 10},
-{0, 0, 1, 3, 0, 10},
-{0, 0, 4, 3, 0, 10},
-{0, 0, 6, 3, 0, 10}
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = {
+ {0, 0, 0, 0, 0, 10},
+ {0, 0, 0, 1, 0, 10},
+ {0, 0, 1, 2, 0, 10},
+ {0, 0, 1, 3, 0, 10},
+ {0, 0, 4, 3, 0, 10},
+ {0, 0, 6, 3, 0, 10}
};
-#define NPHY_RXCAL_TONEAMP 181
-#define NPHY_RXCAL_TONEFREQ_40MHz 4000
-#define NPHY_RXCAL_TONEFREQ_20MHz 2000
-
enum {
NPHY_RXCAL_GAIN_INIT = 0,
NPHY_RXCAL_GAIN_UP,
@@ -230,17 +263,11 @@ enum {
#define wlc_phy_get_papd_nphy(pi) \
(read_phy_reg((pi), 0x1e7) & \
- ((0x1 << 15) | \
- (0x1 << 14) | \
- (0x1 << 13)))
+ ((0x1 << 15) | \
+ (0x1 << 14) | \
+ (0x1 << 13)))
-#define TXFILT_SHAPING_OFDM20 0
-#define TXFILT_SHAPING_OFDM40 1
-#define TXFILT_SHAPING_CCK 2
-#define TXFILT_DEFAULT_OFDM20 3
-#define TXFILT_DEFAULT_OFDM40 4
-
-u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = {
+static const u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = {
{-377, 137, -407, 208, -1527, 956, 93, 186, 93,
230, -44, 230, 201, -191, 201},
{-77, 20, -98, 49, -93, 60, 56, 111, 56, 26, -5,
@@ -416,7 +443,7 @@ struct nphy_sfo_cfg {
u16 PHY_BW6;
};
-static struct chan_info_nphy_2055 chan_info_nphy_2055[] = {
+static const struct chan_info_nphy_2055 chan_info_nphy_2055[] = {
{
184, 4920, 3280, 0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
@@ -915,7 +942,7 @@ static struct chan_info_nphy_2055 chan_info_nphy_2055[] = {
0x01, 0x80, 0x3E6, 0x3E2, 0x3DE, 0x41B, 0x41F, 0x424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev3_2056[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev3_2056[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
@@ -1538,7 +1565,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev3_2056[] = {
0x0f, 0x00, 0x0d, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev4_2056_A1[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev4_2056_A1[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
@@ -2161,7 +2188,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev4_2056_A1[] = {
0x0f, 0x00, 0x0e, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev5_2056v5[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev5_2056v5[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
@@ -2784,7 +2811,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev5_2056v5[] = {
0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v6[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v6[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
@@ -3407,7 +3434,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v6[] = {
0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev5n6_2056v7[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev5n6_2056v7[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
@@ -4030,7 +4057,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev5n6_2056v7[] = {
0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v8[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v8[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
@@ -4653,7 +4680,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v8[] = {
0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v11[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v11[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
@@ -5276,7 +5303,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v11[] = {
0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio2057 chan_info_nphyrev7_2057_rev4[] = {
+static const struct chan_info_nphy_radio2057 chan_info_nphyrev7_2057_rev4[] = {
{
184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
@@ -6139,7 +6166,8 @@ static struct chan_info_nphy_radio2057 chan_info_nphyrev7_2057_rev4[] = {
0x0424}
};
-static struct chan_info_nphy_radio2057_rev5 chan_info_nphyrev8_2057_rev5[] = {
+static const struct chan_info_nphy_radio2057_rev5
+chan_info_nphyrev8_2057_rev5[] = {
{
1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
@@ -6198,7 +6226,8 @@ static struct chan_info_nphy_radio2057_rev5 chan_info_nphyrev8_2057_rev5[] = {
0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio2057_rev5 chan_info_nphyrev9_2057_rev5v1[] = {
+static const struct chan_info_nphy_radio2057_rev5
+chan_info_nphyrev9_2057_rev5v1[] = {
{
1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
@@ -6257,7 +6286,7 @@ static struct chan_info_nphy_radio2057_rev5 chan_info_nphyrev9_2057_rev5v1[] = {
0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev7[] = {
+static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev7[] = {
{
184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
@@ -6998,7 +7027,7 @@ static struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev7[] = {
0x0424}
};
-static struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev8[] = {
+static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev8[] = {
{
186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
@@ -7733,7 +7762,7 @@ static struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev8[] = {
0x0424}
};
-struct radio_regs regs_2055[] = {
+static struct radio_regs regs_2055[] = {
{0x02, 0x80, 0x80, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0x27, 0x27, 0, 0},
@@ -7962,7 +7991,7 @@ struct radio_regs regs_2055[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_SYN_2056[] = {
+static struct radio_regs regs_SYN_2056[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8147,7 +8176,7 @@ struct radio_regs regs_SYN_2056[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_TX_2056[] = {
+static struct radio_regs regs_TX_2056[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8296,7 +8325,7 @@ struct radio_regs regs_TX_2056[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_RX_2056[] = {
+static struct radio_regs regs_RX_2056[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8447,7 +8476,7 @@ struct radio_regs regs_RX_2056[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_SYN_2056_A1[] = {
+static struct radio_regs regs_SYN_2056_A1[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8632,7 +8661,7 @@ struct radio_regs regs_SYN_2056_A1[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_TX_2056_A1[] = {
+static struct radio_regs regs_TX_2056_A1[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8781,7 +8810,7 @@ struct radio_regs regs_TX_2056_A1[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_RX_2056_A1[] = {
+static struct radio_regs regs_RX_2056_A1[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8932,7 +8961,7 @@ struct radio_regs regs_RX_2056_A1[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_SYN_2056_rev5[] = {
+static struct radio_regs regs_SYN_2056_rev5[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9117,7 +9146,7 @@ struct radio_regs regs_SYN_2056_rev5[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_TX_2056_rev5[] = {
+static struct radio_regs regs_TX_2056_rev5[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9274,7 +9303,7 @@ struct radio_regs regs_TX_2056_rev5[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_RX_2056_rev5[] = {
+static struct radio_regs regs_RX_2056_rev5[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9425,7 +9454,7 @@ struct radio_regs regs_RX_2056_rev5[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_SYN_2056_rev6[] = {
+static struct radio_regs regs_SYN_2056_rev6[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9610,7 +9639,7 @@ struct radio_regs regs_SYN_2056_rev6[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_TX_2056_rev6[] = {
+static struct radio_regs regs_TX_2056_rev6[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9767,7 +9796,7 @@ struct radio_regs regs_TX_2056_rev6[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_RX_2056_rev6[] = {
+static struct radio_regs regs_RX_2056_rev6[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9918,7 +9947,7 @@ struct radio_regs regs_RX_2056_rev6[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_SYN_2056_rev7[] = {
+static struct radio_regs regs_SYN_2056_rev7[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10103,7 +10132,7 @@ struct radio_regs regs_SYN_2056_rev7[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_TX_2056_rev7[] = {
+static struct radio_regs regs_TX_2056_rev7[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10260,7 +10289,7 @@ struct radio_regs regs_TX_2056_rev7[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_RX_2056_rev7[] = {
+static struct radio_regs regs_RX_2056_rev7[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10411,7 +10440,7 @@ struct radio_regs regs_RX_2056_rev7[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_SYN_2056_rev8[] = {
+static struct radio_regs regs_SYN_2056_rev8[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10596,7 +10625,7 @@ struct radio_regs regs_SYN_2056_rev8[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_TX_2056_rev8[] = {
+static struct radio_regs regs_TX_2056_rev8[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10753,7 +10782,7 @@ struct radio_regs regs_TX_2056_rev8[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_RX_2056_rev8[] = {
+static struct radio_regs regs_RX_2056_rev8[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10904,7 +10933,7 @@ struct radio_regs regs_RX_2056_rev8[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_SYN_2056_rev11[] = {
+static const struct radio_regs regs_SYN_2056_rev11[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -11089,7 +11118,7 @@ struct radio_regs regs_SYN_2056_rev11[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_TX_2056_rev11[] = {
+static const struct radio_regs regs_TX_2056_rev11[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -11246,7 +11275,7 @@ struct radio_regs regs_TX_2056_rev11[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_RX_2056_rev11[] = {
+static const struct radio_regs regs_RX_2056_rev11[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -11397,7 +11426,7 @@ struct radio_regs regs_RX_2056_rev11[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_20xx_regs regs_2057_rev4[] = {
+static struct radio_20xx_regs regs_2057_rev4[] = {
{0x00, 0x84, 0},
{0x01, 0, 0},
{0x02, 0x60, 0},
@@ -11787,7 +11816,7 @@ struct radio_20xx_regs regs_2057_rev4[] = {
{0xFFFF, 0, 0},
};
-struct radio_20xx_regs regs_2057_rev5[] = {
+static struct radio_20xx_regs regs_2057_rev5[] = {
{0x00, 0, 1},
{0x01, 0x57, 1},
{0x02, 0x20, 1},
@@ -12119,7 +12148,7 @@ struct radio_20xx_regs regs_2057_rev5[] = {
{0xFFFF, 0, 0}
};
-struct radio_20xx_regs regs_2057_rev5v1[] = {
+static struct radio_20xx_regs regs_2057_rev5v1[] = {
{0x00, 0x15, 1},
{0x01, 0x57, 1},
{0x02, 0x20, 1},
@@ -12451,7 +12480,7 @@ struct radio_20xx_regs regs_2057_rev5v1[] = {
{0xFFFF, 0, 0}
};
-struct radio_20xx_regs regs_2057_rev7[] = {
+static struct radio_20xx_regs regs_2057_rev7[] = {
{0x00, 0, 1},
{0x01, 0x57, 1},
{0x02, 0x20, 1},
@@ -12867,7 +12896,7 @@ struct radio_20xx_regs regs_2057_rev7[] = {
{0xFFFF, 0, 0}
};
-struct radio_20xx_regs regs_2057_rev8[] = {
+static struct radio_20xx_regs regs_2057_rev8[] = {
{0x00, 0x8, 1},
{0x01, 0x57, 1},
{0x02, 0x20, 1},
@@ -13290,27 +13319,27 @@ static s32 nphy_lnagain_est1[] = { -224, 23242 };
static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = {
{
- {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69},
- {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69},
- {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68},
- {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67},
- {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66},
- {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65},
- {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65},
- {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65},
- {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65}
- },
- {
- {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
- {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
- {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79},
- {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78},
- {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78},
- {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78},
- {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78},
- {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78},
- {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78}
- }
+ {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69},
+ {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69},
+ {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68},
+ {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67},
+ {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66},
+ {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65},
+ {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65},
+ {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65},
+ {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65}
+ },
+ {
+ {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+ {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+ {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79},
+ {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78},
+ {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78},
+ {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78},
+ {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78},
+ {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78},
+ {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78}
+ }
};
static const u32 nphy_tpc_txgain[] = {
@@ -14081,118 +14110,11 @@ static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = {
static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 };
static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 };
static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = {
- 0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a };
+ 0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a
+};
static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = {
- 0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 };
-
-static bool wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
- struct chan_info_nphy_radio2057 **t0,
- struct chan_info_nphy_radio205x **t1,
- struct chan_info_nphy_radio2057_rev5 **t2,
- struct chan_info_nphy_2055 **t3);
-static void wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chans,
- const struct nphy_sfo_cfg *c);
-
-static void wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi,
- u16 reduction_factr);
-static void wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi,
- int ntones, int *, u32 *buf);
-static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr);
-static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi);
-static void wlc_phy_spurwar_nphy(struct brcms_phy *pi);
-
-static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi);
-static void wlc_phy_radio_init_2055(struct brcms_phy *pi);
-static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi);
-static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi);
-static void wlc_phy_radio_init_2056(struct brcms_phy *pi);
-static void wlc_phy_radio_postinit_2056(struct brcms_phy *pi);
-static void wlc_phy_radio_init_2057(struct brcms_phy *pi);
-static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi);
-static void wlc_phy_workarounds_nphy(struct brcms_phy *pi);
-static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi);
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi);
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi);
-static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi);
-
-static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi);
-static void wlc_phy_reapply_txcal_coeffs_nphy(struct brcms_phy *pi);
-static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi);
-static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
- struct nphy_txgains tg, u8 type, bool d);
-static void wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rxcore,
- u16 *rg, u8 type);
-static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble);
-static void wlc_phy_savecal_nphy(struct brcms_phy *pi);
-static void wlc_phy_restorecal_nphy(struct brcms_phy *pi);
-static void wlc_phy_resetcca_nphy(struct brcms_phy *pi);
-
-static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi);
-static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi);
-static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi);
-static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core);
-
-static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi);
-static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi);
-static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi);
-static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi);
-static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1);
-static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi);
-
-static void wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32,
- u32 e);
-static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core);
-static void wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *,
- enum phy_cal_mode, u8);
-static void wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi,
- struct nphy_papd_restore_state *state);
-static void wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi,
- struct nphy_papd_restore_state *state, u8);
-
-static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals);
-
-static void wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *evts,
- u8 *dlys, u8 len);
-
-static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset);
-
-static void
-wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value,
- u8 core_mask, u8 off,
- u8 override_id);
-
-static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type);
-static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi);
-
-static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi);
-static void wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max,
- u16 *pwr_offset,
- u8 tmp_max_pwr, u8 rate_start,
- u8 rate_end);
-
-static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi);
-static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi);
-static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi);
-static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi);
-
-static bool wlc_phy_txpwr_ison_nphy(struct brcms_phy *pi);
-static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core);
-static void wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0,
- u8 idx1);
-static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal);
-
-static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi);
-
-static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi);
-
-static u16 wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz,
- u16 max_val,
- u8 dac_test_mode);
-static void wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, cs32 *tone_buf,
- u16 num_samps);
-static void wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 n, u16 lps,
- u16 wait, u8 iq, u8 dac_test_mode,
- bool modify_bbmult);
+ 0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16
+};
bool wlc_phy_bist_check_phy(struct brcms_phy_pub *pih)
{
@@ -14209,9 +14131,8 @@ bool wlc_phy_bist_check_phy(struct brcms_phy_pub *pih)
phybist4 = read_phy_reg(pi, 0x156);
if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) &&
- (phybist3 == 0) && (phybist4 == 0)) {
+ (phybist3 == 0) && (phybist4 == 0))
return true;
- }
return false;
}
@@ -14230,18 +14151,7 @@ static void wlc_phy_bphy_init_nphy(struct brcms_phy *pi)
val -= 0x0202;
}
- if (NORADIO_ENAB(pi->pubpi)) {
-
- write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_PHYCRSTH, 0x3206);
-
- write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_RSSI_TRESH, 0x281e);
-
- or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_LNA_GAIN_RANGE, 0x1a);
-
- } else {
-
- write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668);
- }
+ write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668);
}
void
@@ -14307,7 +14217,8 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi)
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
- pi->srom_fem2g.antswctrllut : pi->srom_fem5g.antswctrllut;
+ pi->srom_fem2g.antswctrllut : pi->srom_fem5g.
+ antswctrllut;
switch (antswctrllut) {
case 0:
@@ -14316,20 +14227,20 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi)
case 1:
- if (pi->aa2g == 7) {
+ if (pi->aa2g == 7)
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x21, 8,
+ &ant_sw_ctrl_tbl_rev8_2o3[0]);
+ else
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x21, 8,
+ &ant_sw_ctrl_tbl_rev8
+ [0]);
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x21, 8,
- &ant_sw_ctrl_tbl_rev8_2o3
- [0]);
- } else {
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x21, 8,
- &ant_sw_ctrl_tbl_rev8
- [0]);
- }
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
2, 0x25, 8,
&ant_sw_ctrl_tbl_rev8[2]);
@@ -14340,31 +14251,31 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi)
case 2:
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x1, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core0
- [0]);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x5, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core0
- [2]);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x9, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core0
- [4]);
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x21, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core1
- [0]);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x25, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core1
- [2]);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x29, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core1
- [4]);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x1, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core0[0]);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x5, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core0[2]);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x9, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core0[4]);
+
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x21, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core1[0]);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x25, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core1[2]);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x29, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core1[4]);
break;
default:
@@ -14375,45 +14286,49 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi)
for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) {
if (idx == ANT_SWCTRL_TBL_REV3_IDX) {
- antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
- pi->srom_fem2g.antswctrllut : pi->
- srom_fem5g.antswctrllut;
+ antswctrllut =
+ CHSPEC_IS2G(pi->radio_chanspec) ?
+ pi->srom_fem2g.antswctrllut :
+ pi->srom_fem5g.antswctrllut;
switch (antswctrllut) {
case 0:
- wlc_phy_write_table_nphy(pi,
- &mimophytbl_info_rev3_volatile
- [idx]);
+ wlc_phy_write_table_nphy(
+ pi,
+ &mimophytbl_info_rev3_volatile
+ [idx]);
break;
case 1:
- wlc_phy_write_table_nphy(pi,
- &mimophytbl_info_rev3_volatile1
- [idx]);
+ wlc_phy_write_table_nphy(
+ pi,
+ &mimophytbl_info_rev3_volatile1
+ [idx]);
break;
case 2:
- wlc_phy_write_table_nphy(pi,
- &mimophytbl_info_rev3_volatile2
- [idx]);
+ wlc_phy_write_table_nphy(
+ pi,
+ &mimophytbl_info_rev3_volatile2
+ [idx]);
break;
case 3:
- wlc_phy_write_table_nphy(pi,
- &mimophytbl_info_rev3_volatile3
- [idx]);
+ wlc_phy_write_table_nphy(
+ pi,
+ &mimophytbl_info_rev3_volatile3
+ [idx]);
break;
default:
break;
}
} else {
- wlc_phy_write_table_nphy(pi,
- &mimophytbl_info_rev3_volatile
- [idx]);
+ wlc_phy_write_table_nphy(
+ pi,
+ &mimophytbl_info_rev3_volatile[idx]);
}
}
} else {
- for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) {
+ for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++)
wlc_phy_write_table_nphy(pi,
&mimophytbl_info_rev0_volatile
[idx]);
- }
}
}
@@ -14440,32 +14355,414 @@ void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs)
wlc_phy_write_txmacreg_nphy(pi, holdoff, delay);
- if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) {
+ if (pi && pi->sh && (pi->sh->_rifs_phy != rifs))
pi->sh->_rifs_phy = rifs;
+}
+
+static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi)
+{
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+ pi->phy_5g_pwrgain = true;
+ return;
+ }
+
+ pi->nphy_txpwrctrl = PHY_TPC_HW_OFF;
+ pi->phy_5g_pwrgain = false;
+
+ if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) &&
+ NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4))
+ pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+ else if ((pi->sh->sromrev >= 4)
+ && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN))
+ pi->phy_5g_pwrgain = true;
+}
+
+static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
+{
+ u16 bw40po, cddpo, stbcpo, bwduppo;
+ uint band_num;
+ struct phy_shim_info *shim = pi->sh->physhim;
+
+ if (pi->sh->sromrev >= 9)
+ return;
+
+ bw40po = (u16) wlapi_getintvar(shim, BRCMS_SROM_BW40PO);
+ pi->bw402gpo = bw40po & 0xf;
+ pi->bw405gpo = (bw40po & 0xf0) >> 4;
+ pi->bw405glpo = (bw40po & 0xf00) >> 8;
+ pi->bw405ghpo = (bw40po & 0xf000) >> 12;
+
+ cddpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_CDDPO);
+ pi->cdd2gpo = cddpo & 0xf;
+ pi->cdd5gpo = (cddpo & 0xf0) >> 4;
+ pi->cdd5glpo = (cddpo & 0xf00) >> 8;
+ pi->cdd5ghpo = (cddpo & 0xf000) >> 12;
+
+ stbcpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_STBCPO);
+ pi->stbc2gpo = stbcpo & 0xf;
+ pi->stbc5gpo = (stbcpo & 0xf0) >> 4;
+ pi->stbc5glpo = (stbcpo & 0xf00) >> 8;
+ pi->stbc5ghpo = (stbcpo & 0xf000) >> 12;
+
+ bwduppo = (u16) wlapi_getintvar(shim, BRCMS_SROM_BWDUPPO);
+ pi->bwdup2gpo = bwduppo & 0xf;
+ pi->bwdup5gpo = (bwduppo & 0xf0) >> 4;
+ pi->bwdup5glpo = (bwduppo & 0xf00) >> 8;
+ pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12;
+
+ for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP);
+ band_num++) {
+ switch (band_num) {
+ case 0:
+
+ pi->nphy_txpid2g[PHY_CORE_0] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID2GA0);
+ pi->nphy_txpid2g[PHY_CORE_1] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID2GA1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP2GA0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP2GA1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW0A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW0A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW1A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW1A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW2A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW2A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g =
+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g =
+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA1);
+
+ pi->cck2gpo = (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_CCK2GPO);
+
+ pi->ofdm2gpo =
+ (u32) wlapi_getintvar(shim,
+ BRCMS_SROM_OFDM2GPO);
+
+ pi->mcs2gpo[0] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO0);
+ pi->mcs2gpo[1] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO1);
+ pi->mcs2gpo[2] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO2);
+ pi->mcs2gpo[3] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO3);
+ pi->mcs2gpo[4] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO4);
+ pi->mcs2gpo[5] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO5);
+ pi->mcs2gpo[6] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO6);
+ pi->mcs2gpo[7] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO7);
+ break;
+ case 1:
+
+ pi->nphy_txpid5g[PHY_CORE_0] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GA0);
+ pi->nphy_txpid5g[PHY_CORE_1] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GA1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
+ (s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP5GA1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW0A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW0A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW1A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW1A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW2A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW2A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm =
+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm =
+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA1);
+
+ pi->ofdm5gpo =
+ (u32) wlapi_getintvar(shim,
+ BRCMS_SROM_OFDM5GPO);
+
+ pi->mcs5gpo[0] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO0);
+ pi->mcs5gpo[1] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO1);
+ pi->mcs5gpo[2] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO2);
+ pi->mcs5gpo[3] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO3);
+ pi->mcs5gpo[4] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO4);
+ pi->mcs5gpo[5] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO5);
+ pi->mcs5gpo[6] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO6);
+ pi->mcs5gpo[7] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO7);
+ break;
+ case 2:
+
+ pi->nphy_txpid5gl[0] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GLA0);
+ pi->nphy_txpid5gl[1] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GLA1);
+ pi->nphy_pwrctrl_info[0].max_pwr_5gl =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP5GLA0);
+ pi->nphy_pwrctrl_info[1].max_pwr_5gl =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP5GLA1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW0A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW0A1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW1A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW1A1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW2A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW2A1);
+ pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0;
+ pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0;
+
+ pi->ofdm5glpo =
+ (u32) wlapi_getintvar(shim,
+ BRCMS_SROM_OFDM5GLPO);
+
+ pi->mcs5glpo[0] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO0);
+ pi->mcs5glpo[1] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO1);
+ pi->mcs5glpo[2] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO2);
+ pi->mcs5glpo[3] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO3);
+ pi->mcs5glpo[4] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO4);
+ pi->mcs5glpo[5] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO5);
+ pi->mcs5glpo[6] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO6);
+ pi->mcs5glpo[7] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO7);
+ break;
+ case 3:
+
+ pi->nphy_txpid5gh[0] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GHA0);
+ pi->nphy_txpid5gh[1] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GHA1);
+ pi->nphy_pwrctrl_info[0].max_pwr_5gh =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP5GHA0);
+ pi->nphy_pwrctrl_info[1].max_pwr_5gh =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP5GHA1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW0A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW0A1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW1A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW1A1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW2A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW2A1);
+ pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0;
+ pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0;
+
+ pi->ofdm5ghpo =
+ (u32) wlapi_getintvar(shim,
+ BRCMS_SROM_OFDM5GHPO);
+
+ pi->mcs5ghpo[0] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO0);
+ pi->mcs5ghpo[1] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO1);
+ pi->mcs5ghpo[2] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO2);
+ pi->mcs5ghpo[3] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO3);
+ pi->mcs5ghpo[4] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO4);
+ pi->mcs5ghpo[5] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO5);
+ pi->mcs5ghpo[6] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO6);
+ pi->mcs5ghpo[7] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO7);
+ break;
+ }
}
+
+ wlc_phy_txpwr_apply_nphy(pi);
+}
+
+static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi)
+{
+ struct phy_shim_info *shim = pi->sh->physhim;
+
+ pi->antswitch = (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWITCH);
+ pi->aa2g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G);
+ pi->aa5g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA5G);
+
+ pi->srom_fem2g.tssipos = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TSSIPOS2G);
+ pi->srom_fem2g.extpagain = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_EXTPAGAIN2G);
+ pi->srom_fem2g.pdetrange = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_PDETRANGE2G);
+ pi->srom_fem2g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO2G);
+ pi->srom_fem2g.antswctrllut =
+ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G);
+
+ pi->srom_fem5g.tssipos = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TSSIPOS5G);
+ pi->srom_fem5g.extpagain = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_EXTPAGAIN5G);
+ pi->srom_fem5g.pdetrange = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_PDETRANGE5G);
+ pi->srom_fem5g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO5G);
+ if (wlapi_getvar(shim, BRCMS_SROM_ANTSWCTL5G))
+ pi->srom_fem5g.antswctrllut =
+ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL5G);
+ else
+ pi->srom_fem5g.antswctrllut =
+ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G);
+
+ wlc_phy_txpower_ipa_upd(pi);
+
+ pi->phy_txcore_disable_temp =
+ (s16) wlapi_getintvar(shim, BRCMS_SROM_TEMPTHRESH);
+ if (pi->phy_txcore_disable_temp == 0)
+ pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
+
+ pi->phy_tempsense_offset = (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_TEMPOFFSET);
+ if (pi->phy_tempsense_offset != 0) {
+ if (pi->phy_tempsense_offset >
+ (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET))
+ pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET;
+ else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT +
+ NPHY_SROM_MINTEMPOFFSET))
+ pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET;
+ else
+ pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT;
+ }
+
+ pi->phy_txcore_enable_temp =
+ pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP;
+
+ pi->phycal_tempdelta =
+ (u8) wlapi_getintvar(shim, BRCMS_SROM_PHYCAL_TEMPDELTA);
+ if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA)
+ pi->phycal_tempdelta = 0;
+
+ wlc_phy_txpwr_srom_read_ppr_nphy(pi);
+
+ return true;
}
bool wlc_phy_attach_nphy(struct brcms_phy *pi)
{
uint i;
- if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6))
pi->phyhang_avoid = true;
- }
if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
pi->nphy_gband_spurwar_en = true;
-
- if (pi->sh->boardflags2 & BFL2_SPUR_WAR) {
+ if (pi->sh->boardflags2 & BFL2_SPUR_WAR)
pi->nphy_aband_spurwar_en = true;
- }
}
if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
- if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) {
+ if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR)
pi->nphy_gband_spurwar2_en = true;
- }
}
pi->n_preamble_override = AUTO;
@@ -14485,9 +14782,8 @@ bool wlc_phy_attach_nphy(struct brcms_phy *pi)
pi->nphy_elna_gain_config = false;
pi->radio_is_on = false;
- for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+ for (i = 0; i < pi->pubpi.phy_corenum; i++)
pi->nphy_txpwrindex[i].index = AUTO;
- }
wlc_phy_txpwrctrl_config_nphy(pi);
if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
@@ -14504,751 +14800,1405 @@ bool wlc_phy_attach_nphy(struct brcms_phy *pi)
return true;
}
-static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi)
+static s32 get_rf_pwr_offset(struct brcms_phy *pi, s16 pga_gn, s16 pad_gn)
{
+ s32 rfpwr_offset = 0;
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
- pi->phy_5g_pwrgain = true;
- return;
- }
-
- pi->nphy_txpwrctrl = PHY_TPC_HW_OFF;
- pi->phy_5g_pwrgain = false;
-
- if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) &&
- NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4))
- pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
- else if ((pi->sh->sromrev >= 4)
- && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN))
- pi->phy_5g_pwrgain = true;
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6))
+ rfpwr_offset = (s16)
+ nphy_papd_padgain_dlt_2g_2057rev3n4
+ [pad_gn];
+ else if (pi->pubpi.radiorev == 5)
+ rfpwr_offset = (s16)
+ nphy_papd_padgain_dlt_2g_2057rev5
+ [pad_gn];
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev ==
+ 8))
+ rfpwr_offset = (s16)
+ nphy_papd_padgain_dlt_2g_2057rev7
+ [pad_gn];
+ } else {
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6))
+ rfpwr_offset = (s16)
+ nphy_papd_pgagain_dlt_5g_2057
+ [pga_gn];
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev ==
+ 8))
+ rfpwr_offset = (s16)
+ nphy_papd_pgagain_dlt_5g_2057rev7
+ [pga_gn];
+ }
+ return rfpwr_offset;
}
-void wlc_phy_init_nphy(struct brcms_phy *pi)
+static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble)
{
+ bool gf_preamble = false;
u16 val;
- u16 clip1_ths[2];
- struct nphy_txgains target_gain;
- u8 tx_pwr_ctrl_state;
- bool do_nphy_cal = false;
- uint core;
- uint origidx, intr_val;
- d11regs_t *regs;
- u32 d11_clk_ctl_st;
- core = 0;
-
- if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
- pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
- }
+ if (preamble == BRCMS_N_PREAMBLE_GF)
+ gf_preamble = true;
- if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
- ((pi->sh->chippkg == BCM4717_PKG_ID) ||
- (pi->sh->chippkg == BCM4718_PKG_ID))) {
- if ((pi->sh->boardflags & BFL_EXTLNA) &&
- (CHSPEC_IS2G(pi->radio_chanspec))) {
- ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol), 0x40,
- 0x40);
- }
- }
+ val = read_phy_reg(pi, 0xed);
- if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
- CHSPEC_IS40(pi->radio_chanspec)) {
+ val |= RX_GF_MM_AUTO;
+ val &= ~RX_GF_OR_MM;
+ if (gf_preamble)
+ val |= RX_GF_OR_MM;
- regs = (d11regs_t *) ai_switch_core(pi->sh->sih, D11_CORE_ID,
- &origidx, &intr_val);
- d11_clk_ctl_st = R_REG(&regs->clk_ctl_st);
- AND_REG(&regs->clk_ctl_st,
- ~(CCS_FORCEHT | CCS_HTAREQ));
+ write_phy_reg(pi, 0xed, val);
+}
- W_REG(&regs->clk_ctl_st, d11_clk_ctl_st);
+static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
+{
+ int j, type;
+ u16 addr_offset[] = { 0x186, 0x195, 0x2c5};
- ai_restore_core(pi->sh->sih, origidx, intr_val);
+ for (type = 0; type < 3; type++) {
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, addr_offset[type] + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
}
- pi->use_int_tx_iqlo_cal_nphy =
- (PHY_IPA(pi) ||
- (NREV_GE(pi->pubpi.phy_rev, 7) ||
- (NREV_GE(pi->pubpi.phy_rev, 5)
- && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL)));
-
- pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false;
-
- pi->nphy_deaf_count = 0;
-
- wlc_phy_tbl_init_nphy(pi);
-
- pi->nphy_crsminpwr_adjusted = false;
- pi->nphy_noisevars_adjusted = false;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- write_phy_reg(pi, 0xe7, 0);
- write_phy_reg(pi, 0xec, 0);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- write_phy_reg(pi, 0x342, 0);
- write_phy_reg(pi, 0x343, 0);
- write_phy_reg(pi, 0x346, 0);
- write_phy_reg(pi, 0x347, 0);
- }
- write_phy_reg(pi, 0xe5, 0);
- write_phy_reg(pi, 0xe6, 0);
+ if (pi->bw == WL_CHANSPEC_BW_40) {
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, 0x186 + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
} else {
- write_phy_reg(pi, 0xec, 0);
- }
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, 0x186 + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[5][j]);
+ }
- write_phy_reg(pi, 0x91, 0);
- write_phy_reg(pi, 0x92, 0);
- if (NREV_LT(pi->pubpi.phy_rev, 6)) {
- write_phy_reg(pi, 0x93, 0);
- write_phy_reg(pi, 0x94, 0);
+ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, 0x2c5 + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[6][j]);
+ }
}
+}
- and_phy_reg(pi, 0xa1, ~3);
+static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi)
+{
+ int j;
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- write_phy_reg(pi, 0x8f, 0);
- write_phy_reg(pi, 0xa5, 0);
+ if (pi->bw == WL_CHANSPEC_BW_40) {
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, 0x195 + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]);
} else {
- write_phy_reg(pi, 0xa5, 0);
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, 0x186 + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
}
+}
- if (NREV_IS(pi->pubpi.phy_rev, 2))
- mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
- else if (NREV_LT(pi->pubpi.phy_rev, 2))
- mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
-
- write_phy_reg(pi, 0x203, 32);
- write_phy_reg(pi, 0x201, 32);
-
- if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD)
- write_phy_reg(pi, 0x20d, 160);
- else
- write_phy_reg(pi, 0x20d, 184);
-
- write_phy_reg(pi, 0x13a, 200);
-
- write_phy_reg(pi, 0x70, 80);
-
- write_phy_reg(pi, 0x1ff, 48);
+static void
+wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys,
+ u8 len)
+{
+ u32 t1_offset, t2_offset;
+ u8 ctr;
+ u8 end_event =
+ NREV_GE(pi->pubpi.phy_rev,
+ 3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END;
+ u8 end_dly = 1;
- if (NREV_LT(pi->pubpi.phy_rev, 8)) {
- wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override);
- }
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
- wlc_phy_stf_chain_upd_nphy(pi);
+ t1_offset = cmd << 4;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8,
+ events);
+ t2_offset = t1_offset + 0x080;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8,
+ dlys);
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
- write_phy_reg(pi, 0x180, 0xaa8);
- write_phy_reg(pi, 0x181, 0x9a4);
+ for (ctr = len; ctr < 16; ctr++) {
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+ t1_offset + ctr, 8, &end_event);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+ t2_offset + ctr, 8, &end_dly);
}
- if (PHY_IPA(pi)) {
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (1) << 0);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 :
- 0x29c, (0x1ff << 7),
- (pi->nphy_papd_epsilon_offset[core]) << 7);
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
- }
+static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset)
+{
+ u16 lpf_bw_ctl_val = 0;
+ u16 rx2tx_lpf_rc_lut_offset = 0;
- wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+ if (offset == 0) {
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ rx2tx_lpf_rc_lut_offset = 0x159;
+ else
+ rx2tx_lpf_rc_lut_offset = 0x154;
} else {
-
- if (NREV_GE(pi->pubpi.phy_rev, 5)) {
- wlc_phy_extpa_set_tx_digi_filts_nphy(pi);
- }
+ rx2tx_lpf_rc_lut_offset = offset;
}
+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+ (u32) rx2tx_lpf_rc_lut_offset, 16,
+ &lpf_bw_ctl_val);
- wlc_phy_workarounds_nphy(pi);
-
- wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
-
- val = read_phy_reg(pi, 0x01);
- write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
- write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
- wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
-
- wlapi_bmac_macphyclk_set(pi->sh->physhim, ON);
-
- wlc_phy_pa_override_nphy(pi, OFF);
- wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
- wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
- wlc_phy_pa_override_nphy(pi, ON);
+ lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7;
- wlc_phy_classifier_nphy(pi, 0, 0);
- wlc_phy_clip_det_nphy(pi, 0, clip1_ths);
+ return lpf_bw_ctl_val;
+}
- if (CHSPEC_IS2G(pi->radio_chanspec))
- wlc_phy_bphy_init_nphy(pi);
+static void
+wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value,
+ u8 core_mask, u8 off, u8 override_id)
+{
+ u8 core_num;
+ u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0;
+ u8 val_shift = 0;
- tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
- wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ en_mask = field;
+ for (core_num = 0; core_num < 2; core_num++) {
+ if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) {
- wlc_phy_txpwr_fixpower_nphy(pi);
+ switch (field) {
+ case (0x1 << 2):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 1);
+ val_shift = 1;
+ break;
+ case (0x1 << 3):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 2);
+ val_shift = 2;
+ break;
+ case (0x1 << 4):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 4);
+ val_shift = 4;
+ break;
+ case (0x1 << 5):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 5);
+ val_shift = 5;
+ break;
+ case (0x1 << 6):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 6);
+ val_shift = 6;
+ break;
+ case (0x1 << 7):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 7);
+ val_shift = 7;
+ break;
+ case (0x1 << 10):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0xf8 :
+ 0xfa;
+ val_mask = (0x7 << 4);
+ val_shift = 4;
+ break;
+ case (0x1 << 11):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7b :
+ 0x7e;
+ val_mask = (0xffff << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 12):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7c :
+ 0x7f;
+ val_mask = (0xffff << 0);
+ val_shift = 0;
+ break;
+ case (0x3 << 13):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x348 :
+ 0x349;
+ val_mask = (0xff << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 13):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x348 :
+ 0x349;
+ val_mask = (0xf << 0);
+ val_shift = 0;
+ break;
+ default:
+ addr = 0xffff;
+ break;
+ }
+ } else if (override_id ==
+ NPHY_REV7_RFCTRLOVERRIDE_ID1) {
- wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+ switch (field) {
+ case (0x1 << 1):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 1);
+ val_shift = 1;
+ break;
+ case (0x1 << 3):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 3);
+ val_shift = 3;
+ break;
+ case (0x1 << 5):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 5);
+ val_shift = 5;
+ break;
+ case (0x1 << 4):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 4);
+ val_shift = 4;
+ break;
+ case (0x1 << 2):
- wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 2);
+ val_shift = 2;
+ break;
+ case (0x1 << 7):
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- u32 *tx_pwrctrl_tbl = NULL;
- u16 idx;
- s16 pga_gn = 0;
- s16 pad_gn = 0;
- s32 rfpwr_offset = 0;
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x7 << 8);
+ val_shift = 8;
+ break;
+ case (0x1 << 11):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 14);
+ val_shift = 14;
+ break;
+ case (0x1 << 10):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 13);
+ val_shift = 13;
+ break;
+ case (0x1 << 9):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 12);
+ val_shift = 12;
+ break;
+ case (0x1 << 8):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 11);
+ val_shift = 11;
+ break;
+ case (0x1 << 6):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 6);
+ val_shift = 6;
+ break;
+ case (0x1 << 0):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 0);
+ val_shift = 0;
+ break;
+ default:
+ addr = 0xffff;
+ break;
+ }
+ } else if (override_id ==
+ NPHY_REV7_RFCTRLOVERRIDE_ID2) {
- if (PHY_IPA(pi)) {
- tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi);
- } else {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (NREV_IS(pi->pubpi.phy_rev, 3)) {
- tx_pwrctrl_tbl =
- nphy_tpc_5GHz_txgain_rev3;
- } else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
- tx_pwrctrl_tbl =
- (pi->srom_fem5g.extpagain == 3) ?
- nphy_tpc_5GHz_txgain_HiPwrEPA :
- nphy_tpc_5GHz_txgain_rev4;
- } else {
- tx_pwrctrl_tbl =
- nphy_tpc_5GHz_txgain_rev5;
+ switch (field) {
+ case (0x1 << 3):
+ en_addr = (core_num == 0) ? 0x346 :
+ 0x347;
+ val_addr = (core_num == 0) ? 0x344 :
+ 0x345;
+ val_mask = (0x1 << 3);
+ val_shift = 3;
+ break;
+ case (0x1 << 1):
+ en_addr = (core_num == 0) ? 0x346 :
+ 0x347;
+ val_addr = (core_num == 0) ? 0x344 :
+ 0x345;
+ val_mask = (0x1 << 1);
+ val_shift = 1;
+ break;
+ case (0x1 << 0):
+ en_addr = (core_num == 0) ? 0x346 :
+ 0x347;
+ val_addr = (core_num == 0) ? 0x344 :
+ 0x345;
+ val_mask = (0x1 << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 2):
+ en_addr = (core_num == 0) ? 0x346 :
+ 0x347;
+ val_addr = (core_num == 0) ? 0x344 :
+ 0x345;
+ val_mask = (0x1 << 2);
+ val_shift = 2;
+ break;
+ case (0x1 << 4):
+ en_addr = (core_num == 0) ? 0x346 :
+ 0x347;
+ val_addr = (core_num == 0) ? 0x344 :
+ 0x345;
+ val_mask = (0x1 << 4);
+ val_shift = 4;
+ break;
+ default:
+ addr = 0xffff;
+ break;
}
+ }
+ if (off) {
+ and_phy_reg(pi, en_addr, ~en_mask);
+ and_phy_reg(pi, val_addr, ~val_mask);
} else {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (pi->pubpi.radiorev == 5) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_epa_2057rev5;
- } else if (pi->pubpi.radiorev == 3) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_epa_2057rev3;
- }
- } else {
- if (NREV_GE(pi->pubpi.phy_rev, 5) &&
- (pi->srom_fem2g.extpagain == 3)) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_HiPwrEPA;
- } else {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_rev3;
- }
+ if ((core_mask == 0)
+ || (core_mask & (1 << core_num))) {
+ or_phy_reg(pi, en_addr, en_mask);
+
+ if (addr != 0xffff)
+ mod_phy_reg(pi, val_addr,
+ val_mask,
+ (value <<
+ val_shift));
}
}
}
+ }
+}
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
- 192, 32, tx_pwrctrl_tbl);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
- 192, 32, tx_pwrctrl_tbl);
-
- pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000);
+static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi)
+{
+ uint core;
+ int ctr;
+ s16 gain_delta[2];
+ u8 curr_channel;
+ u16 minmax_gain[2];
+ u16 regval[4];
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
- for (idx = 0; idx < 128; idx++) {
- pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
- pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f;
+ if (pi->nphy_gain_boost) {
+ if ((CHSPEC_IS2G(pi->radio_chanspec))) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
- rfpwr_offset = (s16)
- nphy_papd_padgain_dlt_2g_2057rev3n4
- [pad_gn];
- } else if (pi->pubpi.radiorev == 5) {
- rfpwr_offset = (s16)
- nphy_papd_padgain_dlt_2g_2057rev5
- [pad_gn];
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev ==
- 8)) {
- rfpwr_offset = (s16)
- nphy_papd_padgain_dlt_2g_2057rev7
- [pad_gn];
- }
- } else {
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
- rfpwr_offset = (s16)
- nphy_papd_pgagain_dlt_5g_2057
- [pga_gn];
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev ==
- 8)) {
- rfpwr_offset = (s16)
- nphy_papd_pgagain_dlt_5g_2057rev7
- [pga_gn];
- }
- }
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_CORE1TXPWRCTL,
- 1, 576 + idx, 32,
- &rfpwr_offset);
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_CORE2TXPWRCTL,
- 1, 576 + idx, 32,
- &rfpwr_offset);
- }
+ gain_delta[0] = 6;
+ gain_delta[1] = 6;
} else {
- for (idx = 0; idx < 128; idx++) {
- pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- rfpwr_offset = (s16)
- nphy_papd_pga_gain_delta_ipa_2g
- [pga_gn];
- } else {
- rfpwr_offset = (s16)
- nphy_papd_pga_gain_delta_ipa_5g
- [pga_gn];
- }
-
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_CORE1TXPWRCTL,
- 1, 576 + idx, 32,
- &rfpwr_offset);
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_CORE2TXPWRCTL,
- 1, 576 + idx, 32,
- &rfpwr_offset);
- }
-
+ curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+ gain_delta[0] =
+ (s16)
+ PHY_HW_ROUND(((nphy_lnagain_est0[0] *
+ curr_channel) +
+ nphy_lnagain_est0[1]), 13);
+ gain_delta[1] =
+ (s16)
+ PHY_HW_ROUND(((nphy_lnagain_est1[0] *
+ curr_channel) +
+ nphy_lnagain_est1[1]), 13);
}
} else {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
- 192, 32, nphy_tpc_txgain);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
- 192, 32, nphy_tpc_txgain);
+ gain_delta[0] = 0;
+ gain_delta[1] = 0;
}
- if (pi->sh->phyrxchain != 0x3) {
- wlc_phy_rxcore_setstate_nphy((struct brcms_phy_pub *) pi,
- pi->sh->phyrxchain);
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+ if (pi->nphy_elna_gain_config) {
+
+ regval[0] = nphy_def_lnagains[2] + gain_delta[core];
+ regval[1] = nphy_def_lnagains[3] + gain_delta[core];
+ regval[2] = nphy_def_lnagains[3] + gain_delta[core];
+ regval[3] = nphy_def_lnagains[3] + gain_delta[core];
+ } else {
+ for (ctr = 0; ctr < 4; ctr++)
+ regval[ctr] =
+ nphy_def_lnagains[ctr] +
+ gain_delta[core];
+ }
+ wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval);
+
+ minmax_gain[core] =
+ (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4);
}
- if (PHY_PERICAL_MPHASE_PENDING(pi)) {
- wlc_phy_cal_perical_mphase_restart(pi);
+ mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0));
+ mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0));
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void
+wlc_phy_war_force_trsw_to_R_cliplo_nphy(struct brcms_phy *pi, u8 core)
+{
+ if (core == PHY_CORE_0) {
+ write_phy_reg(pi, 0x38, 0x4);
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ write_phy_reg(pi, 0x37, 0x0060);
+ else
+ write_phy_reg(pi, 0x37, 0x1080);
+ } else if (core == PHY_CORE_1) {
+ write_phy_reg(pi, 0x2ae, 0x4);
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ write_phy_reg(pi, 0x2ad, 0x0060);
+ else
+ write_phy_reg(pi, 0x2ad, 0x1080);
}
+}
- if (!NORADIO_ENAB(pi->pubpi)) {
- bool do_rssi_cal = false;
+static void wlc_phy_war_txchain_upd_nphy(struct brcms_phy *pi, u8 txchain)
+{
+ u8 txchain0, txchain1;
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
- (pi->nphy_rssical_chanspec_2G == 0) :
- (pi->nphy_rssical_chanspec_5G == 0);
+ txchain0 = txchain & 0x1;
+ txchain1 = (txchain & 0x2) >> 1;
+ if (!txchain0)
+ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
- if (do_rssi_cal) {
- wlc_phy_rssi_cal_nphy(pi);
- } else {
- wlc_phy_restore_rssical_nphy(pi);
- }
- } else {
- wlc_phy_rssi_cal_nphy(pi);
- }
+ if (!txchain1)
+ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+}
- if (!SCAN_RM_IN_PROGRESS(pi)) {
- do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
- (pi->nphy_iqcal_chanspec_2G == 0) :
- (pi->nphy_iqcal_chanspec_5G == 0);
- }
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi)
+{
+ s8 lna1_gain_db[] = { 8, 13, 17, 22 };
+ s8 lna2_gain_db[] = { -2, 7, 11, 15 };
+ s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 };
+ s8 tia_gainbits[] = {
+ 0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
- if (!pi->do_initcal)
- do_nphy_cal = false;
+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
- if (do_nphy_cal) {
+ mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
- target_gain = wlc_phy_get_tx_gain_nphy(pi);
+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0));
+ mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0));
- if (pi->antsel_type == ANTSEL_2x3)
- wlc_phy_antsel_init((struct brcms_phy_pub *) pi,
- true);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8,
+ lna1_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8,
+ lna1_gain_db);
- if (pi->nphy_perical != PHY_PERICAL_MPHASE) {
- wlc_phy_rssi_cal_nphy(pi);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8,
+ lna2_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8,
+ lna2_gain_db);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- pi->nphy_cal_orig_pwr_idx[0] =
- pi->nphy_txpwrindex[PHY_CORE_0].
- index_internal;
- pi->nphy_cal_orig_pwr_idx[1] =
- pi->nphy_txpwrindex[PHY_CORE_1].
- index_internal;
-
- wlc_phy_precal_txgain_nphy(pi);
- target_gain =
- wlc_phy_get_tx_gain_nphy(pi);
- }
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+ tia_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+ tia_gain_db);
- if (wlc_phy_cal_txiqlo_nphy
- (pi, target_gain, true, false) == 0) {
- if (wlc_phy_cal_rxiq_nphy
- (pi, target_gain, 2,
- false) == 0) {
- wlc_phy_savecal_nphy(pi);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+ tia_gainbits);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+ tia_gainbits);
- }
- }
- } else if (pi->mphase_cal_phase_id ==
- MPHASE_CAL_STATE_IDLE) {
+ write_phy_reg(pi, 0x37, 0x74);
+ write_phy_reg(pi, 0x2ad, 0x74);
+ write_phy_reg(pi, 0x38, 0x18);
+ write_phy_reg(pi, 0x2ae, 0x18);
- wlc_phy_cal_perical((struct brcms_phy_pub *) pi,
- PHY_PERICAL_PHYINIT);
- }
- } else {
- wlc_phy_restorecal_nphy(pi);
- }
- }
+ write_phy_reg(pi, 0x2b, 0xe8);
+ write_phy_reg(pi, 0x41, 0xe8);
- wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
- wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+ mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0));
+ mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0));
+ } else {
- wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy);
+ mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0));
+ mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0));
+ }
+}
- if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6))
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi)
+{
+ u16 currband;
+ s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
+ s8 *lna1_gain_db = NULL;
+ s8 *lna1_gain_db_2 = NULL;
+ s8 *lna2_gain_db = NULL;
+ s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
+ s8 *tia_gain_db;
+ s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
+ s8 *tia_gainbits;
+ u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
+ u16 *rfseq_init_gain;
+ u16 init_gaincode;
+ u16 clip1hi_gaincode;
+ u16 clip1md_gaincode = 0;
+ u16 clip1md_gaincode_B;
+ u16 clip1lo_gaincode;
+ u16 clip1lo_gaincode_B;
+ u8 crsminl_th = 0;
+ u8 crsminu_th;
+ u16 nbclip_th = 0;
+ u8 w1clip_th;
+ u16 freq;
+ s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0;
+ u8 chg_nbclip_th = 0;
- write_phy_reg(pi, 0x70, 50);
+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
- wlc_phy_txlpfbw_nphy(pi);
+ currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+ if (currband == 0) {
- wlc_phy_spurwar_nphy(pi);
+ lna1_gain_db = lna1G_gain_db_rev7;
-}
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+ lna1_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+ lna1_gain_db);
-static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble)
-{
- bool gf_preamble = false;
- u16 val;
+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0));
- if (preamble == BRCMS_N_PREAMBLE_GF)
- gf_preamble = true;
+ if (CHSPEC_IS40(pi->radio_chanspec)) {
+ mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0));
+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0));
+ }
- val = read_phy_reg(pi, 0xed);
+ mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
- val |= RX_GF_MM_AUTO;
- val &= ~RX_GF_OR_MM;
- if (gf_preamble)
- val |= RX_GF_OR_MM;
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
+ mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0));
+ mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0));
+ }
+ } else {
- write_phy_reg(pi, 0xed, val);
-}
+ init_gaincode = 0x9e;
+ clip1hi_gaincode = 0x9e;
+ clip1md_gaincode_B = 0x24;
+ clip1lo_gaincode = 0x8a;
+ clip1lo_gaincode_B = 8;
+ rfseq_init_gain = rfseqA_init_gain_rev7;
-static void wlc_phy_resetcca_nphy(struct brcms_phy *pi)
-{
- u16 val;
+ tia_gain_db = tiaA_gain_db_rev7;
+ tia_gainbits = tiaA_gainbits_rev7;
- wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+ freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
- val = read_phy_reg(pi, 0x01);
- write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
- udelay(1);
- write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+ w1clip_th = 25;
+ clip1md_gaincode = 0x82;
- wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+ if ((freq <= 5080) || (freq == 5825)) {
- wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-}
+ s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
+ s8 lna1A_gain_db_2_rev7[] = {
+ 11, 17, 22, 25};
+ s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
-void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en)
-{
- u16 rfctrlintc_override_val;
+ crsminu_th = 0x3e;
+ lna1_gain_db = lna1A_gain_db_rev7;
+ lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+ lna2_gain_db = lna2A_gain_db_rev7;
+ } else if ((freq >= 5500) && (freq <= 5700)) {
- if (!en) {
+ s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
+ s8 lna1A_gain_db_2_rev7[] = {
+ 12, 18, 22, 26};
+ s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
- pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91);
- pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92);
+ crsminu_th = 0x45;
+ clip1md_gaincode_B = 0x14;
+ nbclip_th = 0xff;
+ chg_nbclip_th = 1;
+ lna1_gain_db = lna1A_gain_db_rev7;
+ lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+ lna2_gain_db = lna2A_gain_db_rev7;
+ } else {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- rfctrlintc_override_val = 0x1480;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- rfctrlintc_override_val =
- CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480;
+ s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
+ s8 lna1A_gain_db_2_rev7[] = {
+ 12, 18, 22, 26};
+ s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+
+ crsminu_th = 0x41;
+ lna1_gain_db = lna1A_gain_db_rev7;
+ lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+ lna2_gain_db = lna2A_gain_db_rev7;
+ }
+
+ if (freq <= 4920) {
+ nvar_baseline_offset0 = 5;
+ nvar_baseline_offset1 = 5;
+ } else if ((freq > 4920) && (freq <= 5320)) {
+ nvar_baseline_offset0 = 3;
+ nvar_baseline_offset1 = 5;
+ } else if ((freq > 5320) && (freq <= 5700)) {
+ nvar_baseline_offset0 = 3;
+ nvar_baseline_offset1 = 2;
+ } else {
+ nvar_baseline_offset0 = 4;
+ nvar_baseline_offset1 = 0;
+ }
} else {
- rfctrlintc_override_val =
- CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+
+ crsminu_th = 0x3a;
+ crsminl_th = 0x3a;
+ w1clip_th = 20;
+
+ if ((freq >= 4920) && (freq <= 5320)) {
+ nvar_baseline_offset0 = 4;
+ nvar_baseline_offset1 = 5;
+ } else if ((freq > 5320) && (freq <= 5550)) {
+ nvar_baseline_offset0 = 4;
+ nvar_baseline_offset1 = 2;
+ } else {
+ nvar_baseline_offset0 = 5;
+ nvar_baseline_offset1 = 3;
+ }
}
- write_phy_reg(pi, 0x91, rfctrlintc_override_val);
- write_phy_reg(pi, 0x92, rfctrlintc_override_val);
- } else {
+ write_phy_reg(pi, 0x20, init_gaincode);
+ write_phy_reg(pi, 0x2a7, init_gaincode);
- write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save);
- write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save);
- }
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+ pi->pubpi.phy_corenum, 0x106, 16,
+ rfseq_init_gain);
-}
+ write_phy_reg(pi, 0x22, clip1hi_gaincode);
+ write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
-void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi)
-{
+ write_phy_reg(pi, 0x36, clip1md_gaincode_B);
+ write_phy_reg(pi, 0x2ac, clip1md_gaincode_B);
- u16 txrx_chain =
- (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1);
- bool CoreActv_override = false;
+ write_phy_reg(pi, 0x37, clip1lo_gaincode);
+ write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+ write_phy_reg(pi, 0x38, clip1lo_gaincode_B);
+ write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B);
- if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN0) {
- txrx_chain = NPHY_RfseqCoreActv_TxRxChain0;
- CoreActv_override = true;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+ tia_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+ tia_gain_db);
- if (NREV_LE(pi->pubpi.phy_rev, 2)) {
- and_phy_reg(pi, 0xa0, ~0x20);
- }
- } else if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN1) {
- txrx_chain = NPHY_RfseqCoreActv_TxRxChain1;
- CoreActv_override = true;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+ tia_gainbits);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+ tia_gainbits);
- if (NREV_LE(pi->pubpi.phy_rev, 2)) {
- or_phy_reg(pi, 0xa0, 0x20);
+ mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+
+ if (chg_nbclip_th == 1) {
+ write_phy_reg(pi, 0x2b, nbclip_th);
+ write_phy_reg(pi, 0x41, nbclip_th);
}
- }
- mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain);
+ mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0));
+ mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0));
- if (CoreActv_override) {
+ mod_phy_reg(pi, 0x2e4,
+ (0x3f << 0), (nvar_baseline_offset0 << 0));
- pi->nphy_perical = PHY_PERICAL_DISABLE;
- or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
- } else {
- pi->nphy_perical = PHY_PERICAL_MPHASE;
- and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override);
+ mod_phy_reg(pi, 0x2e4,
+ (0x3f << 6), (nvar_baseline_offset1 << 6));
+
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+ lna1_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+ lna1_gain_db_2);
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+ 8, lna2_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+ 8, lna2_gain_db);
+
+ write_phy_reg(pi, 0x24, clip1md_gaincode);
+ write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+ } else {
+ mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+ }
}
}
-void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask)
+static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi)
{
- u16 regval;
- u16 tbl_buf[16];
- uint i;
- struct brcms_phy *pi = (struct brcms_phy *) pih;
- u16 tbl_opcode;
- bool suspend;
+ u16 w1th, hpf_code, currband;
+ int ctr;
+ u8 rfseq_updategainu_events[] = {
+ NPHY_RFSEQ_CMD_RX_GAIN,
+ NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
+ NPHY_RFSEQ_CMD_SET_HPF_BW
+ };
+ u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
+ s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
+ s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
+ s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
+ s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
+ s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
+ s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
+ s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
+ s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
+ s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
+ s8 *lna1_gain_db = NULL;
+ s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
+ s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
+ s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
+ s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
+ s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
+ s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
+ s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
+ s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
+ s8 *lna2_gain_db = NULL;
+ s8 tiaG_gain_db[] = {
+ 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
+ s8 tiaA_gain_db[] = {
+ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
+ s8 tiaA_gain_db_rev4[] = {
+ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+ s8 tiaA_gain_db_rev5[] = {
+ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+ s8 tiaA_gain_db_rev6[] = {
+ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+ s8 *tia_gain_db;
+ s8 tiaG_gainbits[] = {
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+ s8 tiaA_gainbits[] = {
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
+ s8 tiaA_gainbits_rev4[] = {
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+ s8 tiaA_gainbits_rev5[] = {
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+ s8 tiaA_gainbits_rev6[] = {
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+ s8 *tia_gainbits;
+ s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
+ s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
+ u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
+ u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
+ u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
+ u16 rfseqG_init_gain_rev5_elna[] = {
+ 0x013f, 0x013f, 0x013f, 0x013f };
+ u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
+ u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
+ u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
+ u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
+ u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
+ u16 rfseqA_init_gain_rev4_elna[] = {
+ 0x314f, 0x314f, 0x314f, 0x314f };
+ u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
+ u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
+ u16 *rfseq_init_gain;
+ u16 initG_gaincode = 0x627e;
+ u16 initG_gaincode_rev4 = 0x527e;
+ u16 initG_gaincode_rev5 = 0x427e;
+ u16 initG_gaincode_rev5_elna = 0x027e;
+ u16 initG_gaincode_rev6 = 0x527e;
+ u16 initG_gaincode_rev6_224B0 = 0x427e;
+ u16 initG_gaincode_rev6_elna = 0x127e;
+ u16 initA_gaincode = 0x52de;
+ u16 initA_gaincode_rev4 = 0x629e;
+ u16 initA_gaincode_rev4_elna = 0x329e;
+ u16 initA_gaincode_rev5 = 0x729e;
+ u16 initA_gaincode_rev6 = 0x729e;
+ u16 init_gaincode;
+ u16 clip1hiG_gaincode = 0x107e;
+ u16 clip1hiG_gaincode_rev4 = 0x007e;
+ u16 clip1hiG_gaincode_rev5 = 0x1076;
+ u16 clip1hiG_gaincode_rev6 = 0x007e;
+ u16 clip1hiA_gaincode = 0x00de;
+ u16 clip1hiA_gaincode_rev4 = 0x029e;
+ u16 clip1hiA_gaincode_rev5 = 0x029e;
+ u16 clip1hiA_gaincode_rev6 = 0x029e;
+ u16 clip1hi_gaincode;
+ u16 clip1mdG_gaincode = 0x0066;
+ u16 clip1mdA_gaincode = 0x00ca;
+ u16 clip1mdA_gaincode_rev4 = 0x1084;
+ u16 clip1mdA_gaincode_rev5 = 0x2084;
+ u16 clip1mdA_gaincode_rev6 = 0x2084;
+ u16 clip1md_gaincode = 0;
+ u16 clip1loG_gaincode = 0x0074;
+ u16 clip1loG_gaincode_rev5[] = {
+ 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c
+ };
+ u16 clip1loG_gaincode_rev6[] = {
+ 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e
+ };
+ u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
+ u16 clip1loA_gaincode = 0x00cc;
+ u16 clip1loA_gaincode_rev4 = 0x0086;
+ u16 clip1loA_gaincode_rev5 = 0x2086;
+ u16 clip1loA_gaincode_rev6 = 0x2086;
+ u16 clip1lo_gaincode;
+ u8 crsminG_th = 0x18;
+ u8 crsminG_th_rev5 = 0x18;
+ u8 crsminG_th_rev6 = 0x18;
+ u8 crsminA_th = 0x1e;
+ u8 crsminA_th_rev4 = 0x24;
+ u8 crsminA_th_rev5 = 0x24;
+ u8 crsminA_th_rev6 = 0x24;
+ u8 crsmin_th;
+ u8 crsminlG_th = 0x18;
+ u8 crsminlG_th_rev5 = 0x18;
+ u8 crsminlG_th_rev6 = 0x18;
+ u8 crsminlA_th = 0x1e;
+ u8 crsminlA_th_rev4 = 0x24;
+ u8 crsminlA_th_rev5 = 0x24;
+ u8 crsminlA_th_rev6 = 0x24;
+ u8 crsminl_th = 0;
+ u8 crsminuG_th = 0x18;
+ u8 crsminuG_th_rev5 = 0x18;
+ u8 crsminuG_th_rev6 = 0x18;
+ u8 crsminuA_th = 0x1e;
+ u8 crsminuA_th_rev4 = 0x24;
+ u8 crsminuA_th_rev5 = 0x24;
+ u8 crsminuA_th_rev6 = 0x24;
+ u8 crsminuA_th_rev6_224B0 = 0x2d;
+ u8 crsminu_th;
+ u16 nbclipG_th = 0x20d;
+ u16 nbclipG_th_rev4 = 0x1a1;
+ u16 nbclipG_th_rev5 = 0x1d0;
+ u16 nbclipG_th_rev6 = 0x1d0;
+ u16 nbclipA_th = 0x1a1;
+ u16 nbclipA_th_rev4 = 0x107;
+ u16 nbclipA_th_rev5 = 0x0a9;
+ u16 nbclipA_th_rev6 = 0x0f0;
+ u16 nbclip_th = 0;
+ u8 w1clipG_th = 5;
+ u8 w1clipG_th_rev5 = 9;
+ u8 w1clipG_th_rev6 = 5;
+ u8 w1clipA_th = 25, w1clip_th;
+ u8 rssi_gain_default = 0x50;
+ u8 rssiG_gain_rev6_224B0 = 0x50;
+ u8 rssiA_gain_rev5 = 0x90;
+ u8 rssiA_gain_rev6 = 0x90;
+ u8 rssi_gain;
+ u16 regval[21];
+ u8 triso;
- pi->sh->phyrxchain = rxcore_bitmask;
+ triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso :
+ pi->srom_fem2g.triso;
- if (!pi->sh->clk)
- return;
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (pi->pubpi.radiorev == 5) {
+ wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi);
+ } else if (pi->pubpi.radiorev == 7) {
+ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
- suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
- if (!suspend)
- wlapi_suspend_mac_and_wait(pi->sh->physhim);
+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0));
+ mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0));
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
+ } else if ((pi->pubpi.radiorev == 3)
+ || (pi->pubpi.radiorev == 8)) {
+ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
- regval = read_phy_reg(pi, 0xa2);
- regval &= ~(0xf << 4);
- regval |= ((u16) (rxcore_bitmask & 0x3)) << 4;
- write_phy_reg(pi, 0xa2, regval);
+ if (pi->pubpi.radiorev == 8) {
+ mod_phy_reg(pi, 0x283,
+ (0xff << 0), (0x44 << 0));
+ mod_phy_reg(pi, 0x280,
+ (0xff << 0), (0x44 << 0));
+ }
+ } else {
+ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+ }
+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if ((rxcore_bitmask & 0x3) != 0x3) {
+ mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6));
- write_phy_reg(pi, 0x20e, 1);
+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if (pi->rx2tx_biasentry == -1) {
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ,
- ARRAY_SIZE(tbl_buf), 80,
- 16, tbl_buf);
+ currband =
+ read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+ if (currband == 0) {
+ if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+ if (pi->pubpi.radiorev == 11) {
+ lna1_gain_db = lna1G_gain_db_rev6_224B0;
+ lna2_gain_db = lna2G_gain_db_rev6_224B0;
+ rfseq_init_gain =
+ rfseqG_init_gain_rev6_224B0;
+ init_gaincode =
+ initG_gaincode_rev6_224B0;
+ clip1hi_gaincode =
+ clip1hiG_gaincode_rev6;
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6_224B0;
+ nbclip_th = nbclipG_th_rev6;
+ w1clip_th = w1clipG_th_rev6;
+ crsmin_th = crsminG_th_rev6;
+ crsminl_th = crsminlG_th_rev6;
+ crsminu_th = crsminuG_th_rev6;
+ rssi_gain = rssiG_gain_rev6_224B0;
+ } else {
+ lna1_gain_db = lna1G_gain_db_rev6;
+ lna2_gain_db = lna2G_gain_db_rev6;
+ if (pi->sh->boardflags & BFL_EXTLNA) {
- for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) {
- if (tbl_buf[i] ==
- NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) {
+ rfseq_init_gain =
+ rfseqG_init_gain_rev6_elna;
+ init_gaincode =
+ initG_gaincode_rev6_elna;
+ } else {
+ rfseq_init_gain =
+ rfseqG_init_gain_rev6;
+ init_gaincode =
+ initG_gaincode_rev6;
+ }
+ clip1hi_gaincode =
+ clip1hiG_gaincode_rev6;
+ switch (triso) {
+ case 0:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [0];
+ break;
+ case 1:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [1];
+ break;
+ case 2:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [2];
+ break;
+ case 3:
+ default:
- pi->rx2tx_biasentry = (u8) i;
- tbl_opcode =
- NPHY_REV3_RFSEQ_CMD_NOP;
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_RFSEQ,
- 1, i,
- 16,
- &tbl_opcode);
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [3];
break;
- } else if (tbl_buf[i] ==
- NPHY_REV3_RFSEQ_CMD_END) {
+ case 4:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [4];
+ break;
+ case 5:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [5];
+ break;
+ case 6:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [6];
+ break;
+ case 7:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [7];
break;
}
+ nbclip_th = nbclipG_th_rev6;
+ w1clip_th = w1clipG_th_rev6;
+ crsmin_th = crsminG_th_rev6;
+ crsminl_th = crsminlG_th_rev6;
+ crsminu_th = crsminuG_th_rev6;
+ rssi_gain = rssi_gain_default;
+ }
+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+ lna1_gain_db = lna1G_gain_db_rev5;
+ lna2_gain_db = lna2G_gain_db_rev5;
+ if (pi->sh->boardflags & BFL_EXTLNA) {
+
+ rfseq_init_gain =
+ rfseqG_init_gain_rev5_elna;
+ init_gaincode =
+ initG_gaincode_rev5_elna;
+ } else {
+ rfseq_init_gain = rfseqG_init_gain_rev5;
+ init_gaincode = initG_gaincode_rev5;
}
+ clip1hi_gaincode = clip1hiG_gaincode_rev5;
+ switch (triso) {
+ case 0:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[0];
+ break;
+ case 1:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[1];
+ break;
+ case 2:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[2];
+ break;
+ case 3:
+
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[3];
+ break;
+ case 4:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[4];
+ break;
+ case 5:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[5];
+ break;
+ case 6:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[6];
+ break;
+ case 7:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[7];
+ break;
+ default:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[3];
+ break;
+ }
+ nbclip_th = nbclipG_th_rev5;
+ w1clip_th = w1clipG_th_rev5;
+ crsmin_th = crsminG_th_rev5;
+ crsminl_th = crsminlG_th_rev5;
+ crsminu_th = crsminuG_th_rev5;
+ rssi_gain = rssi_gain_default;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+ lna1_gain_db = lna1G_gain_db_rev4;
+ lna2_gain_db = lna2G_gain_db;
+ rfseq_init_gain = rfseqG_init_gain_rev4;
+ init_gaincode = initG_gaincode_rev4;
+ clip1hi_gaincode = clip1hiG_gaincode_rev4;
+ clip1lo_gaincode = clip1loG_gaincode;
+ nbclip_th = nbclipG_th_rev4;
+ w1clip_th = w1clipG_th;
+ crsmin_th = crsminG_th;
+ crsminl_th = crsminlG_th;
+ crsminu_th = crsminuG_th;
+ rssi_gain = rssi_gain_default;
+ } else {
+ lna1_gain_db = lna1G_gain_db;
+ lna2_gain_db = lna2G_gain_db;
+ rfseq_init_gain = rfseqG_init_gain;
+ init_gaincode = initG_gaincode;
+ clip1hi_gaincode = clip1hiG_gaincode;
+ clip1lo_gaincode = clip1loG_gaincode;
+ nbclip_th = nbclipG_th;
+ w1clip_th = w1clipG_th;
+ crsmin_th = crsminG_th;
+ crsminl_th = crsminlG_th;
+ crsminu_th = crsminuG_th;
+ rssi_gain = rssi_gain_default;
}
- }
- } else {
+ tia_gain_db = tiaG_gain_db;
+ tia_gainbits = tiaG_gainbits;
+ clip1md_gaincode = clip1mdG_gaincode;
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+ lna1_gain_db = lna1A_gain_db_rev6;
+ lna2_gain_db = lna2A_gain_db_rev6;
+ tia_gain_db = tiaA_gain_db_rev6;
+ tia_gainbits = tiaA_gainbits_rev6;
+ rfseq_init_gain = rfseqA_init_gain_rev6;
+ init_gaincode = initA_gaincode_rev6;
+ clip1hi_gaincode = clip1hiA_gaincode_rev6;
+ clip1md_gaincode = clip1mdA_gaincode_rev6;
+ clip1lo_gaincode = clip1loA_gaincode_rev6;
+ crsmin_th = crsminA_th_rev6;
+ crsminl_th = crsminlA_th_rev6;
+ if ((pi->pubpi.radiorev == 11) &&
+ (CHSPEC_IS40(pi->radio_chanspec) == 0))
+ crsminu_th = crsminuA_th_rev6_224B0;
+ else
+ crsminu_th = crsminuA_th_rev6;
- write_phy_reg(pi, 0x20e, 30);
+ nbclip_th = nbclipA_th_rev6;
+ rssi_gain = rssiA_gain_rev6;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+ lna1_gain_db = lna1A_gain_db_rev5;
+ lna2_gain_db = lna2A_gain_db_rev5;
+ tia_gain_db = tiaA_gain_db_rev5;
+ tia_gainbits = tiaA_gainbits_rev5;
+ rfseq_init_gain = rfseqA_init_gain_rev5;
+ init_gaincode = initA_gaincode_rev5;
+ clip1hi_gaincode = clip1hiA_gaincode_rev5;
+ clip1md_gaincode = clip1mdA_gaincode_rev5;
+ clip1lo_gaincode = clip1loA_gaincode_rev5;
+ crsmin_th = crsminA_th_rev5;
+ crsminl_th = crsminlA_th_rev5;
+ crsminu_th = crsminuA_th_rev5;
+ nbclip_th = nbclipA_th_rev5;
+ rssi_gain = rssiA_gain_rev5;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+ lna1_gain_db = lna1A_gain_db_rev4;
+ lna2_gain_db = lna2A_gain_db_rev4;
+ tia_gain_db = tiaA_gain_db_rev4;
+ tia_gainbits = tiaA_gainbits_rev4;
+ if (pi->sh->boardflags & BFL_EXTLNA_5GHz) {
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if (pi->rx2tx_biasentry != -1) {
- tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1, pi->rx2tx_biasentry,
- 16, &tbl_opcode);
- pi->rx2tx_biasentry = -1;
+ rfseq_init_gain =
+ rfseqA_init_gain_rev4_elna;
+ init_gaincode =
+ initA_gaincode_rev4_elna;
+ } else {
+ rfseq_init_gain = rfseqA_init_gain_rev4;
+ init_gaincode = initA_gaincode_rev4;
+ }
+ clip1hi_gaincode = clip1hiA_gaincode_rev4;
+ clip1md_gaincode = clip1mdA_gaincode_rev4;
+ clip1lo_gaincode = clip1loA_gaincode_rev4;
+ crsmin_th = crsminA_th_rev4;
+ crsminl_th = crsminlA_th_rev4;
+ crsminu_th = crsminuA_th_rev4;
+ nbclip_th = nbclipA_th_rev4;
+ rssi_gain = rssi_gain_default;
+ } else {
+ lna1_gain_db = lna1A_gain_db;
+ lna2_gain_db = lna2A_gain_db;
+ tia_gain_db = tiaA_gain_db;
+ tia_gainbits = tiaA_gainbits;
+ rfseq_init_gain = rfseqA_init_gain;
+ init_gaincode = initA_gaincode;
+ clip1hi_gaincode = clip1hiA_gaincode;
+ clip1md_gaincode = clip1mdA_gaincode;
+ clip1lo_gaincode = clip1loA_gaincode;
+ crsmin_th = crsminA_th;
+ crsminl_th = crsminlA_th;
+ crsminu_th = crsminuA_th;
+ nbclip_th = nbclipA_th;
+ rssi_gain = rssi_gain_default;
}
+ w1clip_th = w1clipA_th;
}
- }
- wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+ write_radio_reg(pi,
+ (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+ RADIO_2056_RX0), 0x17);
+ write_radio_reg(pi,
+ (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+ RADIO_2056_RX1), 0x17);
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
+ write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0),
+ 0xf0);
+ write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1),
+ 0xf0);
- if (!suspend)
- wlapi_enable_mac(pi->sh->physhim);
-}
+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0),
+ 0x0);
+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1),
+ 0x0);
-u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih)
-{
- u16 regval, rxen_bits;
- struct brcms_phy *pi = (struct brcms_phy *) pih;
+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0),
+ rssi_gain);
+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1),
+ rssi_gain);
- regval = read_phy_reg(pi, 0xa2);
- rxen_bits = (regval >> 4) & 0xf;
+ write_radio_reg(pi,
+ (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+ RADIO_2056_RX0), 0x17);
+ write_radio_reg(pi,
+ (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+ RADIO_2056_RX1), 0x17);
- return (u8) rxen_bits;
-}
+ write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0),
+ 0xFF);
+ write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1),
+ 0xFF);
-bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pi)
-{
- return PHY_IPA(pi);
-}
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8,
+ 8, lna1_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8,
+ 8, lna1_gain_db);
-static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi)
-{
- u8 idx, idx2, i, delta_ind;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+ 8, lna2_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+ 8, lna2_gain_db);
- for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) {
- pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx];
- }
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20,
+ 8, tia_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20,
+ 8, tia_gain_db);
- for (i = 0; i < 4; i++) {
- idx2 = 0;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20,
+ 8, tia_gainbits);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20,
+ 8, tia_gainbits);
- delta_ind = 0;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40,
+ 8, &lpf_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40,
+ 8, &lpf_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40,
+ 8, &lpf_gainbits);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40,
+ 8, &lpf_gainbits);
- switch (i) {
- case 0:
+ write_phy_reg(pi, 0x20, init_gaincode);
+ write_phy_reg(pi, 0x2a7, init_gaincode);
- if (CHSPEC_IS40(pi->radio_chanspec)
- && NPHY_IS_SROM_REINTERPRET) {
- idx = TXP_FIRST_MCS_40_SISO;
- } else {
- idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
- TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM;
- delta_ind = 1;
- }
- break;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+ pi->pubpi.phy_corenum, 0x106, 16,
+ rfseq_init_gain);
- case 1:
+ write_phy_reg(pi, 0x22, clip1hi_gaincode);
+ write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
- idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
- TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD;
- break;
+ write_phy_reg(pi, 0x24, clip1md_gaincode);
+ write_phy_reg(pi, 0x2ab, clip1md_gaincode);
- case 2:
+ write_phy_reg(pi, 0x37, clip1lo_gaincode);
+ write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
- idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
- TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC;
- break;
+ mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0));
+ mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+ mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
- case 3:
+ write_phy_reg(pi, 0x2b, nbclip_th);
+ write_phy_reg(pi, 0x41, nbclip_th);
- idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
- TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM;
- break;
+ mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0));
+ mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0));
+
+ write_phy_reg(pi, 0x150, 0x809c);
+
+ } else {
+
+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+ write_phy_reg(pi, 0x2b, 0x84);
+ write_phy_reg(pi, 0x41, 0x84);
+
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
+ write_phy_reg(pi, 0x6b, 0x2b);
+ write_phy_reg(pi, 0x6c, 0x2b);
+ write_phy_reg(pi, 0x6d, 0x9);
+ write_phy_reg(pi, 0x6e, 0x9);
}
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- idx = idx + delta_ind;
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
+ w1th = NPHY_RSSICAL_W1_TARGET - 4;
+ mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0));
+ mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0));
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
+ mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0));
+ mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0));
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
+ mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0));
+ mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0));
+ }
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- idx = idx + 1 - delta_ind;
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
+ write_phy_reg(pi, 0x150, 0x809c);
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- }
-}
+ if (pi->nphy_gain_boost)
+ if ((CHSPEC_IS2G(pi->radio_chanspec)) &&
+ (CHSPEC_IS40(pi->radio_chanspec)))
+ hpf_code = 4;
+ else
+ hpf_code = 5;
+ else if (CHSPEC_IS40(pi->radio_chanspec))
+ hpf_code = 6;
+ else
+ hpf_code = 7;
-void wlc_phy_cal_init_nphy(struct brcms_phy *pi)
-{
-}
+ mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7));
+ mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7));
-static void
-wlc_phy_war_force_trsw_to_R_cliplo_nphy(struct brcms_phy *pi, u8 core)
-{
- if (core == PHY_CORE_0) {
- write_phy_reg(pi, 0x38, 0x4);
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- write_phy_reg(pi, 0x37, 0x0060);
- } else {
- write_phy_reg(pi, 0x37, 0x1080);
+ for (ctr = 0; ctr < 4; ctr++)
+ regval[ctr] = (hpf_code << 8) | 0x7c;
+ wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+
+ wlc_phy_adjust_lnagaintbl_nphy(pi);
+
+ if (pi->nphy_elna_gain_config) {
+ regval[0] = 0;
+ regval[1] = 1;
+ regval[2] = 1;
+ regval[3] = 1;
+ wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval);
+ wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval);
+
+ for (ctr = 0; ctr < 4; ctr++)
+ regval[ctr] = (hpf_code << 8) | 0x74;
+ wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
}
- } else if (core == PHY_CORE_1) {
- write_phy_reg(pi, 0x2ae, 0x4);
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- write_phy_reg(pi, 0x2ad, 0x0060);
- } else {
- write_phy_reg(pi, 0x2ad, 0x1080);
+
+ if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+ for (ctr = 0; ctr < 21; ctr++)
+ regval[ctr] = 3 * ctr;
+ wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval);
+ wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval);
+
+ for (ctr = 0; ctr < 21; ctr++)
+ regval[ctr] = (u16) ctr;
+ wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval);
+ wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval);
}
- }
-}
-static void wlc_phy_war_txchain_upd_nphy(struct brcms_phy *pi, u8 txchain)
-{
- u8 txchain0, txchain1;
+ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU,
+ rfseq_updategainu_events,
+ rfseq_updategainu_dlys,
+ sizeof(rfseq_updategainu_events) /
+ sizeof(rfseq_updategainu_events[0]));
- txchain0 = txchain & 0x1;
- txchain1 = (txchain & 0x2) >> 1;
- if (!txchain0) {
- wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
- }
+ mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8));
- if (!txchain1) {
- wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ mod_phy_reg(pi,
+ (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES),
+ 0x7f, 0x4);
}
}
@@ -15362,11 +16312,10 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
u16 freq;
int coreNum;
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0);
- } else {
+ else
wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1);
- }
if (pi->phyhang_avoid)
wlc_phy_stay_in_carriersearch_nphy(pi, true);
@@ -15401,9 +16350,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
write_phy_reg(pi, 0x240, 0x1b0);
}
- if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 8))
mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0));
- }
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
&dac_control);
@@ -15422,7 +16370,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16,
rfseq_rx2tx_dacbufpu_rev7);
- if (PHY_IPA(pi)) {
+ if (PHY_IPA(pi))
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
rfseq_rx2tx_events_rev3_ipa,
rfseq_rx2tx_dlys_rev3_ipa,
@@ -15431,7 +16379,6 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
sizeof
(rfseq_rx2tx_events_rev3_ipa
[0]));
- }
mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14));
mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14));
@@ -15448,11 +16395,13 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
|| (pi->pubpi.radiorev == 8)) {
rccal_bcap_val =
- read_radio_reg(pi,
- RADIO_2057_RCCAL_BCAP_VAL);
+ read_radio_reg(
+ pi,
+ RADIO_2057_RCCAL_BCAP_VAL);
rccal_scap_val =
- read_radio_reg(pi,
- RADIO_2057_RCCAL_SCAP_VAL);
+ read_radio_reg(
+ pi,
+ RADIO_2057_RCCAL_SCAP_VAL);
rccal_tx20_11b_bcap = rccal_bcap_val;
rccal_tx20_11b_scap = rccal_scap_val;
@@ -15497,11 +16446,13 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
tx_lpf_bw_ofdm_40mhz = 3;
rccal_bcap_val =
- read_radio_reg(pi,
- RADIO_2057_RCCAL_BCAP_VAL);
+ read_radio_reg(
+ pi,
+ RADIO_2057_RCCAL_BCAP_VAL);
rccal_scap_val =
- read_radio_reg(pi,
- RADIO_2057_RCCAL_SCAP_VAL);
+ read_radio_reg(
+ pi,
+ RADIO_2057_RCCAL_SCAP_VAL);
rccal_tx20_11b_bcap = rccal_bcap_val;
rccal_tx20_11b_scap = rccal_scap_val;
@@ -15517,70 +16468,83 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
if (rccal_ovrd) {
- rx2tx_lpf_rc_lut_tx20_11b = (rccal_tx20_11b_bcap << 8) |
- (rccal_tx20_11b_scap << 3) | tx_lpf_bw_11b;
- rx2tx_lpf_rc_lut_tx20_11n = (rccal_tx20_11n_bcap << 8) |
- (rccal_tx20_11n_scap << 3) | tx_lpf_bw_ofdm_20mhz;
- rx2tx_lpf_rc_lut_tx40_11n = (rccal_tx40_11n_bcap << 8) |
- (rccal_tx40_11n_scap << 3) | tx_lpf_bw_ofdm_40mhz;
+ rx2tx_lpf_rc_lut_tx20_11b =
+ (rccal_tx20_11b_bcap << 8) |
+ (rccal_tx20_11b_scap << 3) |
+ tx_lpf_bw_11b;
+ rx2tx_lpf_rc_lut_tx20_11n =
+ (rccal_tx20_11n_bcap << 8) |
+ (rccal_tx20_11n_scap << 3) |
+ tx_lpf_bw_ofdm_20mhz;
+ rx2tx_lpf_rc_lut_tx40_11n =
+ (rccal_tx40_11n_bcap << 8) |
+ (rccal_tx40_11n_scap << 3) |
+ tx_lpf_bw_ofdm_40mhz;
for (coreNum = 0; coreNum <= 1; coreNum++) {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x152 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx20_11b);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x153 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx20_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x154 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx20_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x155 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx40_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x156 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx40_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x157 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx40_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x158 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx40_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x159 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx40_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x152 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx20_11b);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x153 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx20_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x154 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx20_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x155 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx40_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x156 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx40_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x157 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx40_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x158 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx40_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x159 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx40_11n);
}
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
- 1, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 4),
+ 1, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
}
- if (!NORADIO_ENAB(pi->pubpi)) {
- write_phy_reg(pi, 0x32f, 0x3);
- }
+ write_phy_reg(pi, 0x32f, 0x3);
- if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
- 1, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- }
+ if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2),
+ 1, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) ||
(pi->pubpi.radiorev == 6)) {
@@ -15635,17 +16599,16 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if ((pi->pubpi.radiorev == 3)
|| (pi->pubpi.radiorev == 4)
- || (pi->pubpi.radiorev == 6)) {
-
+ || (pi->pubpi.radiorev == 6))
txgm_idac_bleed = 0x7f;
- }
for (coreNum = 0; coreNum <= 1; coreNum++) {
if (txgm_idac_bleed != 0)
- WRITE_RADIO_REG4(pi, RADIO_2057,
- CORE, coreNum,
- TXGM_IDAC_BLEED,
- txgm_idac_bleed);
+ WRITE_RADIO_REG4(
+ pi, RADIO_2057,
+ CORE, coreNum,
+ TXGM_IDAC_BLEED,
+ txgm_idac_bleed);
}
if (pi->pubpi.radiorev == 5) {
@@ -15660,18 +16623,20 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
CORE, coreNum,
IPA2G_IMAIN,
0x1f);
- WRITE_RADIO_REG4(pi, RADIO_2057,
- CORE, coreNum,
- IPA2G_BIAS_FILTER,
- 0xee);
+ WRITE_RADIO_REG4(
+ pi, RADIO_2057,
+ CORE, coreNum,
+ IPA2G_BIAS_FILTER,
+ 0xee);
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, coreNum,
PAD2G_IDACS,
0x8a);
- WRITE_RADIO_REG4(pi, RADIO_2057,
- CORE, coreNum,
- PAD_BIAS_FILTER_BWS,
- 0x3e);
+ WRITE_RADIO_REG4(
+ pi, RADIO_2057,
+ CORE, coreNum,
+ PAD_BIAS_FILTER_BWS,
+ 0x3e);
}
} else if ((pi->pubpi.radiorev == 7)
@@ -15700,9 +16665,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
}
} else {
- freq =
- CHAN5G_FREQ(CHSPEC_CHANNEL
- (pi->radio_chanspec));
+ freq = CHAN5G_FREQ(CHSPEC_CHANNEL(
+ pi->radio_chanspec));
if (((freq >= 5180) && (freq <= 5230))
|| ((freq >= 5745) && (freq <= 5805))) {
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
@@ -15809,12 +16773,12 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
wlc_phy_workarounds_nphy_gainctrl(pi);
pdetrange =
- (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
- pdetrange : pi->srom_fem2g.pdetrange;
+ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+ pdetrange : pi->srom_fem2g.pdetrange;
if (pdetrange == 0) {
chan_freq_range =
- wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] = 0x70;
aux_adc_vmid_rev7_core1[3] = 0x70;
@@ -15842,15 +16806,15 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
if (chan_freq_range ==
WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] =
- 0x8c;
+ 0x8c;
aux_adc_vmid_rev7_core1[3] =
- 0x8c;
+ 0x8c;
aux_adc_gain_rev7[3] = 0;
} else {
aux_adc_vmid_rev7_core0[3] =
- 0x96;
+ 0x96;
aux_adc_vmid_rev7_core1[3] =
- 0x96;
+ 0x96;
aux_adc_gain_rev7[3] = 0;
}
}
@@ -15918,7 +16882,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
sizeof(rfseq_tx2rx_events_rev3) /
sizeof(rfseq_tx2rx_events_rev3[0]));
- if (PHY_IPA(pi)) {
+ if (PHY_IPA(pi))
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
rfseq_rx2tx_events_rev3_ipa,
rfseq_rx2tx_dlys_rev3_ipa,
@@ -15927,7 +16891,6 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
sizeof
(rfseq_rx2tx_events_rev3_ipa
[0]));
- }
if ((pi->sh->hw_phyrxchain != 0x3) &&
(pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) {
@@ -15936,22 +16899,21 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
rfseq_rx2tx_dlys_rev3[5] = 59;
rfseq_rx2tx_dlys_rev3[6] = 1;
rfseq_rx2tx_events_rev3[7] =
- NPHY_REV3_RFSEQ_CMD_END;
+ NPHY_REV3_RFSEQ_CMD_END;
}
- wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
- rfseq_rx2tx_events_rev3,
- rfseq_rx2tx_dlys_rev3,
- sizeof(rfseq_rx2tx_events_rev3) /
- sizeof(rfseq_rx2tx_events_rev3
- [0]));
+ wlc_phy_set_rfseq_nphy(
+ pi, NPHY_RFSEQ_RX2TX,
+ rfseq_rx2tx_events_rev3,
+ rfseq_rx2tx_dlys_rev3,
+ sizeof(rfseq_rx2tx_events_rev3) /
+ sizeof(rfseq_rx2tx_events_rev3[0]));
}
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec))
write_phy_reg(pi, 0x6a, 0x2);
- } else {
+ else
write_phy_reg(pi, 0x6a, 0x9c40);
- }
mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8));
@@ -15978,8 +16940,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
&dac_control);
pdetrange =
- (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
- pdetrange : pi->srom_fem2g.pdetrange;
+ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+ pdetrange : pi->srom_fem2g.pdetrange;
if (pdetrange == 0) {
if (NREV_GE(pi->pubpi.phy_rev, 4)) {
@@ -15990,7 +16952,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
aux_adc_gain = aux_adc_gain_rev3;
}
chan_freq_range =
- wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
switch (chan_freq_range) {
case WL_CHAN_FREQ_RANGE_5GL:
@@ -16033,7 +16995,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
if (NREV_GE(pi->pubpi.phy_rev, 6)) {
chan_freq_range =
- wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
bcm_adc_vmid[3] = 0x8e;
bcm_adc_gain[3] = 0x03;
@@ -16056,14 +17018,16 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
0x1c, 16, bcm_adc_gain);
} else if (pdetrange == 3) {
chan_freq_range =
- wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ wlc_phy_get_chan_freq_range_nphy(pi, 0);
if ((NREV_GE(pi->pubpi.phy_rev, 4))
&& (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) {
u16 auxadc_vmid[] = {
- 0xa2, 0xb4, 0xb4, 0x270 };
+ 0xa2, 0xb4, 0xb4, 0x270
+ };
u16 auxadc_gain[] = {
- 0x02, 0x02, 0x02, 0x00 };
+ 0x02, 0x02, 0x02, 0x00
+ };
wlc_phy_table_write_nphy(pi,
NPHY_TBL_ID_AFECTRL, 4,
@@ -16084,7 +17048,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
u16 Vmid[2], Av[2];
chan_freq_range =
- wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89;
Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89;
@@ -16155,8 +17119,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
0x0);
triso =
- (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
- triso : pi->srom_fem2g.triso;
+ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+ triso : pi->srom_fem2g.triso;
if (triso == 7) {
wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
@@ -16212,11 +17176,10 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
if (NREV_GE(pi->pubpi.phy_rev, 6)) {
- if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) {
+ if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK)
wlapi_bmac_mhf(pi->sh->physhim, MHF4,
- MHF4_BPHY_TXCORE0,
- MHF4_BPHY_TXCORE0, BRCM_BAND_ALL);
- }
+ MHF4_BPHY_TXCORE0,
+ MHF4_BPHY_TXCORE0, BRCM_BAND_ALL);
}
} else {
@@ -16314,1121 +17277,2720 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
write_phy_reg(pi, 0x194, 0x0);
}
- if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+ if (NREV_IS(pi->pubpi.phy_rev, 2))
mod_phy_reg(pi, 0x221,
NPHY_FORCESIG_DECODEGATEDCLKS,
NPHY_FORCESIG_DECODEGATEDCLKS);
- }
}
if (pi->phyhang_avoid)
wlc_phy_stay_in_carriersearch_nphy(pi, false);
}
-static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi)
+static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
{
- u16 w1th, hpf_code, currband;
- int ctr;
- u8 rfseq_updategainu_events[] = {
- NPHY_RFSEQ_CMD_RX_GAIN,
- NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
- NPHY_RFSEQ_CMD_SET_HPF_BW
- };
- u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
- s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
- s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
- s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
- s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
- s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
- s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
- s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
- s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
- s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
- s8 *lna1_gain_db = NULL;
- s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
- s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
- s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
- s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
- s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
- s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
- s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
- s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
- s8 *lna2_gain_db = NULL;
- s8 tiaG_gain_db[] = {
- 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
- s8 tiaA_gain_db[] = {
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
- s8 tiaA_gain_db_rev4[] = {
- 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
- s8 tiaA_gain_db_rev5[] = {
- 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
- s8 tiaA_gain_db_rev6[] = {
- 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
- s8 *tia_gain_db;
- s8 tiaG_gainbits[] = {
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
- s8 tiaA_gainbits[] = {
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
- s8 tiaA_gainbits_rev4[] = {
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
- s8 tiaA_gainbits_rev5[] = {
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
- s8 tiaA_gainbits_rev6[] = {
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
- s8 *tia_gainbits;
- s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
- s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
- u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
- u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
- u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
- u16 rfseqG_init_gain_rev5_elna[] = {
- 0x013f, 0x013f, 0x013f, 0x013f };
- u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
- u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
- u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
- u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
- u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
- u16 rfseqA_init_gain_rev4_elna[] = {
- 0x314f, 0x314f, 0x314f, 0x314f };
- u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
- u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
- u16 *rfseq_init_gain;
- u16 initG_gaincode = 0x627e;
- u16 initG_gaincode_rev4 = 0x527e;
- u16 initG_gaincode_rev5 = 0x427e;
- u16 initG_gaincode_rev5_elna = 0x027e;
- u16 initG_gaincode_rev6 = 0x527e;
- u16 initG_gaincode_rev6_224B0 = 0x427e;
- u16 initG_gaincode_rev6_elna = 0x127e;
- u16 initA_gaincode = 0x52de;
- u16 initA_gaincode_rev4 = 0x629e;
- u16 initA_gaincode_rev4_elna = 0x329e;
- u16 initA_gaincode_rev5 = 0x729e;
- u16 initA_gaincode_rev6 = 0x729e;
- u16 init_gaincode;
- u16 clip1hiG_gaincode = 0x107e;
- u16 clip1hiG_gaincode_rev4 = 0x007e;
- u16 clip1hiG_gaincode_rev5 = 0x1076;
- u16 clip1hiG_gaincode_rev6 = 0x007e;
- u16 clip1hiA_gaincode = 0x00de;
- u16 clip1hiA_gaincode_rev4 = 0x029e;
- u16 clip1hiA_gaincode_rev5 = 0x029e;
- u16 clip1hiA_gaincode_rev6 = 0x029e;
- u16 clip1hi_gaincode;
- u16 clip1mdG_gaincode = 0x0066;
- u16 clip1mdA_gaincode = 0x00ca;
- u16 clip1mdA_gaincode_rev4 = 0x1084;
- u16 clip1mdA_gaincode_rev5 = 0x2084;
- u16 clip1mdA_gaincode_rev6 = 0x2084;
- u16 clip1md_gaincode = 0;
- u16 clip1loG_gaincode = 0x0074;
- u16 clip1loG_gaincode_rev5[] = {
- 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c
- };
- u16 clip1loG_gaincode_rev6[] = {
- 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e
- };
- u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
- u16 clip1loA_gaincode = 0x00cc;
- u16 clip1loA_gaincode_rev4 = 0x0086;
- u16 clip1loA_gaincode_rev5 = 0x2086;
- u16 clip1loA_gaincode_rev6 = 0x2086;
- u16 clip1lo_gaincode;
- u8 crsminG_th = 0x18;
- u8 crsminG_th_rev5 = 0x18;
- u8 crsminG_th_rev6 = 0x18;
- u8 crsminA_th = 0x1e;
- u8 crsminA_th_rev4 = 0x24;
- u8 crsminA_th_rev5 = 0x24;
- u8 crsminA_th_rev6 = 0x24;
- u8 crsmin_th;
- u8 crsminlG_th = 0x18;
- u8 crsminlG_th_rev5 = 0x18;
- u8 crsminlG_th_rev6 = 0x18;
- u8 crsminlA_th = 0x1e;
- u8 crsminlA_th_rev4 = 0x24;
- u8 crsminlA_th_rev5 = 0x24;
- u8 crsminlA_th_rev6 = 0x24;
- u8 crsminl_th = 0;
- u8 crsminuG_th = 0x18;
- u8 crsminuG_th_rev5 = 0x18;
- u8 crsminuG_th_rev6 = 0x18;
- u8 crsminuA_th = 0x1e;
- u8 crsminuA_th_rev4 = 0x24;
- u8 crsminuA_th_rev5 = 0x24;
- u8 crsminuA_th_rev6 = 0x24;
- u8 crsminuA_th_rev6_224B0 = 0x2d;
- u8 crsminu_th;
- u16 nbclipG_th = 0x20d;
- u16 nbclipG_th_rev4 = 0x1a1;
- u16 nbclipG_th_rev5 = 0x1d0;
- u16 nbclipG_th_rev6 = 0x1d0;
- u16 nbclipA_th = 0x1a1;
- u16 nbclipA_th_rev4 = 0x107;
- u16 nbclipA_th_rev5 = 0x0a9;
- u16 nbclipA_th_rev6 = 0x0f0;
- u16 nbclip_th = 0;
- u8 w1clipG_th = 5;
- u8 w1clipG_th_rev5 = 9;
- u8 w1clipG_th_rev6 = 5;
- u8 w1clipA_th = 25, w1clip_th;
- u8 rssi_gain_default = 0x50;
- u8 rssiG_gain_rev6_224B0 = 0x50;
- u8 rssiA_gain_rev5 = 0x90;
- u8 rssiA_gain_rev6 = 0x90;
- u8 rssi_gain;
- u16 regval[21];
- u8 triso;
+ int j, type = 2;
+ u16 addr_offset = 0x2c5;
- triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso :
- pi->srom_fem2g.triso;
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, addr_offset + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
+}
+
+static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals)
+{
+
+ if (write == 0) {
+ vals[0] = read_phy_reg(pi, 0x2c);
+ vals[1] = read_phy_reg(pi, 0x42);
+ } else {
+ write_phy_reg(pi, 0x2c, vals[0]);
+ write_phy_reg(pi, 0x42, vals[1]);
+ }
+}
+
+static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi)
+{
+ u8 core;
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (pi->pubpi.radiorev == 5) {
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MASTER, 0x5);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MUX, 0xe);
- wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi);
- } else if (pi->pubpi.radiorev == 7) {
- wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+ if (pi->pubpi.radiorev != 5)
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+ core, TSSIA, 0);
- mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0));
- mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0));
+ if (!NREV_IS(pi->pubpi.phy_rev, 7))
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+ core, TSSIG, 0x1);
+ else
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+ core, TSSIG, 0x31);
+ } else {
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MASTER, 0x9);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MUX, 0xc);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TSSIG, 0);
- } else if ((pi->pubpi.radiorev == 3)
- || (pi->pubpi.radiorev == 8)) {
- wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+ if (pi->pubpi.radiorev != 5) {
+ if (!NREV_IS(pi->pubpi.phy_rev, 7))
+ WRITE_RADIO_REG3(pi, RADIO_2057,
+ TX, core,
+ TSSIA, 0x1);
+ else
+ WRITE_RADIO_REG3(pi, RADIO_2057,
+ TX, core,
+ TSSIA, 0x31);
+ }
+ }
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
+ 0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
+ 0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
+ 0x3);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
+ 0x0);
+ }
+ } else {
+ WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31,
+ (CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 :
+ 0x80);
+ WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0);
+ WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29);
- if (pi->pubpi.radiorev == 8) {
- mod_phy_reg(pi, 0x283,
- (0xff << 0), (0x44 << 0));
- mod_phy_reg(pi, 0x280,
- (0xff << 0), (0x44 << 0));
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG,
+ 0x0);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC,
+ 0x0);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM,
+ 0x3);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET,
+ 0x0);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1,
+ 0x8);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2,
+ 0x0);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3,
+ 0x0);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TX_SSI_MASTER, 0x5);
+
+ if (pi->pubpi.radiorev != 5)
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+ core, TSSIA, 0x0);
+ if (NREV_GE(pi->pubpi.phy_rev, 5))
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+ core, TSSIG, 0x31);
+ else
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+ core, TSSIG, 0x11);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TX_SSI_MUX, 0xe);
+ } else {
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TX_SSI_MASTER, 0x9);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TSSIA, 0x31);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TSSIG, 0x0);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TX_SSI_MUX, 0xc);
}
- } else {
- wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
}
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ }
+}
- mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6));
+static void
+wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value,
+ u8 core_mask, u8 off)
+{
+ u8 core_num;
+ u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask =
+ 0, val_mask = 0;
+ u8 shift = 0, val_shift = 0;
- mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
- mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
- currband =
- read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
- if (currband == 0) {
- if (NREV_GE(pi->pubpi.phy_rev, 6)) {
- if (pi->pubpi.radiorev == 11) {
- lna1_gain_db = lna1G_gain_db_rev6_224B0;
- lna2_gain_db = lna2G_gain_db_rev6_224B0;
- rfseq_init_gain =
- rfseqG_init_gain_rev6_224B0;
- init_gaincode =
- initG_gaincode_rev6_224B0;
- clip1hi_gaincode =
- clip1hiG_gaincode_rev6;
- clip1lo_gaincode =
- clip1loG_gaincode_rev6_224B0;
- nbclip_th = nbclipG_th_rev6;
- w1clip_th = w1clipG_th_rev6;
- crsmin_th = crsminG_th_rev6;
- crsminl_th = crsminlG_th_rev6;
- crsminu_th = crsminuG_th_rev6;
- rssi_gain = rssiG_gain_rev6_224B0;
- } else {
- lna1_gain_db = lna1G_gain_db_rev6;
- lna2_gain_db = lna2G_gain_db_rev6;
- if (pi->sh->boardflags & BFL_EXTLNA) {
+ en_mask = field;
+ for (core_num = 0; core_num < 2; core_num++) {
- rfseq_init_gain =
- rfseqG_init_gain_rev6_elna;
- init_gaincode =
- initG_gaincode_rev6_elna;
- } else {
- rfseq_init_gain =
- rfseqG_init_gain_rev6;
- init_gaincode =
- initG_gaincode_rev6;
- }
- clip1hi_gaincode =
- clip1hiG_gaincode_rev6;
- switch (triso) {
- case 0:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[0];
- break;
- case 1:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[1];
- break;
- case 2:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[2];
- break;
- case 3:
- default:
+ switch (field) {
+ case (0x1 << 1):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 2):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 1);
+ val_shift = 1;
+ break;
+ case (0x1 << 3):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 2);
+ val_shift = 2;
+ break;
+ case (0x1 << 4):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 4);
+ val_shift = 4;
+ break;
+ case (0x1 << 5):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 5);
+ val_shift = 5;
+ break;
+ case (0x1 << 6):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 6);
+ val_shift = 6;
+ break;
+ case (0x1 << 7):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 7);
+ val_shift = 7;
+ break;
+ case (0x1 << 8):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x7 << 8);
+ val_shift = 8;
+ break;
+ case (0x1 << 11):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x7 << 13);
+ val_shift = 13;
+ break;
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[3];
- break;
- case 4:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[4];
- break;
- case 5:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[5];
- break;
- case 6:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[6];
- break;
- case 7:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[7];
- break;
- }
- nbclip_th = nbclipG_th_rev6;
- w1clip_th = w1clipG_th_rev6;
- crsmin_th = crsminG_th_rev6;
- crsminl_th = crsminlG_th_rev6;
- crsminu_th = crsminuG_th_rev6;
- rssi_gain = rssi_gain_default;
- }
- } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
- lna1_gain_db = lna1G_gain_db_rev5;
- lna2_gain_db = lna2G_gain_db_rev5;
- if (pi->sh->boardflags & BFL_EXTLNA) {
+ case (0x1 << 9):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+ val_mask = (0x7 << 0);
+ val_shift = 0;
+ break;
- rfseq_init_gain =
- rfseqG_init_gain_rev5_elna;
- init_gaincode =
- initG_gaincode_rev5_elna;
- } else {
- rfseq_init_gain = rfseqG_init_gain_rev5;
- init_gaincode = initG_gaincode_rev5;
- }
- clip1hi_gaincode = clip1hiG_gaincode_rev5;
- switch (triso) {
- case 0:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[0];
- break;
- case 1:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[1];
- break;
- case 2:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[2];
- break;
- case 3:
+ case (0x1 << 10):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+ val_mask = (0x7 << 4);
+ val_shift = 4;
+ break;
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[3];
- break;
- case 4:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[4];
- break;
- case 5:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[5];
- break;
- case 6:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[6];
- break;
- case 7:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[7];
- break;
- default:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[3];
- break;
- }
- nbclip_th = nbclipG_th_rev5;
- w1clip_th = w1clipG_th_rev5;
- crsmin_th = crsminG_th_rev5;
- crsminl_th = crsminlG_th_rev5;
- crsminu_th = crsminuG_th_rev5;
- rssi_gain = rssi_gain_default;
- } else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
- lna1_gain_db = lna1G_gain_db_rev4;
- lna2_gain_db = lna2G_gain_db;
- rfseq_init_gain = rfseqG_init_gain_rev4;
- init_gaincode = initG_gaincode_rev4;
- clip1hi_gaincode = clip1hiG_gaincode_rev4;
- clip1lo_gaincode = clip1loG_gaincode;
- nbclip_th = nbclipG_th_rev4;
- w1clip_th = w1clipG_th;
- crsmin_th = crsminG_th;
- crsminl_th = crsminlG_th;
- crsminu_th = crsminuG_th;
- rssi_gain = rssi_gain_default;
- } else {
- lna1_gain_db = lna1G_gain_db;
- lna2_gain_db = lna2G_gain_db;
- rfseq_init_gain = rfseqG_init_gain;
- init_gaincode = initG_gaincode;
- clip1hi_gaincode = clip1hiG_gaincode;
- clip1lo_gaincode = clip1loG_gaincode;
- nbclip_th = nbclipG_th;
- w1clip_th = w1clipG_th;
- crsmin_th = crsminG_th;
- crsminl_th = crsminlG_th;
- crsminu_th = crsminuG_th;
- rssi_gain = rssi_gain_default;
+ case (0x1 << 12):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7b : 0x7e;
+ val_mask = (0xffff << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 13):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7c : 0x7f;
+ val_mask = (0xffff << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 14):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+ val_mask = (0x3 << 6);
+ val_shift = 6;
+ break;
+ case (0x1 << 0):
+ en_addr = (core_num == 0) ? 0xe5 : 0xe6;
+ val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+ val_mask = (0x1 << 15);
+ val_shift = 15;
+ break;
+ default:
+ addr = 0xffff;
+ break;
}
- tia_gain_db = tiaG_gain_db;
- tia_gainbits = tiaG_gainbits;
- clip1md_gaincode = clip1mdG_gaincode;
- } else {
- if (NREV_GE(pi->pubpi.phy_rev, 6)) {
- lna1_gain_db = lna1A_gain_db_rev6;
- lna2_gain_db = lna2A_gain_db_rev6;
- tia_gain_db = tiaA_gain_db_rev6;
- tia_gainbits = tiaA_gainbits_rev6;
- rfseq_init_gain = rfseqA_init_gain_rev6;
- init_gaincode = initA_gaincode_rev6;
- clip1hi_gaincode = clip1hiA_gaincode_rev6;
- clip1md_gaincode = clip1mdA_gaincode_rev6;
- clip1lo_gaincode = clip1loA_gaincode_rev6;
- crsmin_th = crsminA_th_rev6;
- crsminl_th = crsminlA_th_rev6;
- if ((pi->pubpi.radiorev == 11) &&
- (CHSPEC_IS40(pi->radio_chanspec) == 0)) {
- crsminu_th = crsminuA_th_rev6_224B0;
- } else {
- crsminu_th = crsminuA_th_rev6;
- }
- nbclip_th = nbclipA_th_rev6;
- rssi_gain = rssiA_gain_rev6;
- } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
- lna1_gain_db = lna1A_gain_db_rev5;
- lna2_gain_db = lna2A_gain_db_rev5;
- tia_gain_db = tiaA_gain_db_rev5;
- tia_gainbits = tiaA_gainbits_rev5;
- rfseq_init_gain = rfseqA_init_gain_rev5;
- init_gaincode = initA_gaincode_rev5;
- clip1hi_gaincode = clip1hiA_gaincode_rev5;
- clip1md_gaincode = clip1mdA_gaincode_rev5;
- clip1lo_gaincode = clip1loA_gaincode_rev5;
- crsmin_th = crsminA_th_rev5;
- crsminl_th = crsminlA_th_rev5;
- crsminu_th = crsminuA_th_rev5;
- nbclip_th = nbclipA_th_rev5;
- rssi_gain = rssiA_gain_rev5;
- } else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
- lna1_gain_db = lna1A_gain_db_rev4;
- lna2_gain_db = lna2A_gain_db_rev4;
- tia_gain_db = tiaA_gain_db_rev4;
- tia_gainbits = tiaA_gainbits_rev4;
- if (pi->sh->boardflags & BFL_EXTLNA_5GHz) {
- rfseq_init_gain =
- rfseqA_init_gain_rev4_elna;
- init_gaincode =
- initA_gaincode_rev4_elna;
- } else {
- rfseq_init_gain = rfseqA_init_gain_rev4;
- init_gaincode = initA_gaincode_rev4;
- }
- clip1hi_gaincode = clip1hiA_gaincode_rev4;
- clip1md_gaincode = clip1mdA_gaincode_rev4;
- clip1lo_gaincode = clip1loA_gaincode_rev4;
- crsmin_th = crsminA_th_rev4;
- crsminl_th = crsminlA_th_rev4;
- crsminu_th = crsminuA_th_rev4;
- nbclip_th = nbclipA_th_rev4;
- rssi_gain = rssi_gain_default;
+ if (off) {
+ and_phy_reg(pi, en_addr, ~en_mask);
+ and_phy_reg(pi, val_addr, ~val_mask);
} else {
- lna1_gain_db = lna1A_gain_db;
- lna2_gain_db = lna2A_gain_db;
- tia_gain_db = tiaA_gain_db;
- tia_gainbits = tiaA_gainbits;
- rfseq_init_gain = rfseqA_init_gain;
- init_gaincode = initA_gaincode;
- clip1hi_gaincode = clip1hiA_gaincode;
- clip1md_gaincode = clip1mdA_gaincode;
- clip1lo_gaincode = clip1loA_gaincode;
- crsmin_th = crsminA_th;
- crsminl_th = crsminlA_th;
- crsminu_th = crsminuA_th;
- nbclip_th = nbclipA_th;
- rssi_gain = rssi_gain_default;
+
+ if ((core_mask == 0)
+ || (core_mask & (1 << core_num))) {
+ or_phy_reg(pi, en_addr, en_mask);
+
+ if (addr != 0xffff)
+ mod_phy_reg(pi, val_addr,
+ val_mask,
+ (value <<
+ val_shift));
+ }
}
- w1clip_th = w1clipA_th;
}
+ } else {
- write_radio_reg(pi,
- (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
- RADIO_2056_RX0), 0x17);
- write_radio_reg(pi,
- (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
- RADIO_2056_RX1), 0x17);
+ if (off) {
+ and_phy_reg(pi, 0xec, ~field);
+ value = 0x0;
+ } else {
+ or_phy_reg(pi, 0xec, field);
+ }
- write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0),
- 0xf0);
- write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1),
- 0xf0);
+ for (core_num = 0; core_num < 2; core_num++) {
- write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0),
- 0x0);
- write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1),
- 0x0);
+ switch (field) {
+ case (0x1 << 1):
+ case (0x1 << 9):
+ case (0x1 << 12):
+ case (0x1 << 13):
+ case (0x1 << 14):
+ addr = 0x78;
- write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0),
- rssi_gain);
- write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1),
- rssi_gain);
+ core_mask = 0x1;
+ break;
+ case (0x1 << 2):
+ case (0x1 << 3):
+ case (0x1 << 4):
+ case (0x1 << 5):
+ case (0x1 << 6):
+ case (0x1 << 7):
+ case (0x1 << 8):
+ addr = (core_num == 0) ? 0x7a : 0x7d;
+ break;
+ case (0x1 << 10):
+ addr = (core_num == 0) ? 0x7b : 0x7e;
+ break;
+ case (0x1 << 11):
+ addr = (core_num == 0) ? 0x7c : 0x7f;
+ break;
+ default:
+ addr = 0xffff;
+ }
- write_radio_reg(pi,
- (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
- RADIO_2056_RX0), 0x17);
- write_radio_reg(pi,
- (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
- RADIO_2056_RX1), 0x17);
+ switch (field) {
+ case (0x1 << 1):
+ mask = (0x7 << 3);
+ shift = 3;
+ break;
+ case (0x1 << 9):
+ mask = (0x1 << 2);
+ shift = 2;
+ break;
+ case (0x1 << 12):
+ mask = (0x1 << 8);
+ shift = 8;
+ break;
+ case (0x1 << 13):
+ mask = (0x1 << 9);
+ shift = 9;
+ break;
+ case (0x1 << 14):
+ mask = (0xf << 12);
+ shift = 12;
+ break;
+ case (0x1 << 2):
+ mask = (0x1 << 0);
+ shift = 0;
+ break;
+ case (0x1 << 3):
+ mask = (0x1 << 1);
+ shift = 1;
+ break;
+ case (0x1 << 4):
+ mask = (0x1 << 2);
+ shift = 2;
+ break;
+ case (0x1 << 5):
+ mask = (0x3 << 4);
+ shift = 4;
+ break;
+ case (0x1 << 6):
+ mask = (0x3 << 6);
+ shift = 6;
+ break;
+ case (0x1 << 7):
+ mask = (0x1 << 8);
+ shift = 8;
+ break;
+ case (0x1 << 8):
+ mask = (0x1 << 9);
+ shift = 9;
+ break;
+ case (0x1 << 10):
+ mask = 0x1fff;
+ shift = 0x0;
+ break;
+ case (0x1 << 11):
+ mask = 0x1fff;
+ shift = 0x0;
+ break;
+ default:
+ mask = 0x0;
+ shift = 0x0;
+ break;
+ }
- write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0),
- 0xFF);
- write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1),
- 0xFF);
+ if ((addr != 0xffff) && (core_mask & (1 << core_num)))
+ mod_phy_reg(pi, addr, mask, (value << shift));
+ }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8,
- 8, lna1_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8,
- 8, lna1_gain_db);
+ or_phy_reg(pi, 0xec, (0x1 << 0));
+ or_phy_reg(pi, 0x78, (0x1 << 0));
+ udelay(1);
+ and_phy_reg(pi, 0xec, ~(0x1 << 0));
+ }
+}
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
- 8, lna2_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
- 8, lna2_gain_db);
+static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi)
+{
+ s32 rssi_buf[4];
+ s32 int_val;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20,
- 8, tia_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20,
- 8, tia_gain_db);
+ if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi))
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20,
- 8, tia_gainbits);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20,
- 8, tia_gainbits);
+ return;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40,
- 8, &lpf_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40,
- 8, &lpf_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40,
- 8, &lpf_gainbits);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40,
- 8, &lpf_gainbits);
+ if (PHY_IPA(pi))
+ wlc_phy_ipa_internal_tssi_setup_nphy(pi);
- write_phy_reg(pi, 0x20, init_gaincode);
- write_phy_reg(pi, 0x2a7, init_gaincode);
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+ 0, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ else if (NREV_GE(pi->pubpi.phy_rev, 3))
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- pi->pubpi.phy_corenum, 0x106, 16,
- rfseq_init_gain);
+ wlc_phy_stopplayback_nphy(pi);
- write_phy_reg(pi, 0x22, clip1hi_gaincode);
- write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+ wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false);
- write_phy_reg(pi, 0x24, clip1md_gaincode);
- write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+ udelay(20);
+ int_val =
+ wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf,
+ 1);
+ wlc_phy_stopplayback_nphy(pi);
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0);
- write_phy_reg(pi, 0x37, clip1lo_gaincode);
- write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+ 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ else if (NREV_GE(pi->pubpi.phy_rev, 3))
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1);
- mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0));
- mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
- mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- write_phy_reg(pi, 0x2b, nbclip_th);
- write_phy_reg(pi, 0x41, nbclip_th);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
+ (u8) ((int_val >> 24) & 0xff);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
+ (u8) ((int_val >> 24) & 0xff);
- mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0));
- mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0));
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
+ (u8) ((int_val >> 8) & 0xff);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
+ (u8) ((int_val >> 8) & 0xff);
+ } else {
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
+ (u8) ((int_val >> 24) & 0xff);
- write_phy_reg(pi, 0x150, 0x809c);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
+ (u8) ((int_val >> 8) & 0xff);
- } else {
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
+ (u8) ((int_val >> 16) & 0xff);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
+ (u8) ((int_val) & 0xff);
+ }
- mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
- mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+}
- write_phy_reg(pi, 0x2b, 0x84);
- write_phy_reg(pi, 0x41, 0x84);
+static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi)
+{
+ u8 idx, idx2, i, delta_ind;
- if (CHSPEC_IS20(pi->radio_chanspec)) {
- write_phy_reg(pi, 0x6b, 0x2b);
- write_phy_reg(pi, 0x6c, 0x2b);
- write_phy_reg(pi, 0x6d, 0x9);
- write_phy_reg(pi, 0x6e, 0x9);
- }
+ for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++)
+ pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx];
- w1th = NPHY_RSSICAL_W1_TARGET - 4;
- mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0));
- mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0));
+ for (i = 0; i < 4; i++) {
+ idx2 = 0;
- if (CHSPEC_IS20(pi->radio_chanspec)) {
- mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0));
- mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0));
+ delta_ind = 0;
- mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0));
- mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0));
- }
+ switch (i) {
+ case 0:
- write_phy_reg(pi, 0x150, 0x809c);
+ if (CHSPEC_IS40(pi->radio_chanspec)
+ && NPHY_IS_SROM_REINTERPRET) {
+ idx = TXP_FIRST_MCS_40_SISO;
+ } else {
+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+ TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM;
+ delta_ind = 1;
+ }
+ break;
- if (pi->nphy_gain_boost)
- if ((CHSPEC_IS2G(pi->radio_chanspec)) &&
- (CHSPEC_IS40(pi->radio_chanspec)))
- hpf_code = 4;
- else
- hpf_code = 5;
- else if (CHSPEC_IS40(pi->radio_chanspec))
- hpf_code = 6;
- else
- hpf_code = 7;
+ case 1:
- mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7));
- mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7));
+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+ TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD;
+ break;
- for (ctr = 0; ctr < 4; ctr++) {
- regval[ctr] = (hpf_code << 8) | 0x7c;
- }
- wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+ case 2:
- wlc_phy_adjust_lnagaintbl_nphy(pi);
+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+ TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC;
+ break;
- if (pi->nphy_elna_gain_config) {
- regval[0] = 0;
- regval[1] = 1;
- regval[2] = 1;
- regval[3] = 1;
- wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval);
- wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval);
+ case 3:
- for (ctr = 0; ctr < 4; ctr++) {
- regval[ctr] = (hpf_code << 8) | 0x74;
- }
- wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+ TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM;
+ break;
}
- if (NREV_IS(pi->pubpi.phy_rev, 2)) {
- for (ctr = 0; ctr < 21; ctr++) {
- regval[ctr] = 3 * ctr;
- }
- wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval);
- wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval);
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ idx = idx + delta_ind;
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
- for (ctr = 0; ctr < 21; ctr++) {
- regval[ctr] = (u16) ctr;
- }
- wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval);
- wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval);
- }
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
- wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU,
- rfseq_updategainu_events,
- rfseq_updategainu_dlys,
- sizeof(rfseq_updategainu_events) /
- sizeof(rfseq_updategainu_events[0]));
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
- mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8));
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ idx = idx + 1 - delta_ind;
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
- if (CHSPEC_IS2G(pi->radio_chanspec))
- mod_phy_reg(pi,
- (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES),
- 0x7f, 0x4);
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
}
}
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi)
+static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
{
- s8 lna1_gain_db[] = { 8, 13, 17, 22 };
- s8 lna2_gain_db[] = { -2, 7, 11, 15 };
- s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 };
- s8 tia_gainbits[] = {
- 0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+ u32 idx;
+ s16 a1[2], b0[2], b1[2];
+ s8 target_pwr_qtrdbm[2];
+ s32 num, den, pwr_est;
+ u8 chan_freq_range;
+ u8 idle_tssi[2];
+ u32 tbl_id, tbl_len, tbl_offset;
+ u32 regval[64];
+ u8 core;
- mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
- mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+ (void)R_REG(&pi->regs->maccontrol);
+ udelay(1);
+ }
- mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
- mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0));
- mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0));
+ or_phy_reg(pi, 0x122, (0x1 << 0));
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8,
- lna1_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8,
- lna1_gain_db);
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
+ and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15)));
+ else
+ or_phy_reg(pi, 0x1e7, (0x1 << 15));
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8,
- lna2_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8,
- lna2_gain_db);
+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
- tia_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
- tia_gain_db);
+ if (pi->sh->sromrev < 4) {
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+ target_pwr_qtrdbm[0] = 13 * 4;
+ target_pwr_qtrdbm[1] = 13 * 4;
+ a1[0] = -424;
+ a1[1] = -424;
+ b0[0] = 5612;
+ b0[1] = 5612;
+ b1[1] = -1393;
+ b1[0] = -1393;
+ } else {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
- tia_gainbits);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
- tia_gainbits);
+ chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ switch (chan_freq_range) {
+ case WL_CHAN_FREQ_RANGE_2G:
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+ target_pwr_qtrdbm[0] =
+ pi->nphy_pwrctrl_info[0].max_pwr_2g;
+ target_pwr_qtrdbm[1] =
+ pi->nphy_pwrctrl_info[1].max_pwr_2g;
+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1;
+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1;
+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0;
+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0;
+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1;
+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1;
+ break;
+ case WL_CHAN_FREQ_RANGE_5GL:
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+ target_pwr_qtrdbm[0] =
+ pi->nphy_pwrctrl_info[0].max_pwr_5gl;
+ target_pwr_qtrdbm[1] =
+ pi->nphy_pwrctrl_info[1].max_pwr_5gl;
+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1;
+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1;
+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0;
+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0;
+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1;
+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1;
+ break;
+ case WL_CHAN_FREQ_RANGE_5GM:
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+ target_pwr_qtrdbm[0] =
+ pi->nphy_pwrctrl_info[0].max_pwr_5gm;
+ target_pwr_qtrdbm[1] =
+ pi->nphy_pwrctrl_info[1].max_pwr_5gm;
+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1;
+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1;
+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0;
+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0;
+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1;
+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1;
+ break;
+ case WL_CHAN_FREQ_RANGE_5GH:
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+ target_pwr_qtrdbm[0] =
+ pi->nphy_pwrctrl_info[0].max_pwr_5gh;
+ target_pwr_qtrdbm[1] =
+ pi->nphy_pwrctrl_info[1].max_pwr_5gh;
+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1;
+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1;
+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0;
+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0;
+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1;
+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1;
+ break;
+ default:
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+ target_pwr_qtrdbm[0] = 13 * 4;
+ target_pwr_qtrdbm[1] = 13 * 4;
+ a1[0] = -424;
+ a1[1] = -424;
+ b0[0] = 5612;
+ b0[1] = 5612;
+ b1[1] = -1393;
+ b1[0] = -1393;
+ break;
+ }
+ }
- write_phy_reg(pi, 0x37, 0x74);
- write_phy_reg(pi, 0x2ad, 0x74);
- write_phy_reg(pi, 0x38, 0x18);
- write_phy_reg(pi, 0x2ae, 0x18);
+ target_pwr_qtrdbm[0] = (s8) pi->tx_power_max;
+ target_pwr_qtrdbm[1] = (s8) pi->tx_power_max;
- write_phy_reg(pi, 0x2b, 0xe8);
- write_phy_reg(pi, 0x41, 0xe8);
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (pi->srom_fem2g.tssipos)
+ or_phy_reg(pi, 0x1e9, (0x1 << 14));
- if (CHSPEC_IS20(pi->radio_chanspec)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ for (core = 0; core <= 1; core++) {
+ if (PHY_IPA(pi)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ WRITE_RADIO_REG3(pi, RADIO_2057,
+ TX, core,
+ TX_SSI_MUX,
+ 0xe);
+ else
+ WRITE_RADIO_REG3(pi, RADIO_2057,
+ TX, core,
+ TX_SSI_MUX,
+ 0xc);
+ }
+ }
+ } else {
+ if (PHY_IPA(pi)) {
- mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0));
- mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0));
- } else {
+ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+ RADIO_2056_TX0,
+ (CHSPEC_IS5G
+ (pi->radio_chanspec)) ?
+ 0xc : 0xe);
+ write_radio_reg(pi,
+ RADIO_2056_TX_TX_SSI_MUX |
+ RADIO_2056_TX1,
+ (CHSPEC_IS5G
+ (pi->radio_chanspec)) ?
+ 0xc : 0xe);
+ } else {
- mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0));
- mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0));
+ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+ RADIO_2056_TX0, 0x11);
+ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+ RADIO_2056_TX1, 0x11);
+ }
+ }
}
-}
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi)
-{
- u16 currband;
- s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
- s8 *lna1_gain_db = NULL;
- s8 *lna1_gain_db_2 = NULL;
- s8 *lna2_gain_db = NULL;
- s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
- s8 *tia_gain_db;
- s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
- s8 *tia_gainbits;
- u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
- u16 *rfseq_init_gain;
- u16 init_gaincode;
- u16 clip1hi_gaincode;
- u16 clip1md_gaincode = 0;
- u16 clip1md_gaincode_B;
- u16 clip1lo_gaincode;
- u16 clip1lo_gaincode_B;
- u8 crsminl_th = 0;
- u8 crsminu_th;
- u16 nbclip_th = 0;
- u8 w1clip_th;
- u16 freq;
- s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0;
- u8 chg_nbclip_th = 0;
+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+ (void)R_REG(&pi->regs->maccontrol);
+ udelay(1);
+ }
- mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
- mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+ (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
+ else
+ mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+ (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
- currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
- if (currband == 0) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ mod_phy_reg(pi, 0x222, (0xff << 0),
+ (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
+ else if (NREV_GT(pi->pubpi.phy_rev, 1))
+ mod_phy_reg(pi, 0x222, (0xff << 0),
+ (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
- lna1_gain_db = lna1G_gain_db_rev7;
+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
- lna1_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
- lna1_gain_db);
+ write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0));
- mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0));
+ write_phy_reg(pi, 0x1e9,
+ (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8));
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0));
- mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0));
+ write_phy_reg(pi, 0x1ea,
+ (target_pwr_qtrdbm[0] << 0) |
+ (target_pwr_qtrdbm[1] << 8));
+
+ tbl_len = 64;
+ tbl_offset = 0;
+ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+
+ for (idx = 0; idx < tbl_len; idx++) {
+ num = 8 *
+ (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx);
+ den = 32768 + a1[tbl_id - 26] * idx;
+ pwr_est = max(((4 * num + den / 2) / den), -8);
+ if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+ if (idx <=
+ (uint) (31 - idle_tssi[tbl_id - 26] + 1))
+ pwr_est =
+ max(pwr_est,
+ target_pwr_qtrdbm
+ [tbl_id - 26] + 1);
+ }
+ regval[idx] = (u32) pwr_est;
}
+ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+ regval);
+ }
- mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+ wlc_phy_txpwr_limit_to_tbl_nphy(pi);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8,
+ pi->adj_pwr_tbl_nphy);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8,
+ pi->adj_pwr_tbl_nphy);
- if (CHSPEC_IS20(pi->radio_chanspec)) {
- mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0));
- mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0));
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi)
+{
+ u32 *tx_pwrctrl_tbl = NULL;
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if ((pi->pubpi.radiorev == 4)
+ || (pi->pubpi.radiorev == 6))
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_ipa_2g_2057rev4n6;
+ else if (pi->pubpi.radiorev == 3)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_ipa_2g_2057rev3;
+ else if (pi->pubpi.radiorev == 5)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_ipa_2g_2057rev5;
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_ipa_2g_2057rev7;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
+ } else {
+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa;
}
} else {
- init_gaincode = 0x9e;
- clip1hi_gaincode = 0x9e;
- clip1md_gaincode_B = 0x24;
- clip1lo_gaincode = 0x8a;
- clip1lo_gaincode_B = 8;
- rfseq_init_gain = rfseqA_init_gain_rev7;
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6))
+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057;
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_ipa_5g_2057rev7;
+ } else {
+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g;
+ }
+ }
- tia_gain_db = tiaA_gain_db_rev7;
- tia_gainbits = tiaA_gainbits_rev7;
+ return tx_pwrctrl_tbl;
+}
- freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
- if (CHSPEC_IS20(pi->radio_chanspec)) {
+static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi)
+{
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (pi->nphy_rssical_chanspec_2G == 0)
+ return;
- w1clip_th = 25;
- clip1md_gaincode = 0x82;
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+ RADIO_2057_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_2G[0]);
+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+ RADIO_2057_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_2G[1]);
+ } else {
+ mod_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+ RADIO_2056_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_2G[0]);
+ mod_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+ RADIO_2056_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_2G[1]);
+ }
- if ((freq <= 5080) || (freq == 5825)) {
+ write_phy_reg(pi, 0x1a6,
+ pi->rssical_cache.rssical_phyregs_2G[0]);
+ write_phy_reg(pi, 0x1ac,
+ pi->rssical_cache.rssical_phyregs_2G[1]);
+ write_phy_reg(pi, 0x1b2,
+ pi->rssical_cache.rssical_phyregs_2G[2]);
+ write_phy_reg(pi, 0x1b8,
+ pi->rssical_cache.rssical_phyregs_2G[3]);
+ write_phy_reg(pi, 0x1a4,
+ pi->rssical_cache.rssical_phyregs_2G[4]);
+ write_phy_reg(pi, 0x1aa,
+ pi->rssical_cache.rssical_phyregs_2G[5]);
+ write_phy_reg(pi, 0x1b0,
+ pi->rssical_cache.rssical_phyregs_2G[6]);
+ write_phy_reg(pi, 0x1b6,
+ pi->rssical_cache.rssical_phyregs_2G[7]);
+ write_phy_reg(pi, 0x1a5,
+ pi->rssical_cache.rssical_phyregs_2G[8]);
+ write_phy_reg(pi, 0x1ab,
+ pi->rssical_cache.rssical_phyregs_2G[9]);
+ write_phy_reg(pi, 0x1b1,
+ pi->rssical_cache.rssical_phyregs_2G[10]);
+ write_phy_reg(pi, 0x1b7,
+ pi->rssical_cache.rssical_phyregs_2G[11]);
- s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
- s8 lna1A_gain_db_2_rev7[] = {
- 11, 17, 22, 25 };
- s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+ } else {
+ if (pi->nphy_rssical_chanspec_5G == 0)
+ return;
- crsminu_th = 0x3e;
- lna1_gain_db = lna1A_gain_db_rev7;
- lna1_gain_db_2 = lna1A_gain_db_2_rev7;
- lna2_gain_db = lna2A_gain_db_rev7;
- } else if ((freq >= 5500) && (freq <= 5700)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+ RADIO_2057_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_5G[0]);
+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+ RADIO_2057_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_5G[1]);
+ } else {
+ mod_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+ RADIO_2056_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_5G[0]);
+ mod_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+ RADIO_2056_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_5G[1]);
+ }
- s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
- s8 lna1A_gain_db_2_rev7[] = {
- 12, 18, 22, 26 };
- s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
+ write_phy_reg(pi, 0x1a6,
+ pi->rssical_cache.rssical_phyregs_5G[0]);
+ write_phy_reg(pi, 0x1ac,
+ pi->rssical_cache.rssical_phyregs_5G[1]);
+ write_phy_reg(pi, 0x1b2,
+ pi->rssical_cache.rssical_phyregs_5G[2]);
+ write_phy_reg(pi, 0x1b8,
+ pi->rssical_cache.rssical_phyregs_5G[3]);
+ write_phy_reg(pi, 0x1a4,
+ pi->rssical_cache.rssical_phyregs_5G[4]);
+ write_phy_reg(pi, 0x1aa,
+ pi->rssical_cache.rssical_phyregs_5G[5]);
+ write_phy_reg(pi, 0x1b0,
+ pi->rssical_cache.rssical_phyregs_5G[6]);
+ write_phy_reg(pi, 0x1b6,
+ pi->rssical_cache.rssical_phyregs_5G[7]);
+ write_phy_reg(pi, 0x1a5,
+ pi->rssical_cache.rssical_phyregs_5G[8]);
+ write_phy_reg(pi, 0x1ab,
+ pi->rssical_cache.rssical_phyregs_5G[9]);
+ write_phy_reg(pi, 0x1b1,
+ pi->rssical_cache.rssical_phyregs_5G[10]);
+ write_phy_reg(pi, 0x1b7,
+ pi->rssical_cache.rssical_phyregs_5G[11]);
+ }
+}
- crsminu_th = 0x45;
- clip1md_gaincode_B = 0x14;
- nbclip_th = 0xff;
- chg_nbclip_th = 1;
- lna1_gain_db = lna1A_gain_db_rev7;
- lna1_gain_db_2 = lna1A_gain_db_2_rev7;
- lna2_gain_db = lna2A_gain_db_rev7;
+static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi)
+{
+ u16 txcal_gain[2];
+
+ pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0];
+ pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0];
+ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+
+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+ txcal_gain);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40;
+ txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40;
+ } else {
+ txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60;
+ txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60;
+ }
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+ txcal_gain);
+}
+
+static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi)
+{
+ bool save_bbmult = false;
+ u8 txcal_index_2057_rev5n7 = 0;
+ u8 txcal_index_2057_rev3n4n6 = 10;
+
+ if (pi->use_int_tx_iqlo_cal_nphy) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6)) {
+
+ pi->nphy_txcal_pwr_idx[0] =
+ txcal_index_2057_rev3n4n6;
+ pi->nphy_txcal_pwr_idx[1] =
+ txcal_index_2057_rev3n4n6;
+ wlc_phy_txpwr_index_nphy(
+ pi, 3,
+ txcal_index_2057_rev3n4n6,
+ false);
} else {
- s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
- s8 lna1A_gain_db_2_rev7[] = {
- 12, 18, 22, 26 };
- s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+ pi->nphy_txcal_pwr_idx[0] =
+ txcal_index_2057_rev5n7;
+ pi->nphy_txcal_pwr_idx[1] =
+ txcal_index_2057_rev5n7;
+ wlc_phy_txpwr_index_nphy(
+ pi, 3,
+ txcal_index_2057_rev5n7,
+ false);
+ }
+ save_bbmult = true;
- crsminu_th = 0x41;
- lna1_gain_db = lna1A_gain_db_rev7;
- lna1_gain_db_2 = lna1A_gain_db_2_rev7;
- lna2_gain_db = lna2A_gain_db_rev7;
+ } else if (NREV_LT(pi->pubpi.phy_rev, 5)) {
+ wlc_phy_cal_txgainctrl_nphy(pi, 11, false);
+ if (pi->sh->hw_phytxchain != 3) {
+ pi->nphy_txcal_pwr_idx[1] =
+ pi->nphy_txcal_pwr_idx[0];
+ wlc_phy_txpwr_index_nphy(pi, 3,
+ pi->
+ nphy_txcal_pwr_idx[0],
+ true);
+ save_bbmult = true;
}
- if (freq <= 4920) {
- nvar_baseline_offset0 = 5;
- nvar_baseline_offset1 = 5;
- } else if ((freq > 4920) && (freq <= 5320)) {
- nvar_baseline_offset0 = 3;
- nvar_baseline_offset1 = 5;
- } else if ((freq > 5320) && (freq <= 5700)) {
- nvar_baseline_offset0 = 3;
- nvar_baseline_offset1 = 2;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+ if (PHY_IPA(pi)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ wlc_phy_cal_txgainctrl_nphy(pi, 12,
+ false);
+ } else {
+ pi->nphy_txcal_pwr_idx[0] = 80;
+ pi->nphy_txcal_pwr_idx[1] = 80;
+ wlc_phy_txpwr_index_nphy(pi, 3, 80,
+ false);
+ save_bbmult = true;
+ }
} else {
- nvar_baseline_offset0 = 4;
- nvar_baseline_offset1 = 0;
+ wlc_phy_internal_cal_txgain_nphy(pi);
+ save_bbmult = true;
}
- } else {
-
- crsminu_th = 0x3a;
- crsminl_th = 0x3a;
- w1clip_th = 20;
- if ((freq >= 4920) && (freq <= 5320)) {
- nvar_baseline_offset0 = 4;
- nvar_baseline_offset1 = 5;
- } else if ((freq > 5320) && (freq <= 5550)) {
- nvar_baseline_offset0 = 4;
- nvar_baseline_offset1 = 2;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+ if (PHY_IPA(pi)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ wlc_phy_cal_txgainctrl_nphy(pi, 12,
+ false);
+ else
+ wlc_phy_cal_txgainctrl_nphy(pi, 14,
+ false);
} else {
- nvar_baseline_offset0 = 5;
- nvar_baseline_offset1 = 3;
+ wlc_phy_internal_cal_txgain_nphy(pi);
+ save_bbmult = true;
}
}
- write_phy_reg(pi, 0x20, init_gaincode);
- write_phy_reg(pi, 0x2a7, init_gaincode);
+ } else {
+ wlc_phy_cal_txgainctrl_nphy(pi, 10, false);
+ }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- pi->pubpi.phy_corenum, 0x106, 16,
- rfseq_init_gain);
+ if (save_bbmult)
+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
+ &pi->nphy_txcal_bbmult);
+}
- write_phy_reg(pi, 0x22, clip1hi_gaincode);
- write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+static void
+wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value,
+ u8 core_code)
+{
+ u16 mask;
+ u16 val;
+ u8 core;
- write_phy_reg(pi, 0x36, clip1md_gaincode_B);
- write_phy_reg(pi, 0x2ac, clip1md_gaincode_B);
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+ if (core_code == RADIO_MIMO_CORESEL_CORE1
+ && core == PHY_CORE_1)
+ continue;
+ else if (core_code == RADIO_MIMO_CORESEL_CORE2
+ && core == PHY_CORE_0)
+ continue;
- write_phy_reg(pi, 0x37, clip1lo_gaincode);
- write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
- write_phy_reg(pi, 0x38, clip1lo_gaincode_B);
- write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B);
+ if (NREV_LT(pi->pubpi.phy_rev, 7)) {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
- tia_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
- tia_gain_db);
+ mask = (0x1 << 10);
+ val = 1 << 10;
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+ 0x92, mask, val);
+ }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
- tia_gainbits);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
- tia_gainbits);
+ if (field == NPHY_RfctrlIntc_override_OFF) {
- mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+ 0x92, 0);
- if (chg_nbclip_th == 1) {
- write_phy_reg(pi, 0x2b, nbclip_th);
- write_phy_reg(pi, 0x41, nbclip_th);
- }
+ wlc_phy_force_rfseq_nphy(pi,
+ NPHY_RFSEQ_RESET2RX);
+ } else if (field == NPHY_RfctrlIntc_override_TRSW) {
- mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0));
- mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0));
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- mod_phy_reg(pi, 0x2e4,
- (0x3f << 0), (nvar_baseline_offset0 << 0));
+ mask = (0x1 << 6) | (0x1 << 7);
- mod_phy_reg(pi, 0x2e4,
- (0x3f << 6), (nvar_baseline_offset1 << 6));
+ val = value << 6;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
- if (CHSPEC_IS20(pi->radio_chanspec)) {
+ or_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ (0x1 << 10));
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
- lna1_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
- lna1_gain_db_2);
+ and_phy_reg(pi, 0x2ff, (u16)
+ ~(0x3 << 14));
+ or_phy_reg(pi, 0x2ff, (0x1 << 13));
+ or_phy_reg(pi, 0x2ff, (0x1 << 0));
+ } else {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
- 8, lna2_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
- 8, lna2_gain_db);
+ mask = (0x1 << 6) |
+ (0x1 << 7) |
+ (0x1 << 8) | (0x1 << 9);
+ val = value << 6;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
- write_phy_reg(pi, 0x24, clip1md_gaincode);
- write_phy_reg(pi, 0x2ab, clip1md_gaincode);
- } else {
- mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
- }
+ mask = (0x1 << 0);
+ val = 1 << 0;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0xe7 : 0xec,
+ mask, val);
- }
+ mask = (core == PHY_CORE_0) ?
+ (0x1 << 0) : (0x1 << 1);
+ val = 1 << ((core == PHY_CORE_0) ?
+ 0 : 1);
+ mod_phy_reg(pi, 0x78, mask, val);
+
+ SPINWAIT(((read_phy_reg(pi, 0x78) & val)
+ != 0), 10000);
+ if (WARN(read_phy_reg(pi, 0x78) & val,
+ "HW error: override failed"))
+ return;
+
+ mask = (0x1 << 0);
+ val = 0 << 0;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0xe7 : 0xec,
+ mask, val);
+ }
+ } else if (field == NPHY_RfctrlIntc_override_PA) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ mask = (0x1 << 4) | (0x1 << 5);
+
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ val = value << 5;
+ else
+ val = value << 4;
+
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ or_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ (0x1 << 12));
+ } else {
+
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ mask = (0x1 << 5);
+ val = value << 5;
+ } else {
+ mask = (0x1 << 4);
+ val = value << 4;
+ }
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ }
+ } else if (field ==
+ NPHY_RfctrlIntc_override_EXT_LNA_PU) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+ mask = (0x1 << 0);
+ val = value << 0;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, val);
+
+ mask = (0x1 << 2);
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, 0);
+ } else {
+
+ mask = (0x1 << 2);
+ val = value << 2;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, val);
+
+ mask = (0x1 << 0);
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, 0);
+ }
+
+ mask = (0x1 << 11);
+ val = 1 << 11;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ } else {
+
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ mask = (0x1 << 0);
+ val = value << 0;
+ } else {
+ mask = (0x1 << 2);
+ val = value << 2;
+ }
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ }
+ } else if (field ==
+ NPHY_RfctrlIntc_override_EXT_LNA_GAIN) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+ mask = (0x1 << 1);
+ val = value << 1;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, val);
+
+ mask = (0x1 << 3);
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, 0);
+ } else {
+
+ mask = (0x1 << 3);
+ val = value << 3;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, val);
+
+ mask = (0x1 << 1);
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, 0);
+ }
+
+ mask = (0x1 << 11);
+ val = 1 << 11;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ } else {
+
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ mask = (0x1 << 1);
+ val = value << 1;
+ } else {
+ mask = (0x1 << 3);
+ val = value << 3;
+ }
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ }
+ }
+ }
+ }
}
-static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi)
+void
+wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower,
+ bool debug)
{
+ int gainctrl_loopidx;
uint core;
- int ctr;
- s16 gain_delta[2];
- u8 curr_channel;
- u16 minmax_gain[2];
- u16 regval[4];
+ u16 m0m1, curr_m0m1;
+ s32 delta_power;
+ s32 txpwrindex;
+ s32 qdBm_power[2];
+ u16 orig_BBConfig;
+ u16 phy_saveregs[4];
+ u32 freq_test;
+ u16 ampl_test = 250;
+ uint stepsize;
+ bool phyhang_avoid_state = false;
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ stepsize = 2;
+ else
+ stepsize = 1;
+
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ freq_test = 5000;
+ else
+ freq_test = 2500;
+
+ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
if (pi->phyhang_avoid)
wlc_phy_stay_in_carriersearch_nphy(pi, true);
- if (pi->nphy_gain_boost) {
- if ((CHSPEC_IS2G(pi->radio_chanspec))) {
+ phyhang_avoid_state = pi->phyhang_avoid;
+ pi->phyhang_avoid = false;
- gain_delta[0] = 6;
- gain_delta[1] = 6;
- } else {
+ phy_saveregs[0] = read_phy_reg(pi, 0x91);
+ phy_saveregs[1] = read_phy_reg(pi, 0x92);
+ phy_saveregs[2] = read_phy_reg(pi, 0xe7);
+ phy_saveregs[3] = read_phy_reg(pi, 0xec);
+ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1,
+ RADIO_MIMO_CORESEL_CORE1 |
+ RADIO_MIMO_CORESEL_CORE2);
- curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
- gain_delta[0] =
- (s16)
- PHY_HW_ROUND(((nphy_lnagain_est0[0] *
- curr_channel) +
- nphy_lnagain_est0[1]), 13);
- gain_delta[1] =
- (s16)
- PHY_HW_ROUND(((nphy_lnagain_est1[0] *
- curr_channel) +
- nphy_lnagain_est1[1]), 13);
- }
+ if (!debug) {
+ wlc_phy_rfctrlintc_override_nphy(pi,
+ NPHY_RfctrlIntc_override_TRSW,
+ 0x2, RADIO_MIMO_CORESEL_CORE1);
+ wlc_phy_rfctrlintc_override_nphy(pi,
+ NPHY_RfctrlIntc_override_TRSW,
+ 0x8, RADIO_MIMO_CORESEL_CORE2);
} else {
-
- gain_delta[0] = 0;
- gain_delta[1] = 0;
+ wlc_phy_rfctrlintc_override_nphy(pi,
+ NPHY_RfctrlIntc_override_TRSW,
+ 0x1, RADIO_MIMO_CORESEL_CORE1);
+ wlc_phy_rfctrlintc_override_nphy(pi,
+ NPHY_RfctrlIntc_override_TRSW,
+ 0x7, RADIO_MIMO_CORESEL_CORE2);
}
+ orig_BBConfig = read_phy_reg(pi, 0x01);
+ mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- if (pi->nphy_elna_gain_config) {
+ txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core];
- regval[0] = nphy_def_lnagains[2] + gain_delta[core];
- regval[1] = nphy_def_lnagains[3] + gain_delta[core];
- regval[2] = nphy_def_lnagains[3] + gain_delta[core];
- regval[3] = nphy_def_lnagains[3] + gain_delta[core];
- } else {
- for (ctr = 0; ctr < 4; ctr++) {
- regval[ctr] =
- nphy_def_lnagains[ctr] + gain_delta[core];
+ for (gainctrl_loopidx = 0; gainctrl_loopidx < 2;
+ gainctrl_loopidx++) {
+ wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+ false);
+
+ if (core == PHY_CORE_0)
+ curr_m0m1 = m0m1 & 0xff00;
+ else
+ curr_m0m1 = m0m1 & 0x00ff;
+
+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1);
+ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1);
+
+ udelay(50);
+
+ wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+ NPHY_CAL_TSSISAMPS);
+
+ pi->nphy_bb_mult_save = 0;
+ wlc_phy_stopplayback_nphy(pi);
+
+ delta_power = (dBm_targetpower * 4) - qdBm_power[core];
+
+ txpwrindex -= stepsize * delta_power;
+ if (txpwrindex < 0)
+ txpwrindex = 0;
+ else if (txpwrindex > 127)
+ txpwrindex = 127;
+
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ if (NREV_IS(pi->pubpi.phy_rev, 4) &&
+ (pi->srom_fem5g.extpagain == 3)) {
+ if (txpwrindex < 30)
+ txpwrindex = 30;
+ }
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+ (pi->srom_fem2g.extpagain == 3)) {
+ if (txpwrindex < 50)
+ txpwrindex = 50;
+ }
}
+
+ wlc_phy_txpwr_index_nphy(pi, (1 << core),
+ (u8) txpwrindex, true);
}
- wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval);
- minmax_gain[core] =
- (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4);
+ pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex;
+
+ if (debug) {
+ u16 radio_gain;
+ u16 dbg_m0m1;
+
+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+
+ wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+ false);
+
+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1);
+
+ udelay(100);
+
+ wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+ NPHY_CAL_TSSISAMPS);
+
+ wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16,
+ &radio_gain);
+
+ mdelay(4000);
+ pi->nphy_bb_mult_save = 0;
+ wlc_phy_stopplayback_nphy(pi);
+ }
}
- mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0));
- mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0));
+ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true);
+ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true);
+
+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult);
+
+ write_phy_reg(pi, 0x01, orig_BBConfig);
+
+ write_phy_reg(pi, 0x91, phy_saveregs[0]);
+ write_phy_reg(pi, 0x92, phy_saveregs[1]);
+ write_phy_reg(pi, 0xe7, phy_saveregs[2]);
+ write_phy_reg(pi, 0xec, phy_saveregs[3]);
+
+ pi->phyhang_avoid = phyhang_avoid_state;
if (pi->phyhang_avoid)
wlc_phy_stay_in_carriersearch_nphy(pi, false);
}
-void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on)
+static void wlc_phy_savecal_nphy(struct brcms_phy *pi)
{
- if (on) {
+ void *tbl_ptr;
+ int coreNum;
+ u16 *txcal_radio_regs = NULL;
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+ wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+ &pi->calibration_cache.
+ rxcal_coeffs_2G);
+
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (!pi->radio_is_on) {
- wlc_phy_radio_preinit_205x(pi);
- wlc_phy_radio_init_2057(pi);
- wlc_phy_radio_postinit_2057(pi);
- }
+ txcal_radio_regs =
+ pi->calibration_cache.txcal_radio_regs_2G;
+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
- pi->radio_chanspec);
+ pi->calibration_cache.txcal_radio_regs_2G[0] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_2G[1] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_2G[2] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX1);
+ pi->calibration_cache.txcal_radio_regs_2G[3] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX1);
+
+ pi->calibration_cache.txcal_radio_regs_2G[4] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_2G[5] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_2G[6] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX1);
+ pi->calibration_cache.txcal_radio_regs_2G[7] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX1);
+ } else {
+ pi->calibration_cache.txcal_radio_regs_2G[0] =
+ read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+ pi->calibration_cache.txcal_radio_regs_2G[1] =
+ read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+ pi->calibration_cache.txcal_radio_regs_2G[2] =
+ read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+ pi->calibration_cache.txcal_radio_regs_2G[3] =
+ read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
+ }
+
+ pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec;
+ tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+ } else {
+
+ wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+ &pi->calibration_cache.
+ rxcal_coeffs_5G);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ txcal_radio_regs =
+ pi->calibration_cache.txcal_radio_regs_5G;
} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- wlc_phy_radio_preinit_205x(pi);
- wlc_phy_radio_init_2056(pi);
- wlc_phy_radio_postinit_2056(pi);
- wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
- pi->radio_chanspec);
+ pi->calibration_cache.txcal_radio_regs_5G[0] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_5G[1] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_5G[2] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX1);
+ pi->calibration_cache.txcal_radio_regs_5G[3] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX1);
+
+ pi->calibration_cache.txcal_radio_regs_5G[4] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_5G[5] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_5G[6] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX1);
+ pi->calibration_cache.txcal_radio_regs_5G[7] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX1);
} else {
- wlc_phy_radio_preinit_2055(pi);
- wlc_phy_radio_init_2055(pi);
- wlc_phy_radio_postinit_2055(pi);
+ pi->calibration_cache.txcal_radio_regs_5G[0] =
+ read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+ pi->calibration_cache.txcal_radio_regs_5G[1] =
+ read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+ pi->calibration_cache.txcal_radio_regs_5G[2] =
+ read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+ pi->calibration_cache.txcal_radio_regs_5G[3] =
+ read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
}
- pi->radio_is_on = true;
+ pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec;
+ tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+ }
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+ txcal_radio_regs[2 * coreNum] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_FINE_I);
+ txcal_radio_regs[2 * coreNum + 1] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_FINE_Q);
+
+ txcal_radio_regs[2 * coreNum + 4] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_COARSE_I);
+ txcal_radio_regs[2 * coreNum + 5] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_COARSE_Q);
+ }
+ }
+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr);
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi)
+{
+ struct nphy_iq_comp tx_comp;
+
+ wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, &tx_comp);
+
+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0);
+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0);
+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1);
+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1);
+}
+
+static void wlc_phy_restorecal_nphy(struct brcms_phy *pi)
+{
+ u16 *loft_comp;
+ u16 txcal_coeffs_bphy[4];
+ u16 *tbl_ptr;
+ int coreNum;
+ u16 *txcal_radio_regs = NULL;
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (pi->nphy_iqcal_chanspec_2G == 0)
+ return;
+
+ tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+ loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5];
} else {
+ if (pi->nphy_iqcal_chanspec_5G == 0)
+ return;
- if (NREV_GE(pi->pubpi.phy_rev, 3)
- && NREV_LT(pi->pubpi.phy_rev, 7)) {
- and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
- mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0);
+ tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+ loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5];
+ }
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16, tbl_ptr);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ txcal_coeffs_bphy[0] = tbl_ptr[0];
+ txcal_coeffs_bphy[1] = tbl_ptr[1];
+ txcal_coeffs_bphy[2] = tbl_ptr[2];
+ txcal_coeffs_bphy[3] = tbl_ptr[3];
+ } else {
+ txcal_coeffs_bphy[0] = 0;
+ txcal_coeffs_bphy[1] = 0;
+ txcal_coeffs_bphy[2] = 0;
+ txcal_coeffs_bphy[3] = 0;
+ }
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16,
+ txcal_coeffs_bphy);
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp);
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp);
+
+ if (NREV_LT(pi->pubpi.phy_rev, 2))
+ wlc_phy_tx_iq_war_nphy(pi);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ txcal_radio_regs =
+ pi->calibration_cache.txcal_radio_regs_2G;
+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
write_radio_reg(pi,
- RADIO_2056_TX_PADA_BOOST_TUNE |
- RADIO_2056_TX0, 0);
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[0]);
write_radio_reg(pi,
- RADIO_2056_TX_PADG_BOOST_TUNE |
- RADIO_2056_TX0, 0);
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[1]);
write_radio_reg(pi,
- RADIO_2056_TX_PGAA_BOOST_TUNE |
- RADIO_2056_TX0, 0);
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[2]);
write_radio_reg(pi,
- RADIO_2056_TX_PGAG_BOOST_TUNE |
- RADIO_2056_TX0, 0);
- mod_radio_reg(pi,
- RADIO_2056_TX_MIXA_BOOST_TUNE |
- RADIO_2056_TX0, 0xf0, 0);
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[3]);
+
write_radio_reg(pi,
- RADIO_2056_TX_MIXG_BOOST_TUNE |
- RADIO_2056_TX0, 0);
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[4]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[5]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[6]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[7]);
+ } else {
+ write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[0]);
+ write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[1]);
+ write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[2]);
+ write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[3]);
+ }
+
+ wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+ &pi->calibration_cache.
+ rxcal_coeffs_2G);
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ txcal_radio_regs =
+ pi->calibration_cache.txcal_radio_regs_5G;
+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
write_radio_reg(pi,
- RADIO_2056_TX_PADA_BOOST_TUNE |
- RADIO_2056_TX1, 0);
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[0]);
write_radio_reg(pi,
- RADIO_2056_TX_PADG_BOOST_TUNE |
- RADIO_2056_TX1, 0);
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[1]);
write_radio_reg(pi,
- RADIO_2056_TX_PGAA_BOOST_TUNE |
- RADIO_2056_TX1, 0);
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[2]);
write_radio_reg(pi,
- RADIO_2056_TX_PGAG_BOOST_TUNE |
- RADIO_2056_TX1, 0);
- mod_radio_reg(pi,
- RADIO_2056_TX_MIXA_BOOST_TUNE |
- RADIO_2056_TX1, 0xf0, 0);
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[3]);
+
write_radio_reg(pi,
- RADIO_2056_TX_MIXG_BOOST_TUNE |
- RADIO_2056_TX1, 0);
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[4]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[5]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[6]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[7]);
+ } else {
+ write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[0]);
+ write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[1]);
+ write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[2]);
+ write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[3]);
+ }
- pi->radio_is_on = false;
+ wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+ &pi->calibration_cache.
+ rxcal_coeffs_5G);
+ }
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_FINE_I,
+ txcal_radio_regs[2 * coreNum]);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_FINE_Q,
+ txcal_radio_regs[2 * coreNum + 1]);
+
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_COARSE_I,
+ txcal_radio_regs[2 * coreNum + 4]);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_COARSE_Q,
+ txcal_radio_regs[2 * coreNum + 5]);
}
+ }
+}
- if (NREV_GE(pi->pubpi.phy_rev, 8)) {
- and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
- pi->radio_is_on = false;
+static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi)
+{
+ u32 idx;
+ u16 iqloCalbuf[7];
+ u32 iqcomp, locomp, curr_locomp;
+ s8 locomp_i, locomp_q;
+ s8 curr_locomp_i, curr_locomp_q;
+ u32 tbl_id, tbl_len, tbl_offset;
+ u32 regval[128];
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+ wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf);
+
+ tbl_len = 128;
+ tbl_offset = 320;
+ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+ iqcomp =
+ (tbl_id ==
+ 26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) |
+ (iqloCalbuf[1] & 0x3ff)
+ : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) |
+ (iqloCalbuf[3] & 0x3ff);
+
+ for (idx = 0; idx < tbl_len; idx++)
+ regval[idx] = iqcomp;
+ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+ regval);
+ }
+
+ tbl_offset = 448;
+ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+
+ locomp =
+ (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]);
+ locomp_i = (s8) ((locomp >> 8) & 0xff);
+ locomp_q = (s8) ((locomp) & 0xff);
+ for (idx = 0; idx < tbl_len; idx++) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ curr_locomp_i = locomp_i;
+ curr_locomp_q = locomp_q;
+ } else {
+ curr_locomp_i = (s8) ((locomp_i *
+ nphy_tpc_loscale[idx] +
+ 128) >> 8);
+ curr_locomp_q =
+ (s8) ((locomp_q *
+ nphy_tpc_loscale[idx] +
+ 128) >> 8);
+ }
+ curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8);
+ curr_locomp |= (u32) (curr_locomp_q & 0xff);
+ regval[idx] = curr_locomp;
}
+ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+ regval);
+ }
+
+ if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+ wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF);
+ wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF);
}
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
}
-static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi)
+static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi)
{
+ u8 tx_lpf_bw = 0;
- and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE);
- or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE);
+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ tx_lpf_bw = 3;
+ else
+ tx_lpf_bw = 1;
- or_phy_reg(pi, 0x78, RFCC_POR_FORCE);
+ if (PHY_IPA(pi)) {
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ tx_lpf_bw = 5;
+ else
+ tx_lpf_bw = 4;
+ }
+
+ write_phy_reg(pi, 0xe8,
+ (tx_lpf_bw << 0) |
+ (tx_lpf_bw << 3) |
+ (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+
+ if (PHY_IPA(pi)) {
+
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ tx_lpf_bw = 4;
+ else
+ tx_lpf_bw = 1;
+
+ write_phy_reg(pi, 0xe9,
+ (tx_lpf_bw << 0) |
+ (tx_lpf_bw << 3) |
+ (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+ }
+ }
}
-static void wlc_phy_radio_init_2055(struct brcms_phy *pi)
+static void
+wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi, u16 reduction_factr)
{
- wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE);
+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+ if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+ CHSPEC_IS40(pi->radio_chanspec)) {
+ if (!pi->nphy_anarxlpf_adjusted) {
+ write_radio_reg(pi,
+ (RADIO_2056_RX_RXLPF_RCCAL_LPC |
+ RADIO_2056_RX0),
+ ((pi->nphy_rccal_value +
+ reduction_factr) | 0x80));
+
+ pi->nphy_anarxlpf_adjusted = true;
+ }
+ } else {
+ if (pi->nphy_anarxlpf_adjusted) {
+ write_radio_reg(pi,
+ (RADIO_2056_RX_RXLPF_RCCAL_LPC |
+ RADIO_2056_RX0),
+ (pi->nphy_rccal_value | 0x80));
+
+ pi->nphy_anarxlpf_adjusted = false;
+ }
+ }
+ }
}
-static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi)
+static void
+wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi, int ntones,
+ int *tone_id_buf, u32 *noise_var_buf)
{
+ int i;
+ u32 offset;
+ int tone_id;
+ int tbllen =
+ CHSPEC_IS40(pi->radio_chanspec) ?
+ NPHY_NOISEVAR_TBLLEN40 : NPHY_NOISEVAR_TBLLEN20;
- and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1,
- ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK));
+ if (pi->nphy_noisevars_adjusted) {
+ for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) {
+ tone_id = pi->nphy_saved_noisevars.tone_id[i];
+ offset = (tone_id >= 0) ?
+ ((tone_id *
+ 2) + 1) : (tbllen + (tone_id * 2) + 1);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_NOISEVAR, 1,
+ offset, 32,
+ &pi->nphy_saved_noisevars.min_noise_vars[i]);
+ }
- if (((pi->sh->sromrev >= 4)
- && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS))
- || ((pi->sh->sromrev < 4))) {
- and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F);
- and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F);
+ pi->nphy_saved_noisevars.bufcount = 0;
+ pi->nphy_noisevars_adjusted = false;
}
- mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C);
- write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C);
+ if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) {
+ pi->nphy_saved_noisevars.bufcount = 0;
- and_radio_reg(pi, RADIO_2055_CAL_MISC,
- ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N));
+ for (i = 0; i < ntones; i++) {
+ tone_id = tone_id_buf[i];
+ offset = (tone_id >= 0) ?
+ ((tone_id * 2) + 1) :
+ (tbllen + (tone_id * 2) + 1);
+ pi->nphy_saved_noisevars.tone_id[i] = tone_id;
+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+ offset, 32,
+ &pi->nphy_saved_noisevars.
+ min_noise_vars[i]);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+ offset, 32, &noise_var_buf[i]);
+ pi->nphy_saved_noisevars.bufcount++;
+ }
- or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE);
+ pi->nphy_noisevars_adjusted = true;
+ }
+}
- or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N);
+static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr)
+{
+ u16 regval;
- udelay(1000);
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+ CHSPEC_IS40(pi->radio_chanspec)) {
+ if (!pi->nphy_crsminpwr_adjusted) {
+ regval = read_phy_reg(pi, 0x27d);
+ pi->nphy_crsminpwr[0] = regval & 0xff;
+ regval &= 0xff00;
+ regval |= (u16) minpwr;
+ write_phy_reg(pi, 0x27d, regval);
- or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START);
+ regval = read_phy_reg(pi, 0x280);
+ pi->nphy_crsminpwr[1] = regval & 0xff;
+ regval &= 0xff00;
+ regval |= (u16) minpwr;
+ write_phy_reg(pi, 0x280, regval);
- SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
- RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000);
+ regval = read_phy_reg(pi, 0x283);
+ pi->nphy_crsminpwr[2] = regval & 0xff;
+ regval &= 0xff00;
+ regval |= (u16) minpwr;
+ write_phy_reg(pi, 0x283, regval);
- if (WARN((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
- RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE,
- "HW error: radio calibration1\n"))
+ pi->nphy_crsminpwr_adjusted = true;
+ }
+ } else {
+ if (pi->nphy_crsminpwr_adjusted) {
+ regval = read_phy_reg(pi, 0x27d);
+ regval &= 0xff00;
+ regval |= pi->nphy_crsminpwr[0];
+ write_phy_reg(pi, 0x27d, regval);
+
+ regval = read_phy_reg(pi, 0x280);
+ regval &= 0xff00;
+ regval |= pi->nphy_crsminpwr[1];
+ write_phy_reg(pi, 0x280, regval);
+
+ regval = read_phy_reg(pi, 0x283);
+ regval &= 0xff00;
+ regval |= pi->nphy_crsminpwr[2];
+ write_phy_reg(pi, 0x283, regval);
+
+ pi->nphy_crsminpwr_adjusted = false;
+ }
+ }
+ }
+}
+
+static void wlc_phy_spurwar_nphy(struct brcms_phy *pi)
+{
+ u16 cur_channel = 0;
+ int nphy_adj_tone_id_buf[] = { 57, 58 };
+ u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff };
+ bool isAdjustNoiseVar = false;
+ uint numTonesAdjust = 0;
+ u32 tempval = 0;
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+ cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+
+ if (pi->nphy_gband_spurwar_en) {
+
+ wlc_phy_adjust_rx_analpfbw_nphy(
+ pi,
+ NPHY_ANARXLPFBW_REDUCTIONFACT);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if ((cur_channel == 11)
+ && CHSPEC_IS40(pi->radio_chanspec))
+ wlc_phy_adjust_min_noisevar_nphy(
+ pi, 2,
+ nphy_adj_tone_id_buf,
+ nphy_adj_noise_var_buf);
+ else
+ wlc_phy_adjust_min_noisevar_nphy(pi, 0,
+ NULL,
+ NULL);
+ }
+
+ wlc_phy_adjust_crsminpwr_nphy(pi,
+ NPHY_ADJUSTED_MINCRSPOWER);
+ }
+
+ if ((pi->nphy_gband_spurwar2_en)
+ && CHSPEC_IS2G(pi->radio_chanspec)) {
+
+ if (CHSPEC_IS40(pi->radio_chanspec)) {
+ switch (cur_channel) {
+ case 3:
+ nphy_adj_tone_id_buf[0] = 57;
+ nphy_adj_tone_id_buf[1] = 58;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x25f;
+ isAdjustNoiseVar = true;
+ break;
+ case 4:
+ nphy_adj_tone_id_buf[0] = 41;
+ nphy_adj_tone_id_buf[1] = 42;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x25f;
+ isAdjustNoiseVar = true;
+ break;
+ case 5:
+ nphy_adj_tone_id_buf[0] = 25;
+ nphy_adj_tone_id_buf[1] = 26;
+ nphy_adj_noise_var_buf[0] = 0x24f;
+ nphy_adj_noise_var_buf[1] = 0x25f;
+ isAdjustNoiseVar = true;
+ break;
+ case 6:
+ nphy_adj_tone_id_buf[0] = 9;
+ nphy_adj_tone_id_buf[1] = 10;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x24f;
+ isAdjustNoiseVar = true;
+ break;
+ case 7:
+ nphy_adj_tone_id_buf[0] = 121;
+ nphy_adj_tone_id_buf[1] = 122;
+ nphy_adj_noise_var_buf[0] = 0x18f;
+ nphy_adj_noise_var_buf[1] = 0x24f;
+ isAdjustNoiseVar = true;
+ break;
+ case 8:
+ nphy_adj_tone_id_buf[0] = 105;
+ nphy_adj_tone_id_buf[1] = 106;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x25f;
+ isAdjustNoiseVar = true;
+ break;
+ case 9:
+ nphy_adj_tone_id_buf[0] = 89;
+ nphy_adj_tone_id_buf[1] = 90;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x24f;
+ isAdjustNoiseVar = true;
+ break;
+ case 10:
+ nphy_adj_tone_id_buf[0] = 73;
+ nphy_adj_tone_id_buf[1] = 74;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x24f;
+ isAdjustNoiseVar = true;
+ break;
+ default:
+ isAdjustNoiseVar = false;
+ break;
+ }
+ }
+
+ if (isAdjustNoiseVar) {
+ numTonesAdjust = sizeof(nphy_adj_tone_id_buf) /
+ sizeof(nphy_adj_tone_id_buf[0]);
+
+ wlc_phy_adjust_min_noisevar_nphy(
+ pi,
+ numTonesAdjust,
+ nphy_adj_tone_id_buf,
+ nphy_adj_noise_var_buf);
+
+ tempval = 0;
+
+ } else {
+ wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+ NULL);
+ }
+ }
+
+ if ((pi->nphy_aband_spurwar_en) &&
+ (CHSPEC_IS5G(pi->radio_chanspec))) {
+ switch (cur_channel) {
+ case 54:
+ nphy_adj_tone_id_buf[0] = 32;
+ nphy_adj_noise_var_buf[0] = 0x25f;
+ break;
+ case 38:
+ case 102:
+ case 118:
+ nphy_adj_tone_id_buf[0] = 0;
+ nphy_adj_noise_var_buf[0] = 0x0;
+ break;
+ case 134:
+ nphy_adj_tone_id_buf[0] = 32;
+ nphy_adj_noise_var_buf[0] = 0x21f;
+ break;
+ case 151:
+ nphy_adj_tone_id_buf[0] = 16;
+ nphy_adj_noise_var_buf[0] = 0x23f;
+ break;
+ case 153:
+ case 161:
+ nphy_adj_tone_id_buf[0] = 48;
+ nphy_adj_noise_var_buf[0] = 0x23f;
+ break;
+ default:
+ nphy_adj_tone_id_buf[0] = 0;
+ nphy_adj_noise_var_buf[0] = 0x0;
+ break;
+ }
+
+ if (nphy_adj_tone_id_buf[0]
+ && nphy_adj_noise_var_buf[0])
+ wlc_phy_adjust_min_noisevar_nphy(
+ pi, 1,
+ nphy_adj_tone_id_buf,
+ nphy_adj_noise_var_buf);
+ else
+ wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+ NULL);
+ }
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+ }
+}
+
+void wlc_phy_init_nphy(struct brcms_phy *pi)
+{
+ u16 val;
+ u16 clip1_ths[2];
+ struct nphy_txgains target_gain;
+ u8 tx_pwr_ctrl_state;
+ bool do_nphy_cal = false;
+ uint core;
+ uint origidx, intr_val;
+ struct d11regs __iomem *regs;
+ u32 d11_clk_ctl_st;
+ bool do_rssi_cal = false;
+
+ core = 0;
+
+ if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN))
+ pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
+
+ if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
+ ((pi->sh->chippkg == BCM4717_PKG_ID) ||
+ (pi->sh->chippkg == BCM4718_PKG_ID))) {
+ if ((pi->sh->boardflags & BFL_EXTLNA) &&
+ (CHSPEC_IS2G(pi->radio_chanspec)))
+ ai_corereg(pi->sh->sih, SI_CC_IDX,
+ offsetof(struct chipcregs, chipcontrol),
+ 0x40, 0x40);
+ }
+
+ if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
+ CHSPEC_IS40(pi->radio_chanspec)) {
+
+ regs = (struct d11regs __iomem *)
+ ai_switch_core(pi->sh->sih,
+ D11_CORE_ID, &origidx,
+ &intr_val);
+ d11_clk_ctl_st = R_REG(&regs->clk_ctl_st);
+ AND_REG(&regs->clk_ctl_st,
+ ~(CCS_FORCEHT | CCS_HTAREQ));
+
+ W_REG(&regs->clk_ctl_st, d11_clk_ctl_st);
+
+ ai_restore_core(pi->sh->sih, origidx, intr_val);
+ }
+
+ pi->use_int_tx_iqlo_cal_nphy =
+ (PHY_IPA(pi) ||
+ (NREV_GE(pi->pubpi.phy_rev, 7) ||
+ (NREV_GE(pi->pubpi.phy_rev, 5)
+ && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL)));
+
+ pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false;
+
+ pi->nphy_deaf_count = 0;
+
+ wlc_phy_tbl_init_nphy(pi);
+
+ pi->nphy_crsminpwr_adjusted = false;
+ pi->nphy_noisevars_adjusted = false;
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ write_phy_reg(pi, 0xe7, 0);
+ write_phy_reg(pi, 0xec, 0);
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ write_phy_reg(pi, 0x342, 0);
+ write_phy_reg(pi, 0x343, 0);
+ write_phy_reg(pi, 0x346, 0);
+ write_phy_reg(pi, 0x347, 0);
+ }
+ write_phy_reg(pi, 0xe5, 0);
+ write_phy_reg(pi, 0xe6, 0);
+ } else {
+ write_phy_reg(pi, 0xec, 0);
+ }
+
+ write_phy_reg(pi, 0x91, 0);
+ write_phy_reg(pi, 0x92, 0);
+ if (NREV_LT(pi->pubpi.phy_rev, 6)) {
+ write_phy_reg(pi, 0x93, 0);
+ write_phy_reg(pi, 0x94, 0);
+ }
+
+ and_phy_reg(pi, 0xa1, ~3);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ write_phy_reg(pi, 0x8f, 0);
+ write_phy_reg(pi, 0xa5, 0);
+ } else {
+ write_phy_reg(pi, 0xa5, 0);
+ }
+
+ if (NREV_IS(pi->pubpi.phy_rev, 2))
+ mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
+ else if (NREV_LT(pi->pubpi.phy_rev, 2))
+ mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
+
+ write_phy_reg(pi, 0x203, 32);
+ write_phy_reg(pi, 0x201, 32);
+
+ if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD)
+ write_phy_reg(pi, 0x20d, 160);
+ else
+ write_phy_reg(pi, 0x20d, 184);
+
+ write_phy_reg(pi, 0x13a, 200);
+
+ write_phy_reg(pi, 0x70, 80);
+
+ write_phy_reg(pi, 0x1ff, 48);
+
+ if (NREV_LT(pi->pubpi.phy_rev, 8))
+ wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override);
+
+ wlc_phy_stf_chain_upd_nphy(pi);
+
+ if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+ write_phy_reg(pi, 0x180, 0xaa8);
+ write_phy_reg(pi, 0x181, 0x9a4);
+ }
+
+ if (PHY_IPA(pi)) {
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (1) << 0);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 :
+ 0x29c, (0x1ff << 7),
+ (pi->nphy_papd_epsilon_offset[core]) << 7);
+
+ }
+
+ wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+ } else if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+ wlc_phy_extpa_set_tx_digi_filts_nphy(pi);
+ }
+
+ wlc_phy_workarounds_nphy(pi);
+
+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+ val = read_phy_reg(pi, 0x01);
+ write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+ write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+ wlapi_bmac_macphyclk_set(pi->sh->physhim, ON);
+
+ wlc_phy_pa_override_nphy(pi, OFF);
+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+ wlc_phy_pa_override_nphy(pi, ON);
+
+ wlc_phy_classifier_nphy(pi, 0, 0);
+ wlc_phy_clip_det_nphy(pi, 0, clip1_ths);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ wlc_phy_bphy_init_nphy(pi);
+
+ tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+ wlc_phy_txpwr_fixpower_nphy(pi);
+
+ wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+
+ wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ u32 *tx_pwrctrl_tbl = NULL;
+ u16 idx;
+ s16 pga_gn = 0;
+ s16 pad_gn = 0;
+ s32 rfpwr_offset;
+
+ if (PHY_IPA(pi)) {
+ tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi);
+ } else {
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ if (NREV_IS(pi->pubpi.phy_rev, 3))
+ tx_pwrctrl_tbl =
+ nphy_tpc_5GHz_txgain_rev3;
+ else if (NREV_IS(pi->pubpi.phy_rev, 4))
+ tx_pwrctrl_tbl =
+ (pi->srom_fem5g.extpagain ==
+ 3) ?
+ nphy_tpc_5GHz_txgain_HiPwrEPA :
+ nphy_tpc_5GHz_txgain_rev4;
+ else
+ tx_pwrctrl_tbl =
+ nphy_tpc_5GHz_txgain_rev5;
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (pi->pubpi.radiorev == 5)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_epa_2057rev5;
+ else if (pi->pubpi.radiorev == 3)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_epa_2057rev3;
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+ (pi->srom_fem2g.extpagain == 3))
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_HiPwrEPA;
+ else
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_rev3;
+ }
+ }
+ }
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+ 192, 32, tx_pwrctrl_tbl);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+ 192, 32, tx_pwrctrl_tbl);
+
+ pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ for (idx = 0; idx < 128; idx++) {
+ pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+ pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f;
+ rfpwr_offset = get_rf_pwr_offset(pi, pga_gn,
+ pad_gn);
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_CORE1TXPWRCTL,
+ 1, 576 + idx, 32,
+ &rfpwr_offset);
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_CORE2TXPWRCTL,
+ 1, 576 + idx, 32,
+ &rfpwr_offset);
+ }
+ } else {
+
+ for (idx = 0; idx < 128; idx++) {
+ pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ rfpwr_offset = (s16)
+ nphy_papd_pga_gain_delta_ipa_2g
+ [pga_gn];
+ else
+ rfpwr_offset = (s16)
+ nphy_papd_pga_gain_delta_ipa_5g
+ [pga_gn];
+
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_CORE1TXPWRCTL,
+ 1, 576 + idx, 32,
+ &rfpwr_offset);
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_CORE2TXPWRCTL,
+ 1, 576 + idx, 32,
+ &rfpwr_offset);
+ }
+
+ }
+ } else {
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+ 192, 32, nphy_tpc_txgain);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+ 192, 32, nphy_tpc_txgain);
+ }
+
+ if (pi->sh->phyrxchain != 0x3)
+ wlc_phy_rxcore_setstate_nphy((struct brcms_phy_pub *) pi,
+ pi->sh->phyrxchain);
+
+ if (PHY_PERICAL_MPHASE_PENDING(pi))
+ wlc_phy_cal_perical_mphase_restart(pi);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+ (pi->nphy_rssical_chanspec_2G == 0) :
+ (pi->nphy_rssical_chanspec_5G == 0);
+
+ if (do_rssi_cal)
+ wlc_phy_rssi_cal_nphy(pi);
+ else
+ wlc_phy_restore_rssical_nphy(pi);
+ } else {
+ wlc_phy_rssi_cal_nphy(pi);
+ }
+
+ if (!SCAN_RM_IN_PROGRESS(pi))
+ do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+ (pi->nphy_iqcal_chanspec_2G == 0) :
+ (pi->nphy_iqcal_chanspec_5G == 0);
+
+ if (!pi->do_initcal)
+ do_nphy_cal = false;
+
+ if (do_nphy_cal) {
+
+ target_gain = wlc_phy_get_tx_gain_nphy(pi);
+
+ if (pi->antsel_type == ANTSEL_2x3)
+ wlc_phy_antsel_init((struct brcms_phy_pub *) pi,
+ true);
+
+ if (pi->nphy_perical != PHY_PERICAL_MPHASE) {
+ wlc_phy_rssi_cal_nphy(pi);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ pi->nphy_cal_orig_pwr_idx[0] =
+ pi->nphy_txpwrindex[PHY_CORE_0]
+ .
+ index_internal;
+ pi->nphy_cal_orig_pwr_idx[1] =
+ pi->nphy_txpwrindex[PHY_CORE_1]
+ .
+ index_internal;
+
+ wlc_phy_precal_txgain_nphy(pi);
+ target_gain =
+ wlc_phy_get_tx_gain_nphy(pi);
+ }
+
+ if (wlc_phy_cal_txiqlo_nphy
+ (pi, target_gain, true,
+ false) == 0) {
+ if (wlc_phy_cal_rxiq_nphy
+ (pi, target_gain, 2,
+ false) == 0)
+ wlc_phy_savecal_nphy(pi);
+
+ }
+ } else if (pi->mphase_cal_phase_id ==
+ MPHASE_CAL_STATE_IDLE) {
+ wlc_phy_cal_perical((struct brcms_phy_pub *) pi,
+ PHY_PERICAL_PHYINIT);
+ }
+ } else {
+ wlc_phy_restorecal_nphy(pi);
+ }
+
+ wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+
+ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+
+ wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6))
+
+ write_phy_reg(pi, 0x70, 50);
+
+ wlc_phy_txlpfbw_nphy(pi);
+
+ wlc_phy_spurwar_nphy(pi);
+
+}
+
+static void wlc_phy_resetcca_nphy(struct brcms_phy *pi)
+{
+ u16 val;
+
+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+ val = read_phy_reg(pi, 0x01);
+ write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+ udelay(1);
+ write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+
+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+}
+
+void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en)
+{
+ u16 rfctrlintc_override_val;
+
+ if (!en) {
+
+ pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91);
+ pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ rfctrlintc_override_val = 0x1480;
+ else if (NREV_GE(pi->pubpi.phy_rev, 3))
+ rfctrlintc_override_val =
+ CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480;
+ else
+ rfctrlintc_override_val =
+ CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+
+ write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+ write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+ } else {
+ write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save);
+ write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save);
+ }
+
+}
+
+void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi)
+{
+
+ u16 txrx_chain =
+ (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1);
+ bool CoreActv_override = false;
+
+ if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN0) {
+ txrx_chain = NPHY_RfseqCoreActv_TxRxChain0;
+ CoreActv_override = true;
+
+ if (NREV_LE(pi->pubpi.phy_rev, 2))
+ and_phy_reg(pi, 0xa0, ~0x20);
+ } else if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN1) {
+ txrx_chain = NPHY_RfseqCoreActv_TxRxChain1;
+ CoreActv_override = true;
+
+ if (NREV_LE(pi->pubpi.phy_rev, 2))
+ or_phy_reg(pi, 0xa0, 0x20);
+ }
+
+ mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain);
+
+ if (CoreActv_override) {
+ pi->nphy_perical = PHY_PERICAL_DISABLE;
+ or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
+ } else {
+ pi->nphy_perical = PHY_PERICAL_MPHASE;
+ and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override);
+ }
+}
+
+void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask)
+{
+ u16 regval;
+ u16 tbl_buf[16];
+ uint i;
+ struct brcms_phy *pi = (struct brcms_phy *) pih;
+ u16 tbl_opcode;
+ bool suspend;
+
+ pi->sh->phyrxchain = rxcore_bitmask;
+
+ if (!pi->sh->clk)
return;
- and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL,
- ~(RADIO_2055_CAL_LPO_ENABLE));
+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ if (!suspend)
+ wlapi_suspend_mac_and_wait(pi->sh->physhim);
- wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
- write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9);
- write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9);
+ regval = read_phy_reg(pi, 0xa2);
+ regval &= ~(0xf << 4);
+ regval |= ((u16) (rxcore_bitmask & 0x3)) << 4;
+ write_phy_reg(pi, 0xa2, regval);
- write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83);
- write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83);
+ if ((rxcore_bitmask & 0x3) != 0x3) {
- mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST,
- RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
- mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST,
- RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
- if (pi->nphy_gain_boost) {
- and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
- ~(RADIO_2055_GAINBST_DISABLE));
- and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
- ~(RADIO_2055_GAINBST_DISABLE));
+ write_phy_reg(pi, 0x20e, 1);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (pi->rx2tx_biasentry == -1) {
+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ,
+ ARRAY_SIZE(tbl_buf), 80,
+ 16, tbl_buf);
+
+ for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) {
+ if (tbl_buf[i] ==
+ NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) {
+ pi->rx2tx_biasentry = (u8) i;
+ tbl_opcode =
+ NPHY_REV3_RFSEQ_CMD_NOP;
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_RFSEQ,
+ 1, i,
+ 16,
+ &tbl_opcode);
+ break;
+ } else if (tbl_buf[i] ==
+ NPHY_REV3_RFSEQ_CMD_END)
+ break;
+ }
+ }
+ }
} else {
- or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
- RADIO_2055_GAINBST_DISABLE);
- or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
- RADIO_2055_GAINBST_DISABLE);
+
+ write_phy_reg(pi, 0x20e, 30);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (pi->rx2tx_biasentry != -1) {
+ tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+ 1, pi->rx2tx_biasentry,
+ 16, &tbl_opcode);
+ pi->rx2tx_biasentry = -1;
+ }
+ }
}
- udelay(2);
+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+ if (!suspend)
+ wlapi_enable_mac(pi->sh->physhim);
+}
+
+u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih)
+{
+ u16 regval, rxen_bits;
+ struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+ regval = read_phy_reg(pi, 0xa2);
+ rxen_bits = (regval >> 4) & 0xf;
+
+ return (u8) rxen_bits;
+}
+
+bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pi)
+{
+ return PHY_IPA(pi);
+}
+
+void wlc_phy_cal_init_nphy(struct brcms_phy *pi)
+{
}
static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi)
@@ -17442,11 +20004,257 @@ static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi)
}
+static void wlc_phy_radio_init_2057(struct brcms_phy *pi)
+{
+ struct radio_20xx_regs *regs_2057_ptr = NULL;
+
+ if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+ regs_2057_ptr = regs_2057_rev4;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 8)
+ || NREV_IS(pi->pubpi.phy_rev, 9)) {
+ switch (pi->pubpi.radiorev) {
+ case 5:
+
+ if (pi->pubpi.radiover == 0x0)
+ regs_2057_ptr = regs_2057_rev5;
+ else if (pi->pubpi.radiover == 0x1)
+ regs_2057_ptr = regs_2057_rev5v1;
+ else
+ break;
+
+ case 7:
+
+ regs_2057_ptr = regs_2057_rev7;
+ break;
+
+ case 8:
+
+ regs_2057_ptr = regs_2057_rev8;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr);
+}
+
+static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi)
+{
+ u16 rcal_reg = 0;
+ int i;
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ if (pi->pubpi.radiorev == 5) {
+
+ and_phy_reg(pi, 0x342, ~(0x1 << 1));
+
+ udelay(10);
+
+ mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1);
+ mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+ 0x1);
+ }
+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1);
+
+ udelay(10);
+
+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3);
+
+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+ rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS);
+ if (rcal_reg & 0x1)
+ break;
+
+ udelay(100);
+ }
+
+ if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
+ "HW error: radio calib2"))
+ return 0;
+
+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0);
+
+ rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e;
+
+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0);
+ if (pi->pubpi.radiorev == 5) {
+
+ mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0);
+ mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+ 0x0);
+ }
+
+ if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
+
+ mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c,
+ rcal_reg);
+ mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0,
+ rcal_reg << 2);
+ }
+
+ } else if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+ u16 savereg;
+
+ savereg =
+ read_radio_reg(
+ pi,
+ RADIO_2056_SYN_PLL_MAST2 |
+ RADIO_2056_SYN);
+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+ savereg | 0x7);
+ udelay(10);
+
+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+ 0x1);
+ udelay(10);
+
+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+ 0x9);
+
+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+ rcal_reg = read_radio_reg(
+ pi,
+ RADIO_2056_SYN_RCAL_CODE_OUT |
+ RADIO_2056_SYN);
+ if (rcal_reg & 0x80)
+ break;
+
+ udelay(100);
+ }
+
+ if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
+ "HW error: radio calib3"))
+ return 0;
+
+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+ 0x1);
+
+ rcal_reg =
+ read_radio_reg(pi,
+ RADIO_2056_SYN_RCAL_CODE_OUT |
+ RADIO_2056_SYN);
+
+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+ 0x0);
+
+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+ savereg);
+
+ return rcal_reg & 0x1f;
+ }
+ return rcal_reg & 0x3e;
+}
+
+static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi)
+{
+ u16 rccal_valid;
+ int i;
+ bool chip43226_6362A0;
+
+ chip43226_6362A0 = ((pi->pubpi.radiorev == 3)
+ || (pi->pubpi.radiorev == 4)
+ || (pi->pubpi.radiorev == 6));
+
+ rccal_valid = 0;
+ if (chip43226_6362A0) {
+ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61);
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0);
+ } else {
+ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61);
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9);
+ }
+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+ if (rccal_valid & 0x2)
+ break;
+
+ udelay(500);
+ }
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+ rccal_valid = 0;
+ if (chip43226_6362A0) {
+ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69);
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+ } else {
+ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69);
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5);
+ }
+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+ if (rccal_valid & 0x2)
+ break;
+
+ udelay(500);
+ }
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+ rccal_valid = 0;
+ if (chip43226_6362A0) {
+ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73);
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28);
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+ } else {
+ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73);
+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99);
+ }
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+ if (rccal_valid & 0x2)
+ break;
+
+ udelay(500);
+ }
+
+ if (WARN(!(rccal_valid & 0x2), "HW error: radio calib4"))
+ return 0;
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+ return rccal_valid;
+}
+
+static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi)
+{
+
+ mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1);
+
+ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78);
+ mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80);
+ mdelay(2);
+ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0);
+ mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0);
+
+ if (pi->phy_init_por) {
+ wlc_phy_radio205x_rcal(pi);
+ wlc_phy_radio2057_rccal(pi);
+ }
+
+ mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0);
+}
+
static void wlc_phy_radio_init_2056(struct brcms_phy *pi)
{
- struct radio_regs *regs_SYN_2056_ptr = NULL;
- struct radio_regs *regs_TX_2056_ptr = NULL;
- struct radio_regs *regs_RX_2056_ptr = NULL;
+ const struct radio_regs *regs_SYN_2056_ptr = NULL;
+ const struct radio_regs *regs_TX_2056_ptr = NULL;
+ const struct radio_regs *regs_RX_2056_ptr = NULL;
if (NREV_IS(pi->pubpi.phy_rev, 3)) {
regs_SYN_2056_ptr = regs_SYN_2056;
@@ -17515,92 +20323,190 @@ static void wlc_phy_radio_postinit_2056(struct brcms_phy *pi)
mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0);
if ((pi->sh->boardflags2 & BFL2_LEGACY)
- || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) {
-
+ || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN))
mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0);
- } else {
-
+ else
mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0);
- }
mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0);
- if (pi->phy_init_por) {
+ if (pi->phy_init_por)
wlc_phy_radio205x_rcal(pi);
- }
}
-static void wlc_phy_radio_init_2057(struct brcms_phy *pi)
+static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi)
{
- struct radio_20xx_regs *regs_2057_ptr = NULL;
- if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+ and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE);
+ or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE);
- regs_2057_ptr = regs_2057_rev4;
- } else if (NREV_IS(pi->pubpi.phy_rev, 8)
- || NREV_IS(pi->pubpi.phy_rev, 9)) {
- switch (pi->pubpi.radiorev) {
- case 5:
+ or_phy_reg(pi, 0x78, RFCC_POR_FORCE);
+}
- if (pi->pubpi.radiover == 0x0) {
+static void wlc_phy_radio_init_2055(struct brcms_phy *pi)
+{
+ wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE);
+}
- regs_2057_ptr = regs_2057_rev5;
+static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi)
+{
- } else if (pi->pubpi.radiover == 0x1) {
+ and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1,
+ ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK));
- regs_2057_ptr = regs_2057_rev5v1;
- } else {
- break;
- }
+ if (((pi->sh->sromrev >= 4)
+ && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS))
+ || ((pi->sh->sromrev < 4))) {
+ and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F);
+ and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F);
+ }
- case 7:
+ mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C);
+ write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C);
- regs_2057_ptr = regs_2057_rev7;
- break;
+ and_radio_reg(pi, RADIO_2055_CAL_MISC,
+ ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N));
- case 8:
+ or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE);
- regs_2057_ptr = regs_2057_rev8;
- break;
+ or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N);
- default:
- break;
- }
+ udelay(1000);
+
+ or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START);
+
+ SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+ RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000);
+
+ if (WARN((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+ RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE,
+ "HW error: radio calibration1\n"))
+ return;
+
+ and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL,
+ ~(RADIO_2055_CAL_LPO_ENABLE));
+
+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
+
+ write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9);
+ write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9);
+
+ write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83);
+ write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83);
+
+ mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST,
+ RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+ mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST,
+ RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+ if (pi->nphy_gain_boost) {
+ and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+ ~(RADIO_2055_GAINBST_DISABLE));
+ and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+ ~(RADIO_2055_GAINBST_DISABLE));
+ } else {
+ or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+ RADIO_2055_GAINBST_DISABLE);
+ or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+ RADIO_2055_GAINBST_DISABLE);
}
- wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr);
+ udelay(2);
}
-static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi)
+void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on)
{
+ if (on) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (!pi->radio_is_on) {
+ wlc_phy_radio_preinit_205x(pi);
+ wlc_phy_radio_init_2057(pi);
+ wlc_phy_radio_postinit_2057(pi);
+ }
- mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1);
+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
+ pi->radio_chanspec);
+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ wlc_phy_radio_preinit_205x(pi);
+ wlc_phy_radio_init_2056(pi);
+ wlc_phy_radio_postinit_2056(pi);
- mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78);
- mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80);
- mdelay(2);
- mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0);
- mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0);
+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
+ pi->radio_chanspec);
+ } else {
+ wlc_phy_radio_preinit_2055(pi);
+ wlc_phy_radio_init_2055(pi);
+ wlc_phy_radio_postinit_2055(pi);
+ }
- if (pi->phy_init_por) {
- wlc_phy_radio205x_rcal(pi);
- wlc_phy_radio2057_rccal(pi);
- }
+ pi->radio_is_on = true;
- mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0);
+ } else {
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)
+ && NREV_LT(pi->pubpi.phy_rev, 7)) {
+ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+ mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0);
+
+ write_radio_reg(pi,
+ RADIO_2056_TX_PADA_BOOST_TUNE |
+ RADIO_2056_TX0, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PADG_BOOST_TUNE |
+ RADIO_2056_TX0, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PGAA_BOOST_TUNE |
+ RADIO_2056_TX0, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PGAG_BOOST_TUNE |
+ RADIO_2056_TX0, 0);
+ mod_radio_reg(pi,
+ RADIO_2056_TX_MIXA_BOOST_TUNE |
+ RADIO_2056_TX0, 0xf0, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_MIXG_BOOST_TUNE |
+ RADIO_2056_TX0, 0);
+
+ write_radio_reg(pi,
+ RADIO_2056_TX_PADA_BOOST_TUNE |
+ RADIO_2056_TX1, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PADG_BOOST_TUNE |
+ RADIO_2056_TX1, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PGAA_BOOST_TUNE |
+ RADIO_2056_TX1, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PGAG_BOOST_TUNE |
+ RADIO_2056_TX1, 0);
+ mod_radio_reg(pi,
+ RADIO_2056_TX_MIXA_BOOST_TUNE |
+ RADIO_2056_TX1, 0xf0, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_MIXG_BOOST_TUNE |
+ RADIO_2056_TX1, 0);
+
+ pi->radio_is_on = false;
+ }
+
+ if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+ pi->radio_is_on = false;
+ }
+
+ }
}
static bool
wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
- struct chan_info_nphy_radio2057 **t0,
- struct chan_info_nphy_radio205x **t1,
- struct chan_info_nphy_radio2057_rev5 **t2,
- struct chan_info_nphy_2055 **t3)
+ const struct chan_info_nphy_radio2057 **t0,
+ const struct chan_info_nphy_radio205x **t1,
+ const struct chan_info_nphy_radio2057_rev5 **t2,
+ const struct chan_info_nphy_2055 **t3)
{
uint i;
- struct chan_info_nphy_radio2057 *chan_info_tbl_p_0 = NULL;
- struct chan_info_nphy_radio205x *chan_info_tbl_p_1 = NULL;
- struct chan_info_nphy_radio2057_rev5 *chan_info_tbl_p_2 = NULL;
+ const struct chan_info_nphy_radio2057 *chan_info_tbl_p_0 = NULL;
+ const struct chan_info_nphy_radio205x *chan_info_tbl_p_1 = NULL;
+ const struct chan_info_nphy_radio2057_rev5 *chan_info_tbl_p_2 = NULL;
u32 tbl_len = 0;
int freq = 0;
@@ -17621,40 +20527,35 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
if (pi->pubpi.radiover == 0x0) {
chan_info_tbl_p_2 =
- chan_info_nphyrev8_2057_rev5;
- tbl_len =
- ARRAY_SIZE
- (chan_info_nphyrev8_2057_rev5);
+ chan_info_nphyrev8_2057_rev5;
+ tbl_len = ARRAY_SIZE(
+ chan_info_nphyrev8_2057_rev5);
} else if (pi->pubpi.radiover == 0x1) {
chan_info_tbl_p_2 =
- chan_info_nphyrev9_2057_rev5v1;
- tbl_len =
- ARRAY_SIZE
- (chan_info_nphyrev9_2057_rev5v1);
+ chan_info_nphyrev9_2057_rev5v1;
+ tbl_len = ARRAY_SIZE(
+ chan_info_nphyrev9_2057_rev5v1);
}
break;
case 7:
chan_info_tbl_p_0 =
- chan_info_nphyrev8_2057_rev7;
- tbl_len =
- ARRAY_SIZE(chan_info_nphyrev8_2057_rev7);
+ chan_info_nphyrev8_2057_rev7;
+ tbl_len = ARRAY_SIZE(
+ chan_info_nphyrev8_2057_rev7);
break;
case 8:
chan_info_tbl_p_0 =
- chan_info_nphyrev8_2057_rev8;
- tbl_len =
- ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
+ chan_info_nphyrev8_2057_rev8;
+ tbl_len = ARRAY_SIZE(
+ chan_info_nphyrev8_2057_rev8);
break;
default:
- if (NORADIO_ENAB(pi->pubpi)) {
- goto fail;
- }
break;
}
} else if (NREV_IS(pi->pubpi.phy_rev, 16)) {
@@ -17677,9 +20578,9 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
}
}
- if (i >= tbl_len) {
+ if (i >= tbl_len)
goto fail;
- }
+
if (pi->pubpi.radiorev == 5) {
*t2 = &chan_info_tbl_p_2[i];
freq = chan_info_tbl_p_2[i].freq;
@@ -17710,7 +20611,7 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
case 9:
chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7;
tbl_len =
- ARRAY_SIZE(chan_info_nphyrev5n6_2056v7);
+ ARRAY_SIZE(chan_info_nphyrev5n6_2056v7);
break;
case 8:
chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8;
@@ -17718,12 +20619,10 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
break;
case 11:
chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11;
- tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v11);
+ tbl_len = ARRAY_SIZE(
+ chan_info_nphyrev6_2056v11);
break;
default:
- if (NORADIO_ENAB(pi->pubpi)) {
- goto fail;
- }
break;
}
}
@@ -17733,9 +20632,9 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
break;
}
- if (i >= tbl_len) {
+ if (i >= tbl_len)
goto fail;
- }
+
*t1 = &chan_info_tbl_p_1[i];
freq = chan_info_tbl_p_1[i].freq;
@@ -17744,9 +20643,9 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
if (chan_info_nphy_2055[i].chan == channel)
break;
- if (i >= ARRAY_SIZE(chan_info_nphy_2055)) {
+ if (i >= ARRAY_SIZE(chan_info_nphy_2055))
goto fail;
- }
+
*t3 = &chan_info_nphy_2055[i];
freq = chan_info_nphy_2055[i].freq;
}
@@ -17754,7 +20653,7 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
*f = freq;
return true;
- fail:
+fail:
*f = WL_CHAN_FREQ_RANGE_2G;
return false;
}
@@ -17762,13 +20661,10 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint channel)
{
int freq;
- struct chan_info_nphy_radio2057 *t0 = NULL;
- struct chan_info_nphy_radio205x *t1 = NULL;
- struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
- struct chan_info_nphy_2055 *t3 = NULL;
-
- if (NORADIO_ENAB(pi->pubpi))
- return WL_CHAN_FREQ_RANGE_2G;
+ const struct chan_info_nphy_radio2057 *t0 = NULL;
+ const struct chan_info_nphy_radio205x *t1 = NULL;
+ const struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
+ const struct chan_info_nphy_2055 *t3 = NULL;
if (channel == 0)
channel = CHSPEC_CHANNEL(pi->radio_chanspec);
@@ -17778,18 +20674,17 @@ u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint channel)
if (CHSPEC_IS2G(pi->radio_chanspec))
return WL_CHAN_FREQ_RANGE_2G;
- if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) {
+ if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN))
return WL_CHAN_FREQ_RANGE_5GL;
- } else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) {
+ else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN))
return WL_CHAN_FREQ_RANGE_5GM;
- } else {
+ else
return WL_CHAN_FREQ_RANGE_5GH;
- }
}
static void
wlc_phy_chanspec_radio2055_setup(struct brcms_phy *pi,
- struct chan_info_nphy_2055 *ci)
+ const struct chan_info_nphy_2055 *ci)
{
write_radio_reg(pi, RADIO_2055_PLL_REF, ci->RF_pll_ref);
@@ -17854,7 +20749,7 @@ static void
wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
const struct chan_info_nphy_radio205x *ci)
{
- struct radio_regs *regs_SYN_2056_ptr = NULL;
+ const struct radio_regs *regs_SYN_2056_ptr = NULL;
write_radio_reg(pi,
RADIO_2056_SYN_PLL_VCOCAL1 | RADIO_2056_SYN,
@@ -17960,15 +20855,14 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
break;
}
}
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec))
write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
RADIO_2056_SYN,
(u16) regs_SYN_2056_ptr[0x49 - 2].init_g);
- } else {
+ else
write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
RADIO_2056_SYN,
(u16) regs_SYN_2056_ptr[0x49 - 2].init_a);
- }
if (pi->sh->boardflags2 & BFL2_GPLL_WAR) {
if (CHSPEC_IS2G(pi->radio_chanspec)) {
@@ -18069,7 +20963,8 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
mixg_boost_tune);
} else {
- bias = IS40MHZ(pi) ? 0x40 : 0x20;
+ bias = (pi->bw == WL_CHANSPEC_BW_40) ?
+ 0x40 : 0x20;
WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
INTPAG_IMAIN_STAT, bias);
@@ -18116,11 +21011,11 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
paa_boost_tune = 0x0;
pada_boost_tune = 0x77;
- if (freq != 5825) {
+ if (freq != 5825)
pgaa_boost_tune = -(int)(freq - 18) / 36 + 168;
- } else {
+ else
pgaa_boost_tune = 6;
- }
+
mixa_boost_tune = 0xf;
}
@@ -18146,9 +21041,8 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
if ((pi->sh->chip == BCM43224_CHIP_ID) ||
(pi->sh->chip == BCM43225_CHIP_ID)) {
- if (pi->sh->chippkg == BCM43224_FAB_SMIC) {
+ if (pi->sh->chippkg == BCM43224_FAB_SMIC)
cascbias = 0x35;
- }
}
pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias;
@@ -18186,117 +21080,12 @@ void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi)
udelay(300);
}
-#define MAX_205x_RCAL_WAITLOOPS 10000
-
-static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi)
-{
- u16 rcal_reg = 0;
- int i;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- if (pi->pubpi.radiorev == 5) {
-
- and_phy_reg(pi, 0x342, ~(0x1 << 1));
-
- udelay(10);
-
- mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1);
- mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
- 0x1);
- }
- mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1);
-
- udelay(10);
-
- mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3);
-
- for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
- rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS);
- if (rcal_reg & 0x1) {
- break;
- }
- udelay(100);
- }
-
- if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
- "HW error: radio calib2"))
- return 0;
-
- mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0);
-
- rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e;
-
- mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0);
- if (pi->pubpi.radiorev == 5) {
-
- mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0);
- mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
- 0x0);
- }
-
- if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
-
- mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c,
- rcal_reg);
- mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0,
- rcal_reg << 2);
- }
-
- } else if (NREV_IS(pi->pubpi.phy_rev, 3)) {
- u16 savereg;
-
- savereg =
- read_radio_reg(pi,
- RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN);
- write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
- savereg | 0x7);
- udelay(10);
-
- write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
- 0x1);
- udelay(10);
-
- write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
- 0x9);
-
- for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
- rcal_reg = read_radio_reg(pi,
- RADIO_2056_SYN_RCAL_CODE_OUT |
- RADIO_2056_SYN);
- if (rcal_reg & 0x80) {
- break;
- }
- udelay(100);
- }
-
- if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
- "HW error: radio calib3"))
- return 0;
-
- write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
- 0x1);
-
- rcal_reg =
- read_radio_reg(pi,
- RADIO_2056_SYN_RCAL_CODE_OUT |
- RADIO_2056_SYN);
-
- write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
- 0x0);
-
- write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
- savereg);
-
- return rcal_reg & 0x1f;
- }
- return rcal_reg & 0x3e;
-}
-
static void
-wlc_phy_chanspec_radio2057_setup(struct brcms_phy *pi,
- const struct chan_info_nphy_radio2057 *ci,
- const struct chan_info_nphy_radio2057_rev5 *ci2)
+wlc_phy_chanspec_radio2057_setup(
+ struct brcms_phy *pi,
+ const struct chan_info_nphy_radio2057 *ci,
+ const struct chan_info_nphy_radio2057_rev5 *
+ ci2)
{
int coreNum;
u16 txmix2g_tune_boost_pu = 0;
@@ -18455,9 +21244,8 @@ wlc_phy_chanspec_radio2057_setup(struct brcms_phy *pi,
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if (PHY_IPA(pi)) {
- if (pi->pubpi.radiorev == 3) {
+ if (pi->pubpi.radiorev == 3)
txmix2g_tune_boost_pu = 0x6b;
- }
if (pi->pubpi.radiorev == 5)
pad2g_tune_pus = 0x73;
@@ -18489,430 +21277,8 @@ wlc_phy_chanspec_radio2057_setup(struct brcms_phy *pi,
wlc_phy_radio205x_vcocal_nphy(pi);
}
-static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi)
-{
- u16 rccal_valid;
- int i;
- bool chip43226_6362A0;
-
- chip43226_6362A0 = ((pi->pubpi.radiorev == 3)
- || (pi->pubpi.radiorev == 4)
- || (pi->pubpi.radiorev == 6));
-
- rccal_valid = 0;
- if (chip43226_6362A0) {
- write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61);
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0);
- } else {
- write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61);
-
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9);
- }
- write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
- for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
- rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
- if (rccal_valid & 0x2) {
- break;
- }
- udelay(500);
- }
-
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
- rccal_valid = 0;
- if (chip43226_6362A0) {
- write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69);
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
- } else {
- write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69);
-
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5);
- }
- write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
- for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
- rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
- if (rccal_valid & 0x2) {
- break;
- }
- udelay(500);
- }
-
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
- rccal_valid = 0;
- if (chip43226_6362A0) {
- write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73);
-
- write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28);
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
- } else {
- write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73);
- write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99);
- }
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
- for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
- rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
- if (rccal_valid & 0x2) {
- break;
- }
- udelay(500);
- }
-
- if (WARN(!(rccal_valid & 0x2), "HW error: radio calib4"))
- return 0;
-
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
- return rccal_valid;
-}
-
-static void
-wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi, u16 reduction_factr)
-{
- if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
- if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
- CHSPEC_IS40(pi->radio_chanspec)) {
- if (!pi->nphy_anarxlpf_adjusted) {
- write_radio_reg(pi,
- (RADIO_2056_RX_RXLPF_RCCAL_LPC |
- RADIO_2056_RX0),
- ((pi->nphy_rccal_value +
- reduction_factr) | 0x80));
-
- pi->nphy_anarxlpf_adjusted = true;
- }
- } else {
- if (pi->nphy_anarxlpf_adjusted) {
- write_radio_reg(pi,
- (RADIO_2056_RX_RXLPF_RCCAL_LPC |
- RADIO_2056_RX0),
- (pi->nphy_rccal_value | 0x80));
-
- pi->nphy_anarxlpf_adjusted = false;
- }
- }
- }
-}
-
-static void
-wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi, int ntones,
- int *tone_id_buf, u32 *noise_var_buf)
-{
- int i;
- u32 offset;
- int tone_id;
- int tbllen =
- CHSPEC_IS40(pi->
- radio_chanspec) ? NPHY_NOISEVAR_TBLLEN40 :
- NPHY_NOISEVAR_TBLLEN20;
-
- if (pi->nphy_noisevars_adjusted) {
- for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) {
- tone_id = pi->nphy_saved_noisevars.tone_id[i];
- offset = (tone_id >= 0) ?
- ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
- offset, 32,
- (void *)&pi->
- nphy_saved_noisevars.
- min_noise_vars[i]);
- }
-
- pi->nphy_saved_noisevars.bufcount = 0;
- pi->nphy_noisevars_adjusted = false;
- }
-
- if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) {
- pi->nphy_saved_noisevars.bufcount = 0;
-
- for (i = 0; i < ntones; i++) {
- tone_id = tone_id_buf[i];
- offset = (tone_id >= 0) ?
- ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
- pi->nphy_saved_noisevars.tone_id[i] = tone_id;
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
- offset, 32,
- &pi->nphy_saved_noisevars.
- min_noise_vars[i]);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
- offset, 32,
- (void *)&noise_var_buf[i]);
- pi->nphy_saved_noisevars.bufcount++;
- }
-
- pi->nphy_noisevars_adjusted = true;
- }
-}
-
-static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr)
-{
- u16 regval;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
- CHSPEC_IS40(pi->radio_chanspec)) {
- if (!pi->nphy_crsminpwr_adjusted) {
- regval = read_phy_reg(pi, 0x27d);
- pi->nphy_crsminpwr[0] = regval & 0xff;
- regval &= 0xff00;
- regval |= (u16) minpwr;
- write_phy_reg(pi, 0x27d, regval);
-
- regval = read_phy_reg(pi, 0x280);
- pi->nphy_crsminpwr[1] = regval & 0xff;
- regval &= 0xff00;
- regval |= (u16) minpwr;
- write_phy_reg(pi, 0x280, regval);
-
- regval = read_phy_reg(pi, 0x283);
- pi->nphy_crsminpwr[2] = regval & 0xff;
- regval &= 0xff00;
- regval |= (u16) minpwr;
- write_phy_reg(pi, 0x283, regval);
-
- pi->nphy_crsminpwr_adjusted = true;
- }
- } else {
- if (pi->nphy_crsminpwr_adjusted) {
- regval = read_phy_reg(pi, 0x27d);
- regval &= 0xff00;
- regval |= pi->nphy_crsminpwr[0];
- write_phy_reg(pi, 0x27d, regval);
-
- regval = read_phy_reg(pi, 0x280);
- regval &= 0xff00;
- regval |= pi->nphy_crsminpwr[1];
- write_phy_reg(pi, 0x280, regval);
-
- regval = read_phy_reg(pi, 0x283);
- regval &= 0xff00;
- regval |= pi->nphy_crsminpwr[2];
- write_phy_reg(pi, 0x283, regval);
-
- pi->nphy_crsminpwr_adjusted = false;
- }
- }
- }
-}
-
-static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi)
-{
- u8 tx_lpf_bw = 0;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- tx_lpf_bw = 3;
- } else {
- tx_lpf_bw = 1;
- }
-
- if (PHY_IPA(pi)) {
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- tx_lpf_bw = 5;
- } else {
- tx_lpf_bw = 4;
- }
- }
- write_phy_reg(pi, 0xe8,
- (tx_lpf_bw << 0) |
- (tx_lpf_bw << 3) |
- (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
-
- if (PHY_IPA(pi)) {
-
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- tx_lpf_bw = 4;
- } else {
- tx_lpf_bw = 1;
- }
-
- write_phy_reg(pi, 0xe9,
- (tx_lpf_bw << 0) |
- (tx_lpf_bw << 3) |
- (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
- }
- }
-}
-
-static void wlc_phy_spurwar_nphy(struct brcms_phy *pi)
-{
- u16 cur_channel = 0;
- int nphy_adj_tone_id_buf[] = { 57, 58 };
- u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff };
- bool isAdjustNoiseVar = false;
- uint numTonesAdjust = 0;
- u32 tempval = 0;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
-
- if (pi->nphy_gband_spurwar_en) {
-
- wlc_phy_adjust_rx_analpfbw_nphy(pi,
- NPHY_ANARXLPFBW_REDUCTIONFACT);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if ((cur_channel == 11)
- && CHSPEC_IS40(pi->radio_chanspec)) {
-
- wlc_phy_adjust_min_noisevar_nphy(pi, 2,
- nphy_adj_tone_id_buf,
- nphy_adj_noise_var_buf);
- } else {
-
- wlc_phy_adjust_min_noisevar_nphy(pi, 0,
- NULL,
- NULL);
- }
- }
- wlc_phy_adjust_crsminpwr_nphy(pi,
- NPHY_ADJUSTED_MINCRSPOWER);
- }
-
- if ((pi->nphy_gband_spurwar2_en)
- && CHSPEC_IS2G(pi->radio_chanspec)) {
-
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- switch (cur_channel) {
- case 3:
- nphy_adj_tone_id_buf[0] = 57;
- nphy_adj_tone_id_buf[1] = 58;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x25f;
- isAdjustNoiseVar = true;
- break;
- case 4:
- nphy_adj_tone_id_buf[0] = 41;
- nphy_adj_tone_id_buf[1] = 42;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x25f;
- isAdjustNoiseVar = true;
- break;
- case 5:
- nphy_adj_tone_id_buf[0] = 25;
- nphy_adj_tone_id_buf[1] = 26;
- nphy_adj_noise_var_buf[0] = 0x24f;
- nphy_adj_noise_var_buf[1] = 0x25f;
- isAdjustNoiseVar = true;
- break;
- case 6:
- nphy_adj_tone_id_buf[0] = 9;
- nphy_adj_tone_id_buf[1] = 10;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x24f;
- isAdjustNoiseVar = true;
- break;
- case 7:
- nphy_adj_tone_id_buf[0] = 121;
- nphy_adj_tone_id_buf[1] = 122;
- nphy_adj_noise_var_buf[0] = 0x18f;
- nphy_adj_noise_var_buf[1] = 0x24f;
- isAdjustNoiseVar = true;
- break;
- case 8:
- nphy_adj_tone_id_buf[0] = 105;
- nphy_adj_tone_id_buf[1] = 106;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x25f;
- isAdjustNoiseVar = true;
- break;
- case 9:
- nphy_adj_tone_id_buf[0] = 89;
- nphy_adj_tone_id_buf[1] = 90;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x24f;
- isAdjustNoiseVar = true;
- break;
- case 10:
- nphy_adj_tone_id_buf[0] = 73;
- nphy_adj_tone_id_buf[1] = 74;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x24f;
- isAdjustNoiseVar = true;
- break;
- default:
- isAdjustNoiseVar = false;
- break;
- }
- }
-
- if (isAdjustNoiseVar) {
- numTonesAdjust = sizeof(nphy_adj_tone_id_buf) /
- sizeof(nphy_adj_tone_id_buf[0]);
-
- wlc_phy_adjust_min_noisevar_nphy(pi,
- numTonesAdjust,
- nphy_adj_tone_id_buf,
- nphy_adj_noise_var_buf);
-
- tempval = 0;
-
- } else {
-
- wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
- NULL);
- }
- }
-
- if ((pi->nphy_aband_spurwar_en) &&
- (CHSPEC_IS5G(pi->radio_chanspec))) {
- switch (cur_channel) {
- case 54:
- nphy_adj_tone_id_buf[0] = 32;
- nphy_adj_noise_var_buf[0] = 0x25f;
- break;
- case 38:
- case 102:
- case 118:
- nphy_adj_tone_id_buf[0] = 0;
- nphy_adj_noise_var_buf[0] = 0x0;
- break;
- case 134:
- nphy_adj_tone_id_buf[0] = 32;
- nphy_adj_noise_var_buf[0] = 0x21f;
- break;
- case 151:
- nphy_adj_tone_id_buf[0] = 16;
- nphy_adj_noise_var_buf[0] = 0x23f;
- break;
- case 153:
- case 161:
- nphy_adj_tone_id_buf[0] = 48;
- nphy_adj_noise_var_buf[0] = 0x23f;
- break;
- default:
- nphy_adj_tone_id_buf[0] = 0;
- nphy_adj_noise_var_buf[0] = 0x0;
- break;
- }
-
- if (nphy_adj_tone_id_buf[0]
- && nphy_adj_noise_var_buf[0]) {
- wlc_phy_adjust_min_noisevar_nphy(pi, 1,
- nphy_adj_tone_id_buf,
- nphy_adj_noise_var_buf);
- } else {
- wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
- NULL);
- }
- }
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
- }
-}
-
static void
-wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chanspec,
+wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
const struct nphy_sfo_cfg *ci)
{
u16 val;
@@ -18964,14 +21330,11 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chanspec,
and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840);
}
- if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF)
wlc_phy_txpwr_fixpower_nphy(pi);
- }
-
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
wlc_phy_adjust_lnagaintbl_nphy(pi);
- }
wlc_phy_txlpfbw_nphy(pi);
@@ -18982,28 +21345,20 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chanspec,
val = CHSPEC_CHANNEL(chanspec);
if (!CHSPEC_IS40(pi->radio_chanspec)) {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if ((val == 13) || (val == 14) || (val == 153)) {
- spuravoid = 1;
- }
- } else {
-
- if (((val >= 5) && (val <= 8)) || (val == 13)
- || (val == 14)) {
+ if ((val == 13) || (val == 14) || (val == 153))
spuravoid = 1;
- }
+ } else if (((val >= 5) && (val <= 8)) || (val == 13)
+ || (val == 14)) {
+ spuravoid = 1;
}
+ } else if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (val == 54)
+ spuravoid = 1;
} else {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (val == 54) {
- spuravoid = 1;
- }
- } else {
-
- if (pi->nphy_aband_spurwar_en &&
- ((val == 38) || (val == 102)
- || (val == 118)))
- spuravoid = 1;
- }
+ if (pi->nphy_aband_spurwar_en &&
+ ((val == 38) || (val == 102)
+ || (val == 118)))
+ spuravoid = 1;
}
if (pi->phy_spuravoid == SPURAVOID_FORCEON)
@@ -19047,20 +21402,16 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chanspec,
wlc_phy_spurwar_nphy(pi);
}
-void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, chanspec_t chanspec)
+void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec)
{
int freq;
- struct chan_info_nphy_radio2057 *t0 = NULL;
- struct chan_info_nphy_radio205x *t1 = NULL;
- struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
- struct chan_info_nphy_2055 *t3 = NULL;
-
- if (NORADIO_ENAB(pi->pubpi)) {
- return;
- }
+ const struct chan_info_nphy_radio2057 *t0 = NULL;
+ const struct chan_info_nphy_radio205x *t1 = NULL;
+ const struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
+ const struct chan_info_nphy_2055 *t3 = NULL;
if (!wlc_phy_chan2freq_nphy
- (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3))
+ (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3))
return;
wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec);
@@ -19071,15 +21422,13 @@ void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, chanspec_t chanspec)
if (CHSPEC_IS40(chanspec)) {
if (CHSPEC_SB_UPPER(chanspec)) {
or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
or_phy_reg(pi, 0x310, PRIM_SEL_UP20);
- }
} else {
and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
and_phy_reg(pi, 0x310,
(~PRIM_SEL_UP20 & 0xffff));
- }
}
}
@@ -19124,358 +21473,10 @@ void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, chanspec_t chanspec)
wlc_phy_chanspec_radio2055_setup(pi, t3);
wlc_phy_chanspec_nphy_setup(pi, chanspec,
- (const struct nphy_sfo_cfg *)&(t3->
- PHY_BW1a));
- }
-
-}
-
-static void wlc_phy_savecal_nphy(struct brcms_phy *pi)
-{
- void *tbl_ptr;
- int coreNum;
- u16 *txcal_radio_regs = NULL;
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
- wlc_phy_rx_iq_coeffs_nphy(pi, 0,
- &pi->calibration_cache.
- rxcal_coeffs_2G);
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- txcal_radio_regs =
- pi->calibration_cache.txcal_radio_regs_2G;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- pi->calibration_cache.txcal_radio_regs_2G[0] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_2G[1] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_2G[2] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX1);
- pi->calibration_cache.txcal_radio_regs_2G[3] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX1);
-
- pi->calibration_cache.txcal_radio_regs_2G[4] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_2G[5] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_2G[6] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX1);
- pi->calibration_cache.txcal_radio_regs_2G[7] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX1);
- } else {
- pi->calibration_cache.txcal_radio_regs_2G[0] =
- read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
- pi->calibration_cache.txcal_radio_regs_2G[1] =
- read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
- pi->calibration_cache.txcal_radio_regs_2G[2] =
- read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
- pi->calibration_cache.txcal_radio_regs_2G[3] =
- read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
- }
-
- pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec;
- tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
- } else {
-
- wlc_phy_rx_iq_coeffs_nphy(pi, 0,
- &pi->calibration_cache.
- rxcal_coeffs_5G);
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- txcal_radio_regs =
- pi->calibration_cache.txcal_radio_regs_5G;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- pi->calibration_cache.txcal_radio_regs_5G[0] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_5G[1] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_5G[2] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX1);
- pi->calibration_cache.txcal_radio_regs_5G[3] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX1);
-
- pi->calibration_cache.txcal_radio_regs_5G[4] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_5G[5] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_5G[6] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX1);
- pi->calibration_cache.txcal_radio_regs_5G[7] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX1);
- } else {
- pi->calibration_cache.txcal_radio_regs_5G[0] =
- read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
- pi->calibration_cache.txcal_radio_regs_5G[1] =
- read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
- pi->calibration_cache.txcal_radio_regs_5G[2] =
- read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
- pi->calibration_cache.txcal_radio_regs_5G[3] =
- read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
- }
-
- pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec;
- tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
- }
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- for (coreNum = 0; coreNum <= 1; coreNum++) {
-
- txcal_radio_regs[2 * coreNum] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_FINE_I);
- txcal_radio_regs[2 * coreNum + 1] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_FINE_Q);
-
- txcal_radio_regs[2 * coreNum + 4] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_COARSE_I);
- txcal_radio_regs[2 * coreNum + 5] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_COARSE_Q);
- }
- }
-
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr);
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_restorecal_nphy(struct brcms_phy *pi)
-{
- u16 *loft_comp;
- u16 txcal_coeffs_bphy[4];
- u16 *tbl_ptr;
- int coreNum;
- u16 *txcal_radio_regs = NULL;
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (pi->nphy_iqcal_chanspec_2G == 0)
- return;
-
- tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
- loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5];
- } else {
- if (pi->nphy_iqcal_chanspec_5G == 0)
- return;
-
- tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
- loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5];
- }
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16,
- (void *)tbl_ptr);
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- txcal_coeffs_bphy[0] = tbl_ptr[0];
- txcal_coeffs_bphy[1] = tbl_ptr[1];
- txcal_coeffs_bphy[2] = tbl_ptr[2];
- txcal_coeffs_bphy[3] = tbl_ptr[3];
- } else {
- txcal_coeffs_bphy[0] = 0;
- txcal_coeffs_bphy[1] = 0;
- txcal_coeffs_bphy[2] = 0;
- txcal_coeffs_bphy[3] = 0;
- }
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16,
- txcal_coeffs_bphy);
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp);
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp);
-
- if (NREV_LT(pi->pubpi.phy_rev, 2))
- wlc_phy_tx_iq_war_nphy(pi);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- txcal_radio_regs =
- pi->calibration_cache.txcal_radio_regs_2G;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_2G[0]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_2G[1]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_2G[2]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_2G[3]);
-
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_2G[4]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_2G[5]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_2G[6]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_2G[7]);
- } else {
- write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
- pi->calibration_cache.
- txcal_radio_regs_2G[0]);
- write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
- pi->calibration_cache.
- txcal_radio_regs_2G[1]);
- write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
- pi->calibration_cache.
- txcal_radio_regs_2G[2]);
- write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
- pi->calibration_cache.
- txcal_radio_regs_2G[3]);
- }
-
- wlc_phy_rx_iq_coeffs_nphy(pi, 1,
- &pi->calibration_cache.
- rxcal_coeffs_2G);
- } else {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- txcal_radio_regs =
- pi->calibration_cache.txcal_radio_regs_5G;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_5G[0]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_5G[1]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_5G[2]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_5G[3]);
-
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_5G[4]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_5G[5]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_5G[6]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_5G[7]);
- } else {
- write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
- pi->calibration_cache.
- txcal_radio_regs_5G[0]);
- write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
- pi->calibration_cache.
- txcal_radio_regs_5G[1]);
- write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
- pi->calibration_cache.
- txcal_radio_regs_5G[2]);
- write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
- pi->calibration_cache.
- txcal_radio_regs_5G[3]);
- }
-
- wlc_phy_rx_iq_coeffs_nphy(pi, 1,
- &pi->calibration_cache.
- rxcal_coeffs_5G);
+ (const struct nphy_sfo_cfg *)
+ &(t3->PHY_BW1a));
}
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- for (coreNum = 0; coreNum <= 1; coreNum++) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_FINE_I,
- txcal_radio_regs[2 * coreNum]);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_FINE_Q,
- txcal_radio_regs[2 * coreNum + 1]);
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_COARSE_I,
- txcal_radio_regs[2 * coreNum + 4]);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_COARSE_Q,
- txcal_radio_regs[2 * coreNum + 5]);
- }
- }
}
void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init)
@@ -19545,8 +21546,8 @@ u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val)
if (D11REV_IS(pi->sh->corerev, 16)) {
suspended =
- (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ?
- false : true;
+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ?
+ false : true;
if (!suspended)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
}
@@ -19563,18 +21564,6 @@ u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val)
return new_ctl;
}
-static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals)
-{
-
- if (write == 0) {
- vals[0] = read_phy_reg(pi, 0x2c);
- vals[1] = read_phy_reg(pi, 0x42);
- } else {
- write_phy_reg(pi, 0x2c, vals[0]);
- write_phy_reg(pi, 0x42, vals[1]);
- }
-}
-
void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd)
{
u16 trigger_mask, status_mask;
@@ -19620,577 +21609,6 @@ void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd)
}
static void
-wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys,
- u8 len)
-{
- u32 t1_offset, t2_offset;
- u8 ctr;
- u8 end_event =
- NREV_GE(pi->pubpi.phy_rev,
- 3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END;
- u8 end_dly = 1;
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- t1_offset = cmd << 4;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8,
- events);
- t2_offset = t1_offset + 0x080;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8,
- dlys);
-
- for (ctr = len; ctr < 16; ctr++) {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
- t1_offset + ctr, 8, &end_event);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
- t2_offset + ctr, 8, &end_dly);
- }
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset)
-{
- u16 lpf_bw_ctl_val = 0;
- u16 rx2tx_lpf_rc_lut_offset = 0;
-
- if (offset == 0) {
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- rx2tx_lpf_rc_lut_offset = 0x159;
- } else {
- rx2tx_lpf_rc_lut_offset = 0x154;
- }
- } else {
- rx2tx_lpf_rc_lut_offset = offset;
- }
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
- (u32) rx2tx_lpf_rc_lut_offset, 16,
- &lpf_bw_ctl_val);
-
- lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7;
-
- return lpf_bw_ctl_val;
-}
-
-static void
-wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value,
- u8 core_mask, u8 off, u8 override_id)
-{
- u8 core_num;
- u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0;
- u8 val_shift = 0;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- en_mask = field;
- for (core_num = 0; core_num < 2; core_num++) {
- if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) {
-
- switch (field) {
- case (0x1 << 2):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 1);
- val_shift = 1;
- break;
- case (0x1 << 3):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 2);
- val_shift = 2;
- break;
- case (0x1 << 4):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 4);
- val_shift = 4;
- break;
- case (0x1 << 5):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 5);
- val_shift = 5;
- break;
- case (0x1 << 6):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 6);
- val_shift = 6;
- break;
- case (0x1 << 7):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 7);
- val_shift = 7;
- break;
- case (0x1 << 10):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0xf8 :
- 0xfa;
- val_mask = (0x7 << 4);
- val_shift = 4;
- break;
- case (0x1 << 11):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7b :
- 0x7e;
- val_mask = (0xffff << 0);
- val_shift = 0;
- break;
- case (0x1 << 12):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7c :
- 0x7f;
- val_mask = (0xffff << 0);
- val_shift = 0;
- break;
- case (0x3 << 13):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x348 :
- 0x349;
- val_mask = (0xff << 0);
- val_shift = 0;
- break;
- case (0x1 << 13):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x348 :
- 0x349;
- val_mask = (0xf << 0);
- val_shift = 0;
- break;
- default:
- addr = 0xffff;
- break;
- }
- } else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID1) {
-
- switch (field) {
- case (0x1 << 1):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 1);
- val_shift = 1;
- break;
- case (0x1 << 3):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 3);
- val_shift = 3;
- break;
- case (0x1 << 5):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 5);
- val_shift = 5;
- break;
- case (0x1 << 4):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 4);
- val_shift = 4;
- break;
- case (0x1 << 2):
-
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 2);
- val_shift = 2;
- break;
- case (0x1 << 7):
-
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x7 << 8);
- val_shift = 8;
- break;
- case (0x1 << 11):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 14);
- val_shift = 14;
- break;
- case (0x1 << 10):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 13);
- val_shift = 13;
- break;
- case (0x1 << 9):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 12);
- val_shift = 12;
- break;
- case (0x1 << 8):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 11);
- val_shift = 11;
- break;
- case (0x1 << 6):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 6);
- val_shift = 6;
- break;
- case (0x1 << 0):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 0);
- val_shift = 0;
- break;
- default:
- addr = 0xffff;
- break;
- }
- } else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID2) {
-
- switch (field) {
- case (0x1 << 3):
- en_addr = (core_num == 0) ? 0x346 :
- 0x347;
- val_addr = (core_num == 0) ? 0x344 :
- 0x345;
- val_mask = (0x1 << 3);
- val_shift = 3;
- break;
- case (0x1 << 1):
- en_addr = (core_num == 0) ? 0x346 :
- 0x347;
- val_addr = (core_num == 0) ? 0x344 :
- 0x345;
- val_mask = (0x1 << 1);
- val_shift = 1;
- break;
- case (0x1 << 0):
- en_addr = (core_num == 0) ? 0x346 :
- 0x347;
- val_addr = (core_num == 0) ? 0x344 :
- 0x345;
- val_mask = (0x1 << 0);
- val_shift = 0;
- break;
- case (0x1 << 2):
- en_addr = (core_num == 0) ? 0x346 :
- 0x347;
- val_addr = (core_num == 0) ? 0x344 :
- 0x345;
- val_mask = (0x1 << 2);
- val_shift = 2;
- break;
- case (0x1 << 4):
- en_addr = (core_num == 0) ? 0x346 :
- 0x347;
- val_addr = (core_num == 0) ? 0x344 :
- 0x345;
- val_mask = (0x1 << 4);
- val_shift = 4;
- break;
- default:
- addr = 0xffff;
- break;
- }
- }
-
- if (off) {
- and_phy_reg(pi, en_addr, ~en_mask);
- and_phy_reg(pi, val_addr, ~val_mask);
- } else {
-
- if ((core_mask == 0)
- || (core_mask & (1 << core_num))) {
- or_phy_reg(pi, en_addr, en_mask);
-
- if (addr != 0xffff) {
- mod_phy_reg(pi, val_addr,
- val_mask,
- (value <<
- val_shift));
- }
- }
- }
- }
- }
-}
-
-static void
-wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value,
- u8 core_mask, u8 off)
-{
- u8 core_num;
- u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask =
- 0, val_mask = 0;
- u8 shift = 0, val_shift = 0;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
- en_mask = field;
- for (core_num = 0; core_num < 2; core_num++) {
-
- switch (field) {
- case (0x1 << 1):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 0);
- val_shift = 0;
- break;
- case (0x1 << 2):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 1);
- val_shift = 1;
- break;
- case (0x1 << 3):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 2);
- val_shift = 2;
- break;
- case (0x1 << 4):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 4);
- val_shift = 4;
- break;
- case (0x1 << 5):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 5);
- val_shift = 5;
- break;
- case (0x1 << 6):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 6);
- val_shift = 6;
- break;
- case (0x1 << 7):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 7);
- val_shift = 7;
- break;
- case (0x1 << 8):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x7 << 8);
- val_shift = 8;
- break;
- case (0x1 << 11):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x7 << 13);
- val_shift = 13;
- break;
-
- case (0x1 << 9):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0xf8 : 0xfa;
- val_mask = (0x7 << 0);
- val_shift = 0;
- break;
-
- case (0x1 << 10):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0xf8 : 0xfa;
- val_mask = (0x7 << 4);
- val_shift = 4;
- break;
-
- case (0x1 << 12):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7b : 0x7e;
- val_mask = (0xffff << 0);
- val_shift = 0;
- break;
- case (0x1 << 13):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7c : 0x7f;
- val_mask = (0xffff << 0);
- val_shift = 0;
- break;
- case (0x1 << 14):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0xf9 : 0xfb;
- val_mask = (0x3 << 6);
- val_shift = 6;
- break;
- case (0x1 << 0):
- en_addr = (core_num == 0) ? 0xe5 : 0xe6;
- val_addr = (core_num == 0) ? 0xf9 : 0xfb;
- val_mask = (0x1 << 15);
- val_shift = 15;
- break;
- default:
- addr = 0xffff;
- break;
- }
-
- if (off) {
- and_phy_reg(pi, en_addr, ~en_mask);
- and_phy_reg(pi, val_addr, ~val_mask);
- } else {
-
- if ((core_mask == 0)
- || (core_mask & (1 << core_num))) {
- or_phy_reg(pi, en_addr, en_mask);
-
- if (addr != 0xffff) {
- mod_phy_reg(pi, val_addr,
- val_mask,
- (value <<
- val_shift));
- }
- }
- }
- }
- } else {
-
- if (off) {
- and_phy_reg(pi, 0xec, ~field);
- value = 0x0;
- } else {
- or_phy_reg(pi, 0xec, field);
- }
-
- for (core_num = 0; core_num < 2; core_num++) {
-
- switch (field) {
- case (0x1 << 1):
- case (0x1 << 9):
- case (0x1 << 12):
- case (0x1 << 13):
- case (0x1 << 14):
- addr = 0x78;
-
- core_mask = 0x1;
- break;
- case (0x1 << 2):
- case (0x1 << 3):
- case (0x1 << 4):
- case (0x1 << 5):
- case (0x1 << 6):
- case (0x1 << 7):
- case (0x1 << 8):
- addr = (core_num == 0) ? 0x7a : 0x7d;
- break;
- case (0x1 << 10):
- addr = (core_num == 0) ? 0x7b : 0x7e;
- break;
- case (0x1 << 11):
- addr = (core_num == 0) ? 0x7c : 0x7f;
- break;
- default:
- addr = 0xffff;
- }
-
- switch (field) {
- case (0x1 << 1):
- mask = (0x7 << 3);
- shift = 3;
- break;
- case (0x1 << 9):
- mask = (0x1 << 2);
- shift = 2;
- break;
- case (0x1 << 12):
- mask = (0x1 << 8);
- shift = 8;
- break;
- case (0x1 << 13):
- mask = (0x1 << 9);
- shift = 9;
- break;
- case (0x1 << 14):
- mask = (0xf << 12);
- shift = 12;
- break;
- case (0x1 << 2):
- mask = (0x1 << 0);
- shift = 0;
- break;
- case (0x1 << 3):
- mask = (0x1 << 1);
- shift = 1;
- break;
- case (0x1 << 4):
- mask = (0x1 << 2);
- shift = 2;
- break;
- case (0x1 << 5):
- mask = (0x3 << 4);
- shift = 4;
- break;
- case (0x1 << 6):
- mask = (0x3 << 6);
- shift = 6;
- break;
- case (0x1 << 7):
- mask = (0x1 << 8);
- shift = 8;
- break;
- case (0x1 << 8):
- mask = (0x1 << 9);
- shift = 9;
- break;
- case (0x1 << 10):
- mask = 0x1fff;
- shift = 0x0;
- break;
- case (0x1 << 11):
- mask = 0x1fff;
- shift = 0x0;
- break;
- default:
- mask = 0x0;
- shift = 0x0;
- break;
- }
-
- if ((addr != 0xffff) && (core_mask & (1 << core_num))) {
- mod_phy_reg(pi, addr, mask, (value << shift));
- }
- }
-
- or_phy_reg(pi, 0xec, (0x1 << 0));
- or_phy_reg(pi, 0x78, (0x1 << 0));
- udelay(1);
- and_phy_reg(pi, 0xec, ~(0x1 << 0));
- }
-}
-
-static void
wlc_phy_rfctrl_override_1tomany_nphy(struct brcms_phy *pi, u16 cmd, u16 value,
u8 core_mask, u8 off)
{
@@ -20201,76 +21619,93 @@ wlc_phy_rfctrl_override_1tomany_nphy(struct brcms_phy *pi, u16 cmd, u16 value,
switch (cmd) {
case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu:
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
- value, core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 5),
+ value, core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 4), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 3), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
break;
case NPHY_REV7_RfctrlOverride_cmd_rx_pu:
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
- value, core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2),
+ value, core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 1), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 0), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 1), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 11), 0,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
break;
case NPHY_REV7_RfctrlOverride_cmd_tx_pu:
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
- value, core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2),
+ value, core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 1), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 0), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 11), 1,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
break;
case NPHY_REV7_RfctrlOverride_cmd_rxgain:
rfmxgain = value & 0x000ff;
lpfgain = value & 0x0ff00;
lpfgain = lpfgain >> 8;
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
- rfmxgain, core_mask,
- off,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x3 << 13),
- lpfgain, core_mask,
- off,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 11),
+ rfmxgain, core_mask,
+ off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x3 << 13),
+ lpfgain, core_mask,
+ off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
break;
case NPHY_REV7_RfctrlOverride_cmd_txgain:
tgain = value & 0x7fff;
lpfgain = value & 0x8000;
lpfgain = lpfgain >> 14;
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
- tgain, core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 13),
- lpfgain, core_mask,
- off,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 12),
+ tgain, core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 13),
+ lpfgain, core_mask,
+ off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
break;
}
}
@@ -20283,137 +21718,164 @@ wlc_phy_scale_offset_rssi_nphy(struct brcms_phy *pi, u16 scale, s8 offset,
u16 valuetostuff;
offset = (offset > NPHY_RSSICAL_MAXREAD) ?
- NPHY_RSSICAL_MAXREAD : offset;
+ NPHY_RSSICAL_MAXREAD : offset;
offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ?
- -NPHY_RSSICAL_MAXREAD - 1 : offset;
+ -NPHY_RSSICAL_MAXREAD - 1 : offset;
valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f);
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB))
write_phy_reg(pi, 0x1a6, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB))
write_phy_reg(pi, 0x1ac, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB))
write_phy_reg(pi, 0x1b2, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB))
write_phy_reg(pi, 0x1b8, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1))
write_phy_reg(pi, 0x1a4, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1))
write_phy_reg(pi, 0x1aa, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1))
write_phy_reg(pi, 0x1b0, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1))
write_phy_reg(pi, 0x1b6, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2))
write_phy_reg(pi, 0x1a5, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2))
write_phy_reg(pi, 0x1ab, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2))
write_phy_reg(pi, 0x1b1, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2))
write_phy_reg(pi, 0x1b7, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD))
write_phy_reg(pi, 0x1a7, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD))
write_phy_reg(pi, 0x1ad, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD))
write_phy_reg(pi, 0x1b3, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD))
write_phy_reg(pi, 0x1b9, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ))
write_phy_reg(pi, 0x1a8, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ))
write_phy_reg(pi, 0x1ae, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ))
write_phy_reg(pi, 0x1b4, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ))
write_phy_reg(pi, 0x1ba, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
+ (rssi_type == NPHY_RSSI_SEL_TSSI_2G))
write_phy_reg(pi, 0x1a9, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
+ (rssi_type == NPHY_RSSI_SEL_TSSI_2G))
write_phy_reg(pi, 0x1b5, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
+ (rssi_type == NPHY_RSSI_SEL_TSSI_5G))
write_phy_reg(pi, 0x1af, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
+ (rssi_type == NPHY_RSSI_SEL_TSSI_5G))
write_phy_reg(pi, 0x1bb, valuetostuff);
+}
+
+static void brcms_phy_wr_tx_mux(struct brcms_phy *pi, u8 core)
+{
+ if (PHY_IPA(pi)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ write_radio_reg(pi,
+ ((core == PHY_CORE_0) ?
+ RADIO_2057_TX0_TX_SSI_MUX :
+ RADIO_2057_TX1_TX_SSI_MUX),
+ (CHSPEC_IS5G(pi->radio_chanspec) ?
+ 0xc : 0xe));
+ else
+ write_radio_reg(pi,
+ RADIO_2056_TX_TX_SSI_MUX |
+ ((core == PHY_CORE_0) ?
+ RADIO_2056_TX0 : RADIO_2056_TX1),
+ (CHSPEC_IS5G(pi->radio_chanspec) ?
+ 0xc : 0xe));
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ write_radio_reg(pi,
+ ((core == PHY_CORE_0) ?
+ RADIO_2057_TX0_TX_SSI_MUX :
+ RADIO_2057_TX1_TX_SSI_MUX),
+ 0x11);
+
+ if (pi->pubpi.radioid == BCM2057_ID)
+ write_radio_reg(pi,
+ RADIO_2057_IQTEST_SEL_PU, 0x1);
+
+ } else {
+ write_radio_reg(pi,
+ RADIO_2056_TX_TX_SSI_MUX |
+ ((core == PHY_CORE_0) ?
+ RADIO_2056_TX0 : RADIO_2056_TX1),
+ 0x11);
+ }
}
}
@@ -20440,7 +21902,7 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
mod_phy_reg(pi, 0xe6, (0x1 << 5), 0);
mask = (0x1 << 2) |
- (0x1 << 3) | (0x1 << 4) | (0x1 << 5);
+ (0x1 << 3) | (0x1 << 4) | (0x1 << 5);
mod_phy_reg(pi, 0xf9, mask, 0);
mod_phy_reg(pi, 0xfb, mask, 0);
@@ -20459,23 +21921,22 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
if (rssi_type == NPHY_RSSI_SEL_W1 ||
rssi_type == NPHY_RSSI_SEL_W2 ||
rssi_type == NPHY_RSSI_SEL_NB) {
-
mod_phy_reg(pi,
(core ==
PHY_CORE_0) ? 0xa6 : 0xa7,
(0x3 << 8), 0);
mask = (0x1 << 2) |
- (0x1 << 3) |
- (0x1 << 4) | (0x1 << 5);
+ (0x1 << 3) |
+ (0x1 << 4) | (0x1 << 5);
mod_phy_reg(pi,
(core ==
PHY_CORE_0) ? 0xf9 : 0xfb,
mask, 0);
if (rssi_type == NPHY_RSSI_SEL_W1) {
- if (CHSPEC_IS5G
- (pi->radio_chanspec)) {
+ if (CHSPEC_IS5G(
+ pi->radio_chanspec)) {
mask = (0x1 << 2);
val = 1 << 2;
} else {
@@ -20501,7 +21962,6 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
0xe5 : 0xe6, mask, val);
} else {
if (rssi_type == NPHY_RSSI_SEL_TBD) {
-
mask = (0x3 << 8);
val = 1 << 8;
mod_phy_reg(pi,
@@ -20516,7 +21976,6 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
: 0xa7, mask, val);
} else if (rssi_type ==
NPHY_RSSI_SEL_IQ) {
-
mask = (0x3 << 8);
val = 2 << 8;
mod_phy_reg(pi,
@@ -20530,7 +21989,6 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
PHY_CORE_0) ? 0xa6
: 0xa7, mask, val);
} else {
-
mask = (0x3 << 8);
val = 3 << 8;
mod_phy_reg(pi,
@@ -20543,86 +22001,13 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
(core ==
PHY_CORE_0) ? 0xa6
: 0xa7, mask, val);
-
- if (PHY_IPA(pi)) {
- if (NREV_GE
- (pi->pubpi.phy_rev,
- 7)) {
-
- write_radio_reg
- (pi,
- ((core ==
- PHY_CORE_0)
- ?
- RADIO_2057_TX0_TX_SSI_MUX
- :
- RADIO_2057_TX1_TX_SSI_MUX),
- (CHSPEC_IS5G
- (pi->
- radio_chanspec)
- ? 0xc :
- 0xe));
- } else {
- write_radio_reg
- (pi,
- RADIO_2056_TX_TX_SSI_MUX
- |
- ((core ==
- PHY_CORE_0)
- ?
- RADIO_2056_TX0
- :
- RADIO_2056_TX1),
- (CHSPEC_IS5G
- (pi->
- radio_chanspec)
- ? 0xc :
- 0xe));
- }
- } else {
-
- if (NREV_GE
- (pi->pubpi.phy_rev,
- 7)) {
- write_radio_reg
- (pi,
- ((core ==
- PHY_CORE_0)
- ?
- RADIO_2057_TX0_TX_SSI_MUX
- :
- RADIO_2057_TX1_TX_SSI_MUX),
- 0x11);
-
- if (pi->pubpi.
- radioid ==
- BCM2057_ID)
- write_radio_reg
- (pi,
- RADIO_2057_IQTEST_SEL_PU,
- 0x1);
-
- } else {
- write_radio_reg
- (pi,
- RADIO_2056_TX_TX_SSI_MUX
- |
- ((core ==
- PHY_CORE_0)
- ?
- RADIO_2056_TX0
- :
- RADIO_2056_TX1),
- 0x11);
- }
- }
-
+ brcms_phy_wr_tx_mux(pi, core);
afectrlovr_rssi_val = 1 << 9;
mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x8f
- : 0xa5, (0x1 << 9),
- afectrlovr_rssi_val);
+ (core ==
+ PHY_CORE_0) ? 0x8f
+ : 0xa5, (0x1 << 9),
+ afectrlovr_rssi_val);
}
}
}
@@ -20631,19 +22016,15 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
if ((rssi_type == NPHY_RSSI_SEL_W1) ||
(rssi_type == NPHY_RSSI_SEL_W2) ||
- (rssi_type == NPHY_RSSI_SEL_NB)) {
-
+ (rssi_type == NPHY_RSSI_SEL_NB))
val = 0x0;
- } else if (rssi_type == NPHY_RSSI_SEL_TBD) {
-
+ else if (rssi_type == NPHY_RSSI_SEL_TBD)
val = 0x1;
- } else if (rssi_type == NPHY_RSSI_SEL_IQ) {
-
+ else if (rssi_type == NPHY_RSSI_SEL_IQ)
val = 0x2;
- } else {
-
+ else
val = 0x3;
- }
+
mask = ((0x3 << 12) | (0x3 << 14));
val = (val << 12) | (val << 14);
mod_phy_reg(pi, 0xa6, mask, val);
@@ -20652,15 +22033,13 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
if ((rssi_type == NPHY_RSSI_SEL_W1) ||
(rssi_type == NPHY_RSSI_SEL_W2) ||
(rssi_type == NPHY_RSSI_SEL_NB)) {
- if (rssi_type == NPHY_RSSI_SEL_W1) {
+ if (rssi_type == NPHY_RSSI_SEL_W1)
val = 0x1;
- }
- if (rssi_type == NPHY_RSSI_SEL_W2) {
+ if (rssi_type == NPHY_RSSI_SEL_W2)
val = 0x2;
- }
- if (rssi_type == NPHY_RSSI_SEL_NB) {
+ if (rssi_type == NPHY_RSSI_SEL_NB)
val = 0x3;
- }
+
mask = (0x3 << 4);
val = (val << 4);
mod_phy_reg(pi, 0x7a, mask, val);
@@ -20698,16 +22077,16 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
(rssi_type == NPHY_RSSI_SEL_NB)) {
rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3));
rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) |
- (rfctrlcmd_coresel_val << 3);
+ (rfctrlcmd_coresel_val << 3);
rfctrlovr_mask = ((0x1 << 5) |
(0x1 << 12) |
(0x1 << 1) | (0x1 << 0));
rfctrlovr_val = (rfctrlovr_rssi_val <<
5) |
- (rfctrlovr_rxen_val << 12) |
- (rfctrlovr_coresel_val << 1) |
- (rfctrlovr_trigger_val << 0);
+ (rfctrlovr_rxen_val << 12) |
+ (rfctrlovr_coresel_val << 1) |
+ (rfctrlovr_trigger_val << 0);
mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val);
mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val);
@@ -20762,13 +22141,11 @@ wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf,
wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
gpiosel_orig = read_phy_reg(pi, 0xca);
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+ if (NREV_LT(pi->pubpi.phy_rev, 2))
write_phy_reg(pi, 0xca, 5);
- }
- for (ctr = 0; ctr < 4; ctr++) {
+ for (ctr = 0; ctr < 4; ctr++)
rssi_buf[ctr] = 0;
- }
for (samp = 0; samp < nsamps; samp++) {
if (NREV_LT(pi->pubpi.phy_rev, 2)) {
@@ -20785,9 +22162,8 @@ wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf,
tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2;
tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2;
- for (ctr = 0; ctr < 4; ctr++) {
+ for (ctr = 0; ctr < 4; ctr++)
rssi_buf[ctr] += tmp_buf[ctr];
- }
}
@@ -20796,9 +22172,8 @@ wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf,
rssi_out_val |= (rssi_buf[1] & 0xff) << 16;
rssi_out_val |= (rssi_buf[0] & 0xff) << 24;
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+ if (NREV_LT(pi->pubpi.phy_rev, 2))
write_phy_reg(pi, 0xca, gpiosel_orig);
- }
write_phy_reg(pi, 0xa6, afectrlCore1_save);
write_phy_reg(pi, 0xa7, afectrlCore2_save);
@@ -20848,7 +22223,7 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
u16 tempsense_Rcal;
syn_tempprocsense_save =
- read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG);
+ read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG);
afectrlCore1_save = read_phy_reg(pi, 0xa6);
afectrlCore2_save = read_phy_reg(pi, 0xa7);
@@ -20982,7 +22357,7 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
syn_tempprocsense_save =
- read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE);
+ read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE);
afectrlCore1_save = read_phy_reg(pi, 0xa6);
afectrlCore2_save = read_phy_reg(pi, 0xa7);
@@ -20997,14 +22372,13 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05);
wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01);
- } else {
+ else
write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
- }
radio_temp[0] =
- (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64;
+ (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64;
write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE,
syn_tempprocsense_save);
@@ -21019,17 +22393,17 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
} else {
pwrdet_rxtx_core1_save =
- read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
pwrdet_rxtx_core2_save =
- read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
core1_txrf_iqcal1_save =
- read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
core1_txrf_iqcal2_save =
- read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
core2_txrf_iqcal1_save =
- read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
core2_txrf_iqcal2_save =
- read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS);
afectrlCore1_save = read_phy_reg(pi, 0xa6);
@@ -21060,11 +22434,12 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
radio_temp[3] = (radio_temp[3] + radio_temp2[3]);
radio_temp[0] =
- (radio_temp[0] + radio_temp[1] + radio_temp[2] +
- radio_temp[3]);
+ (radio_temp[0] + radio_temp[1] + radio_temp[2] +
+ radio_temp[3]);
radio_temp[0] =
- (radio_temp[0] + (8 * 32)) * (950 - 350) / 63 + (350 * 8);
+ (radio_temp[0] +
+ (8 * 32)) * (950 - 350) / 63 + (350 * 8);
radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38;
@@ -21126,521 +22501,24 @@ wlc_phy_set_rssi_2055_vcm(struct brcms_phy *pi, u8 rssi_type, u8 *vcm_buf)
RADIO_2055_NBRSSI_VCM_Q_SHIFT);
}
} else {
-
- if (core == PHY_CORE_0) {
+ if (core == PHY_CORE_0)
mod_radio_reg(pi,
RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
RADIO_2055_WBRSSI_VCM_IQ_MASK,
vcm_buf[2 *
core] <<
RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
- } else {
+ else
mod_radio_reg(pi,
RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
RADIO_2055_WBRSSI_VCM_IQ_MASK,
vcm_buf[2 *
core] <<
RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
- }
}
}
}
-void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi)
-{
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- wlc_phy_rssi_cal_nphy_rev3(pi);
- } else {
- wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB);
- wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1);
- wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2);
- }
-}
-
-static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type)
-{
- s32 target_code;
- u16 classif_state;
- u16 clip_state[2];
- u16 rssi_ctrl_state[2], pd_state[2];
- u16 rfctrlintc_state[2], rfpdcorerxtx_state[2];
- u16 rfctrlintc_override_val;
- u16 clip_off[] = { 0xffff, 0xffff };
- u16 rf_pd_val, pd_mask, rssi_ctrl_mask;
- u8 vcm, min_vcm, vcm_tmp[4];
- u8 vcm_final[4] = { 0, 0, 0, 0 };
- u8 result_idx, ctr;
- s32 poll_results[4][4] = {
- {0, 0, 0, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0}
- };
- s32 poll_miniq[4][2] = {
- {0, 0},
- {0, 0},
- {0, 0},
- {0, 0}
- };
- s32 min_d, curr_d;
- s32 fine_digital_offset[4];
- s32 poll_results_min[4] = { 0, 0, 0, 0 };
- s32 min_poll;
-
- switch (rssi_type) {
- case NPHY_RSSI_SEL_NB:
- target_code = NPHY_RSSICAL_NB_TARGET;
- break;
- case NPHY_RSSI_SEL_W1:
- target_code = NPHY_RSSICAL_W1_TARGET;
- break;
- case NPHY_RSSI_SEL_W2:
- target_code = NPHY_RSSICAL_W2_TARGET;
- break;
- default:
- return;
- break;
- }
-
- classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
- wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
- wlc_phy_clip_det_nphy(pi, 0, clip_state);
- wlc_phy_clip_det_nphy(pi, 1, clip_off);
-
- rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4;
- rfctrlintc_override_val =
- CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110;
-
- rfctrlintc_state[0] = read_phy_reg(pi, 0x91);
- rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX);
- write_phy_reg(pi, 0x91, rfctrlintc_override_val);
- write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val);
-
- rfctrlintc_state[1] = read_phy_reg(pi, 0x92);
- rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX);
- write_phy_reg(pi, 0x92, rfctrlintc_override_val);
- write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val);
-
- pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD |
- RADIO_2055_WBRSSI_G2_PD;
- pd_state[0] =
- read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask;
- pd_state[1] =
- read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask;
- mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0);
- mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0);
- rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL |
- RADIO_2055_WBRSSI_G2_SEL;
- rssi_ctrl_state[0] =
- read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask;
- rssi_ctrl_state[1] =
- read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask;
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
-
- wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
- NPHY_RAIL_I, rssi_type);
- wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
- NPHY_RAIL_Q, rssi_type);
-
- for (vcm = 0; vcm < 4; vcm++) {
-
- vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm;
- if (rssi_type != NPHY_RSSI_SEL_W2) {
- wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp);
- }
-
- wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0],
- NPHY_RSSICAL_NPOLL);
-
- if ((rssi_type == NPHY_RSSI_SEL_W1)
- || (rssi_type == NPHY_RSSI_SEL_W2)) {
- for (ctr = 0; ctr < 2; ctr++) {
- poll_miniq[vcm][ctr] =
- min(poll_results[vcm][ctr * 2 + 0],
- poll_results[vcm][ctr * 2 + 1]);
- }
- }
- }
-
- for (result_idx = 0; result_idx < 4; result_idx++) {
- min_d = NPHY_RSSICAL_MAXD;
- min_vcm = 0;
- min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1;
- for (vcm = 0; vcm < 4; vcm++) {
- curr_d = ABS(((rssi_type == NPHY_RSSI_SEL_NB) ?
- poll_results[vcm][result_idx] :
- poll_miniq[vcm][result_idx / 2]) -
- (target_code * NPHY_RSSICAL_NPOLL));
- if (curr_d < min_d) {
- min_d = curr_d;
- min_vcm = vcm;
- }
- if (poll_results[vcm][result_idx] < min_poll) {
- min_poll = poll_results[vcm][result_idx];
- }
- }
- vcm_final[result_idx] = min_vcm;
- poll_results_min[result_idx] = min_poll;
- }
-
- if (rssi_type != NPHY_RSSI_SEL_W2) {
- wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final);
- }
-
- for (result_idx = 0; result_idx < 4; result_idx++) {
- fine_digital_offset[result_idx] =
- (target_code * NPHY_RSSICAL_NPOLL) -
- poll_results[vcm_final[result_idx]][result_idx];
- if (fine_digital_offset[result_idx] < 0) {
- fine_digital_offset[result_idx] =
- ABS(fine_digital_offset[result_idx]);
- fine_digital_offset[result_idx] +=
- (NPHY_RSSICAL_NPOLL / 2);
- fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
- fine_digital_offset[result_idx] =
- -fine_digital_offset[result_idx];
- } else {
- fine_digital_offset[result_idx] +=
- (NPHY_RSSICAL_NPOLL / 2);
- fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
- }
-
- if (poll_results_min[result_idx] ==
- NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
- fine_digital_offset[result_idx] =
- (target_code - NPHY_RSSICAL_MAXREAD - 1);
- }
-
- wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
- (s8)
- fine_digital_offset[result_idx],
- (result_idx / 2 ==
- 0) ? RADIO_MIMO_CORESEL_CORE1 :
- RADIO_MIMO_CORESEL_CORE2,
- (result_idx % 2 ==
- 0) ? NPHY_RAIL_I : NPHY_RAIL_Q,
- rssi_type);
- }
-
- mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]);
- mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]);
- if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
- NPHY_RSSI_SEL_NB);
- } else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
- NPHY_RSSI_SEL_W1);
- } else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
- NPHY_RSSI_SEL_W2);
- } else {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
- NPHY_RSSI_SEL_W2);
- }
- if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
- NPHY_RSSI_SEL_NB);
- } else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
- NPHY_RSSI_SEL_W1);
- } else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
- NPHY_RSSI_SEL_W2);
- } else {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
- NPHY_RSSI_SEL_W2);
- }
-
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type);
-
- write_phy_reg(pi, 0x91, rfctrlintc_state[0]);
- write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]);
- write_phy_reg(pi, 0x92, rfctrlintc_state[1]);
- write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]);
-
- wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
- wlc_phy_clip_det_nphy(pi, 1, clip_state);
-
- wlc_phy_resetcca_nphy(pi);
-}
-
-int
-wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct brcms_d11rxhdr *wlc_rxh)
-{
- struct d11rxhdr *rxh = &wlc_rxh->rxhdr;
- s16 rxpwr, rxpwr0, rxpwr1;
- s16 phyRx0_l, phyRx2_l;
-
- rxpwr = 0;
- rxpwr0 = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR0_MASK;
- rxpwr1 = (le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR1_MASK) >> 8;
-
- if (rxpwr0 > 127)
- rxpwr0 -= 256;
- if (rxpwr1 > 127)
- rxpwr1 -= 256;
-
- phyRx0_l = le16_to_cpu(rxh->PhyRxStatus_0) & 0x00ff;
- phyRx2_l = le16_to_cpu(rxh->PhyRxStatus_2) & 0x00ff;
- if (phyRx2_l > 127)
- phyRx2_l -= 256;
-
- if (((rxpwr0 == 16) || (rxpwr0 == 32))) {
- rxpwr0 = rxpwr1;
- rxpwr1 = phyRx2_l;
- }
-
- wlc_rxh->rxpwr[0] = (s8) rxpwr0;
- wlc_rxh->rxpwr[1] = (s8) rxpwr1;
- wlc_rxh->do_rssi_ma = 0;
-
- if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX)
- rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1;
- else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN)
- rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1;
- else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG)
- rxpwr = (rxpwr0 + rxpwr1) >> 1;
-
- return rxpwr;
-}
-
-static void
-wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value,
- u8 core_code)
-{
- u16 mask;
- u16 val;
- u8 core;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- if (core_code == RADIO_MIMO_CORESEL_CORE1
- && core == PHY_CORE_1)
- continue;
- else if (core_code == RADIO_MIMO_CORESEL_CORE2
- && core == PHY_CORE_0)
- continue;
-
- if (NREV_LT(pi->pubpi.phy_rev, 7)) {
-
- mask = (0x1 << 10);
- val = 1 << 10;
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
- 0x92, mask, val);
- }
-
- if (field == NPHY_RfctrlIntc_override_OFF) {
-
- write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
- 0x92, 0);
-
- wlc_phy_force_rfseq_nphy(pi,
- NPHY_RFSEQ_RESET2RX);
- } else if (field == NPHY_RfctrlIntc_override_TRSW) {
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- mask = (0x1 << 6) | (0x1 << 7);
-
- val = value << 6;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
-
- or_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- (0x1 << 10));
-
- and_phy_reg(pi, 0x2ff, (u16)
- ~(0x3 << 14));
- or_phy_reg(pi, 0x2ff, (0x1 << 13));
- or_phy_reg(pi, 0x2ff, (0x1 << 0));
- } else {
-
- mask = (0x1 << 6) |
- (0x1 << 7) |
- (0x1 << 8) | (0x1 << 9);
- val = value << 6;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
-
- mask = (0x1 << 0);
- val = 1 << 0;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0xe7 : 0xec,
- mask, val);
-
- mask = (core == PHY_CORE_0) ? (0x1 << 0)
- : (0x1 << 1);
- val = 1 << ((core == PHY_CORE_0) ?
- 0 : 1);
- mod_phy_reg(pi, 0x78, mask, val);
-
- SPINWAIT(((read_phy_reg(pi, 0x78) & val)
- != 0), 10000);
- if (WARN(read_phy_reg(pi, 0x78) & val,
- "HW error: override failed"))
- return;
-
- mask = (0x1 << 0);
- val = 0 << 0;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0xe7 : 0xec,
- mask, val);
- }
- } else if (field == NPHY_RfctrlIntc_override_PA) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- mask = (0x1 << 4) | (0x1 << 5);
-
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- val = value << 5;
- } else {
- val = value << 4;
- }
-
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
-
- or_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- (0x1 << 12));
- } else {
-
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- mask = (0x1 << 5);
- val = value << 5;
- } else {
- mask = (0x1 << 4);
- val = value << 4;
- }
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
- }
- } else if (field == NPHY_RfctrlIntc_override_EXT_LNA_PU) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
- mask = (0x1 << 0);
- val = value << 0;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, val);
-
- mask = (0x1 << 2);
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, 0);
- } else {
-
- mask = (0x1 << 2);
- val = value << 2;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, val);
-
- mask = (0x1 << 0);
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, 0);
- }
-
- mask = (0x1 << 11);
- val = 1 << 11;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
- } else {
-
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- mask = (0x1 << 0);
- val = value << 0;
- } else {
- mask = (0x1 << 2);
- val = value << 2;
- }
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
- }
- } else if (field ==
- NPHY_RfctrlIntc_override_EXT_LNA_GAIN) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
- mask = (0x1 << 1);
- val = value << 1;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, val);
-
- mask = (0x1 << 3);
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, 0);
- } else {
-
- mask = (0x1 << 3);
- val = value << 3;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, val);
-
- mask = (0x1 << 1);
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, 0);
- }
-
- mask = (0x1 << 11);
- val = 1 << 11;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
- } else {
-
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- mask = (0x1 << 1);
- val = value << 1;
- } else {
- mask = (0x1 << 3);
- val = value << 3;
- }
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
- }
- }
- }
- } else {
- return;
- }
-}
-
static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
{
u16 classif_state;
@@ -21683,10 +22561,14 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save;
u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save;
- NPHY_REV7_RfctrlOverride3_save = NPHY_REV7_RfctrlOverride4_save =
- NPHY_REV7_RfctrlOverride5_save = NPHY_REV7_RfctrlOverride6_save =
- NPHY_REV7_RfctrlMiscReg3_save = NPHY_REV7_RfctrlMiscReg4_save =
- NPHY_REV7_RfctrlMiscReg5_save = NPHY_REV7_RfctrlMiscReg6_save = 0;
+ NPHY_REV7_RfctrlOverride3_save =
+ NPHY_REV7_RfctrlOverride4_save =
+ NPHY_REV7_RfctrlOverride5_save =
+ NPHY_REV7_RfctrlOverride6_save =
+ NPHY_REV7_RfctrlMiscReg3_save =
+ NPHY_REV7_RfctrlMiscReg4_save =
+ NPHY_REV7_RfctrlMiscReg5_save =
+ NPHY_REV7_RfctrlMiscReg6_save = 0;
classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
@@ -21726,21 +22608,21 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1,
RADIO_MIMO_CORESEL_ALLRXTX);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_rxrf_pu,
- 0, 0, 0);
- } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_rxrf_pu,
+ 0, 0, 0);
+ else
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0);
- }
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_rx_pu,
- 1, 0, 0);
- } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_rx_pu,
+ 1, 0, 0);
+ else
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0);
- }
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
@@ -21755,12 +22637,14 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
if (CHSPEC_IS5G(pi->radio_chanspec)) {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
- 0, 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 1, 0,
- 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 5),
+ 0, 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 4), 1, 0,
+ 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
} else {
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0);
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0);
@@ -21768,12 +22652,14 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
} else {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
- 0, 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 1, 0,
- 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 4),
+ 0, 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 5), 1, 0,
+ 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
} else {
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0);
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0);
@@ -21781,7 +22667,7 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
}
rxcore_state = wlc_phy_rxcore_getstate_nphy(
- (struct brcms_phy_pub *) pi);
+ (struct brcms_phy_pub *) pi);
vcm_level_max = 8;
@@ -21804,21 +22690,18 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
NPHY_RAIL_Q, NPHY_RSSI_SEL_NB);
for (vcm = 0; vcm < vcm_level_max; vcm++) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
mod_radio_reg(pi, (core == PHY_CORE_0) ?
RADIO_2057_NB_MASTER_CORE0 :
RADIO_2057_NB_MASTER_CORE1,
RADIO_2057_VCM_MASK, vcm);
- } else {
-
+ else
mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
((core ==
PHY_CORE_0) ? RADIO_2056_RX0 :
RADIO_2056_RX1),
RADIO_2056_VCM_MASK,
vcm << RADIO_2056_RSSI_VCM_SHIFT);
- }
wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB,
&poll_results[vcm][0],
@@ -21826,92 +22709,90 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
}
for (result_idx = 0; result_idx < 4; result_idx++) {
- if ((core == result_idx / 2) && (result_idx % 2 == 0)) {
+ if ((core == result_idx / 2) &&
+ (result_idx % 2 == 0)) {
min_d = NPHY_RSSICAL_MAXD;
min_vcm = 0;
min_poll =
- NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL +
- 1;
+ NPHY_RSSICAL_MAXREAD *
+ NPHY_RSSICAL_NPOLL + 1;
for (vcm = 0; vcm < vcm_level_max; vcm++) {
- curr_d = poll_results[vcm][result_idx] *
- poll_results[vcm][result_idx] +
- poll_results[vcm][result_idx + 1] *
- poll_results[vcm][result_idx + 1];
+ curr_d =
+ poll_results[vcm][result_idx] *
+ poll_results[vcm][result_idx] +
+ poll_results[vcm][result_idx +
+ 1] *
+ poll_results[vcm][result_idx +
+ 1];
if (curr_d < min_d) {
min_d = curr_d;
min_vcm = vcm;
}
if (poll_results[vcm][result_idx] <
- min_poll) {
+ min_poll)
min_poll =
- poll_results[vcm]
- [result_idx];
- }
+ poll_results[vcm]
+ [result_idx];
}
vcm_final = min_vcm;
poll_results_min[result_idx] = min_poll;
}
}
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
mod_radio_reg(pi, (core == PHY_CORE_0) ?
RADIO_2057_NB_MASTER_CORE0 :
RADIO_2057_NB_MASTER_CORE1,
RADIO_2057_VCM_MASK, vcm_final);
- } else {
+ else
mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
((core ==
PHY_CORE_0) ? RADIO_2056_RX0 :
RADIO_2056_RX1), RADIO_2056_VCM_MASK,
vcm_final << RADIO_2056_RSSI_VCM_SHIFT);
- }
for (result_idx = 0; result_idx < 4; result_idx++) {
if (core == result_idx / 2) {
fine_digital_offset[result_idx] =
- (NPHY_RSSICAL_NB_TARGET *
- NPHY_RSSICAL_NPOLL) -
- poll_results[vcm_final][result_idx];
+ (NPHY_RSSICAL_NB_TARGET *
+ NPHY_RSSICAL_NPOLL) -
+ poll_results[vcm_final][result_idx];
if (fine_digital_offset[result_idx] < 0) {
fine_digital_offset[result_idx] =
- ABS(fine_digital_offset
- [result_idx]);
+ abs(fine_digital_offset
+ [result_idx]);
fine_digital_offset[result_idx] +=
- (NPHY_RSSICAL_NPOLL / 2);
+ (NPHY_RSSICAL_NPOLL / 2);
fine_digital_offset[result_idx] /=
- NPHY_RSSICAL_NPOLL;
+ NPHY_RSSICAL_NPOLL;
fine_digital_offset[result_idx] =
- -fine_digital_offset[result_idx];
+ -fine_digital_offset[
+ result_idx];
} else {
fine_digital_offset[result_idx] +=
- (NPHY_RSSICAL_NPOLL / 2);
+ (NPHY_RSSICAL_NPOLL / 2);
fine_digital_offset[result_idx] /=
- NPHY_RSSICAL_NPOLL;
+ NPHY_RSSICAL_NPOLL;
}
if (poll_results_min[result_idx] ==
- NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
+ NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL)
fine_digital_offset[result_idx] =
- (NPHY_RSSICAL_NB_TARGET -
- NPHY_RSSICAL_MAXREAD - 1);
- }
-
- wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
- (s8)
- fine_digital_offset
- [result_idx],
- (result_idx /
- 2 ==
- 0) ?
- RADIO_MIMO_CORESEL_CORE1
- :
- RADIO_MIMO_CORESEL_CORE2,
- (result_idx %
- 2 ==
- 0) ? NPHY_RAIL_I
- : NPHY_RAIL_Q,
- NPHY_RSSI_SEL_NB);
+ (NPHY_RSSICAL_NB_TARGET -
+ NPHY_RSSICAL_MAXREAD - 1);
+
+ wlc_phy_scale_offset_rssi_nphy(
+ pi, 0x0,
+ (s8)
+ fine_digital_offset
+ [result_idx],
+ (result_idx / 2 == 0) ?
+ RADIO_MIMO_CORESEL_CORE1 :
+ RADIO_MIMO_CORESEL_CORE2,
+ (result_idx % 2 == 0) ?
+ NPHY_RAIL_I : NPHY_RAIL_Q,
+ NPHY_RSSI_SEL_NB);
}
}
@@ -21952,46 +22833,44 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
for (result_idx = 0; result_idx < 4; result_idx++) {
if (core == result_idx / 2) {
fine_digital_offset[result_idx] =
- (target_code * NPHY_RSSICAL_NPOLL) -
- poll_result_core[result_idx];
- if (fine_digital_offset[result_idx] < 0) {
+ (target_code *
+ NPHY_RSSICAL_NPOLL) -
+ poll_result_core[result_idx];
+ if (fine_digital_offset[result_idx] <
+ 0) {
fine_digital_offset[result_idx]
- =
- ABS(fine_digital_offset
- [result_idx]);
+ = abs(
+ fine_digital_offset
+ [result_idx]);
fine_digital_offset[result_idx]
- += (NPHY_RSSICAL_NPOLL / 2);
+ += (NPHY_RSSICAL_NPOLL
+ / 2);
fine_digital_offset[result_idx]
- /= NPHY_RSSICAL_NPOLL;
+ /= NPHY_RSSICAL_NPOLL;
fine_digital_offset[result_idx]
- =
- -fine_digital_offset
- [result_idx];
+ = -fine_digital_offset
+ [result_idx];
} else {
fine_digital_offset[result_idx]
- += (NPHY_RSSICAL_NPOLL / 2);
+ += (NPHY_RSSICAL_NPOLL
+ / 2);
fine_digital_offset[result_idx]
- /= NPHY_RSSICAL_NPOLL;
+ /= NPHY_RSSICAL_NPOLL;
}
- wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
- (s8)
- fine_digital_offset
- [core *
- 2],
- (core ==
- PHY_CORE_0)
- ?
- RADIO_MIMO_CORESEL_CORE1
- :
- RADIO_MIMO_CORESEL_CORE2,
- (result_idx
- % 2 ==
- 0) ?
- NPHY_RAIL_I
- :
- NPHY_RAIL_Q,
- rssi_type);
+ wlc_phy_scale_offset_rssi_nphy(
+ pi, 0x0,
+ (s8)
+ fine_digital_offset
+ [core *
+ 2],
+ (core == PHY_CORE_0) ?
+ RADIO_MIMO_CORESEL_CORE1 :
+ RADIO_MIMO_CORESEL_CORE2,
+ (result_idx % 2 == 0) ?
+ NPHY_RAIL_I :
+ NPHY_RAIL_Q,
+ rssi_type);
}
}
@@ -22040,87 +22919,87 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
pi->rssical_cache.rssical_radio_regs_2G[0] =
- read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
pi->rssical_cache.rssical_radio_regs_2G[1] =
- read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
} else {
pi->rssical_cache.rssical_radio_regs_2G[0] =
- read_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC |
- RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC |
+ RADIO_2056_RX0);
pi->rssical_cache.rssical_radio_regs_2G[1] =
- read_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC |
- RADIO_2056_RX1);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC |
+ RADIO_2056_RX1);
}
pi->rssical_cache.rssical_phyregs_2G[0] =
- read_phy_reg(pi, 0x1a6);
+ read_phy_reg(pi, 0x1a6);
pi->rssical_cache.rssical_phyregs_2G[1] =
- read_phy_reg(pi, 0x1ac);
+ read_phy_reg(pi, 0x1ac);
pi->rssical_cache.rssical_phyregs_2G[2] =
- read_phy_reg(pi, 0x1b2);
+ read_phy_reg(pi, 0x1b2);
pi->rssical_cache.rssical_phyregs_2G[3] =
- read_phy_reg(pi, 0x1b8);
+ read_phy_reg(pi, 0x1b8);
pi->rssical_cache.rssical_phyregs_2G[4] =
- read_phy_reg(pi, 0x1a4);
+ read_phy_reg(pi, 0x1a4);
pi->rssical_cache.rssical_phyregs_2G[5] =
- read_phy_reg(pi, 0x1aa);
+ read_phy_reg(pi, 0x1aa);
pi->rssical_cache.rssical_phyregs_2G[6] =
- read_phy_reg(pi, 0x1b0);
+ read_phy_reg(pi, 0x1b0);
pi->rssical_cache.rssical_phyregs_2G[7] =
- read_phy_reg(pi, 0x1b6);
+ read_phy_reg(pi, 0x1b6);
pi->rssical_cache.rssical_phyregs_2G[8] =
- read_phy_reg(pi, 0x1a5);
+ read_phy_reg(pi, 0x1a5);
pi->rssical_cache.rssical_phyregs_2G[9] =
- read_phy_reg(pi, 0x1ab);
+ read_phy_reg(pi, 0x1ab);
pi->rssical_cache.rssical_phyregs_2G[10] =
- read_phy_reg(pi, 0x1b1);
+ read_phy_reg(pi, 0x1b1);
pi->rssical_cache.rssical_phyregs_2G[11] =
- read_phy_reg(pi, 0x1b7);
+ read_phy_reg(pi, 0x1b7);
pi->nphy_rssical_chanspec_2G = pi->radio_chanspec;
} else {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
pi->rssical_cache.rssical_radio_regs_5G[0] =
- read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
pi->rssical_cache.rssical_radio_regs_5G[1] =
- read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
} else {
pi->rssical_cache.rssical_radio_regs_5G[0] =
- read_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC |
- RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC |
+ RADIO_2056_RX0);
pi->rssical_cache.rssical_radio_regs_5G[1] =
- read_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC |
- RADIO_2056_RX1);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC |
+ RADIO_2056_RX1);
}
pi->rssical_cache.rssical_phyregs_5G[0] =
- read_phy_reg(pi, 0x1a6);
+ read_phy_reg(pi, 0x1a6);
pi->rssical_cache.rssical_phyregs_5G[1] =
- read_phy_reg(pi, 0x1ac);
+ read_phy_reg(pi, 0x1ac);
pi->rssical_cache.rssical_phyregs_5G[2] =
- read_phy_reg(pi, 0x1b2);
+ read_phy_reg(pi, 0x1b2);
pi->rssical_cache.rssical_phyregs_5G[3] =
- read_phy_reg(pi, 0x1b8);
+ read_phy_reg(pi, 0x1b8);
pi->rssical_cache.rssical_phyregs_5G[4] =
- read_phy_reg(pi, 0x1a4);
+ read_phy_reg(pi, 0x1a4);
pi->rssical_cache.rssical_phyregs_5G[5] =
- read_phy_reg(pi, 0x1aa);
+ read_phy_reg(pi, 0x1aa);
pi->rssical_cache.rssical_phyregs_5G[6] =
- read_phy_reg(pi, 0x1b0);
+ read_phy_reg(pi, 0x1b0);
pi->rssical_cache.rssical_phyregs_5G[7] =
- read_phy_reg(pi, 0x1b6);
+ read_phy_reg(pi, 0x1b6);
pi->rssical_cache.rssical_phyregs_5G[8] =
- read_phy_reg(pi, 0x1a5);
+ read_phy_reg(pi, 0x1a5);
pi->rssical_cache.rssical_phyregs_5G[9] =
- read_phy_reg(pi, 0x1ab);
+ read_phy_reg(pi, 0x1ab);
pi->rssical_cache.rssical_phyregs_5G[10] =
- read_phy_reg(pi, 0x1b1);
+ read_phy_reg(pi, 0x1b1);
pi->rssical_cache.rssical_phyregs_5G[11] =
- read_phy_reg(pi, 0x1b7);
+ read_phy_reg(pi, 0x1b7);
pi->nphy_rssical_chanspec_5G = pi->radio_chanspec;
}
@@ -22129,121 +23008,287 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
wlc_phy_clip_det_nphy(pi, 1, clip_state);
}
-static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi)
+static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type)
{
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (pi->nphy_rssical_chanspec_2G == 0)
- return;
+ s32 target_code;
+ u16 classif_state;
+ u16 clip_state[2];
+ u16 rssi_ctrl_state[2], pd_state[2];
+ u16 rfctrlintc_state[2], rfpdcorerxtx_state[2];
+ u16 rfctrlintc_override_val;
+ u16 clip_off[] = { 0xffff, 0xffff };
+ u16 rf_pd_val, pd_mask, rssi_ctrl_mask;
+ u8 vcm, min_vcm, vcm_tmp[4];
+ u8 vcm_final[4] = { 0, 0, 0, 0 };
+ u8 result_idx, ctr;
+ s32 poll_results[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+ };
+ s32 poll_miniq[4][2] = {
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}
+ };
+ s32 min_d, curr_d;
+ s32 fine_digital_offset[4];
+ s32 poll_results_min[4] = { 0, 0, 0, 0 };
+ s32 min_poll;
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
- RADIO_2057_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_2G[0]);
- mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
- RADIO_2057_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_2G[1]);
- } else {
- mod_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
- RADIO_2056_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_2G[0]);
- mod_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
- RADIO_2056_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_2G[1]);
+ switch (rssi_type) {
+ case NPHY_RSSI_SEL_NB:
+ target_code = NPHY_RSSICAL_NB_TARGET;
+ break;
+ case NPHY_RSSI_SEL_W1:
+ target_code = NPHY_RSSICAL_W1_TARGET;
+ break;
+ case NPHY_RSSI_SEL_W2:
+ target_code = NPHY_RSSICAL_W2_TARGET;
+ break;
+ default:
+ return;
+ break;
+ }
+
+ classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+ wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+ wlc_phy_clip_det_nphy(pi, 0, clip_state);
+ wlc_phy_clip_det_nphy(pi, 1, clip_off);
+
+ rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4;
+ rfctrlintc_override_val =
+ CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110;
+
+ rfctrlintc_state[0] = read_phy_reg(pi, 0x91);
+ rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX);
+ write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+ write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val);
+
+ rfctrlintc_state[1] = read_phy_reg(pi, 0x92);
+ rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX);
+ write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+ write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val);
+
+ pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD |
+ RADIO_2055_WBRSSI_G2_PD;
+ pd_state[0] =
+ read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask;
+ pd_state[1] =
+ read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask;
+ mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0);
+ mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0);
+ rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL |
+ RADIO_2055_WBRSSI_G2_SEL;
+ rssi_ctrl_state[0] =
+ read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask;
+ rssi_ctrl_state[1] =
+ read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask;
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
+
+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+ NPHY_RAIL_I, rssi_type);
+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+ NPHY_RAIL_Q, rssi_type);
+
+ for (vcm = 0; vcm < 4; vcm++) {
+
+ vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm;
+ if (rssi_type != NPHY_RSSI_SEL_W2)
+ wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp);
+
+ wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0],
+ NPHY_RSSICAL_NPOLL);
+
+ if ((rssi_type == NPHY_RSSI_SEL_W1)
+ || (rssi_type == NPHY_RSSI_SEL_W2)) {
+ for (ctr = 0; ctr < 2; ctr++)
+ poll_miniq[vcm][ctr] =
+ min(poll_results[vcm][ctr * 2 + 0],
+ poll_results[vcm][ctr * 2 + 1]);
}
+ }
- write_phy_reg(pi, 0x1a6,
- pi->rssical_cache.rssical_phyregs_2G[0]);
- write_phy_reg(pi, 0x1ac,
- pi->rssical_cache.rssical_phyregs_2G[1]);
- write_phy_reg(pi, 0x1b2,
- pi->rssical_cache.rssical_phyregs_2G[2]);
- write_phy_reg(pi, 0x1b8,
- pi->rssical_cache.rssical_phyregs_2G[3]);
- write_phy_reg(pi, 0x1a4,
- pi->rssical_cache.rssical_phyregs_2G[4]);
- write_phy_reg(pi, 0x1aa,
- pi->rssical_cache.rssical_phyregs_2G[5]);
- write_phy_reg(pi, 0x1b0,
- pi->rssical_cache.rssical_phyregs_2G[6]);
- write_phy_reg(pi, 0x1b6,
- pi->rssical_cache.rssical_phyregs_2G[7]);
- write_phy_reg(pi, 0x1a5,
- pi->rssical_cache.rssical_phyregs_2G[8]);
- write_phy_reg(pi, 0x1ab,
- pi->rssical_cache.rssical_phyregs_2G[9]);
- write_phy_reg(pi, 0x1b1,
- pi->rssical_cache.rssical_phyregs_2G[10]);
- write_phy_reg(pi, 0x1b7,
- pi->rssical_cache.rssical_phyregs_2G[11]);
+ for (result_idx = 0; result_idx < 4; result_idx++) {
+ min_d = NPHY_RSSICAL_MAXD;
+ min_vcm = 0;
+ min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1;
+ for (vcm = 0; vcm < 4; vcm++) {
+ curr_d = abs(((rssi_type == NPHY_RSSI_SEL_NB) ?
+ poll_results[vcm][result_idx] :
+ poll_miniq[vcm][result_idx / 2]) -
+ (target_code * NPHY_RSSICAL_NPOLL));
+ if (curr_d < min_d) {
+ min_d = curr_d;
+ min_vcm = vcm;
+ }
+ if (poll_results[vcm][result_idx] < min_poll)
+ min_poll = poll_results[vcm][result_idx];
+ }
+ vcm_final[result_idx] = min_vcm;
+ poll_results_min[result_idx] = min_poll;
+ }
- } else {
- if (pi->nphy_rssical_chanspec_5G == 0)
- return;
+ if (rssi_type != NPHY_RSSI_SEL_W2)
+ wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
- RADIO_2057_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_5G[0]);
- mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
- RADIO_2057_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_5G[1]);
+ for (result_idx = 0; result_idx < 4; result_idx++) {
+ fine_digital_offset[result_idx] =
+ (target_code * NPHY_RSSICAL_NPOLL) -
+ poll_results[vcm_final[result_idx]][result_idx];
+ if (fine_digital_offset[result_idx] < 0) {
+ fine_digital_offset[result_idx] =
+ abs(fine_digital_offset[result_idx]);
+ fine_digital_offset[result_idx] +=
+ (NPHY_RSSICAL_NPOLL / 2);
+ fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
+ fine_digital_offset[result_idx] =
+ -fine_digital_offset[result_idx];
} else {
- mod_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
- RADIO_2056_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_5G[0]);
- mod_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
- RADIO_2056_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_5G[1]);
+ fine_digital_offset[result_idx] +=
+ (NPHY_RSSICAL_NPOLL / 2);
+ fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
}
- write_phy_reg(pi, 0x1a6,
- pi->rssical_cache.rssical_phyregs_5G[0]);
- write_phy_reg(pi, 0x1ac,
- pi->rssical_cache.rssical_phyregs_5G[1]);
- write_phy_reg(pi, 0x1b2,
- pi->rssical_cache.rssical_phyregs_5G[2]);
- write_phy_reg(pi, 0x1b8,
- pi->rssical_cache.rssical_phyregs_5G[3]);
- write_phy_reg(pi, 0x1a4,
- pi->rssical_cache.rssical_phyregs_5G[4]);
- write_phy_reg(pi, 0x1aa,
- pi->rssical_cache.rssical_phyregs_5G[5]);
- write_phy_reg(pi, 0x1b0,
- pi->rssical_cache.rssical_phyregs_5G[6]);
- write_phy_reg(pi, 0x1b6,
- pi->rssical_cache.rssical_phyregs_5G[7]);
- write_phy_reg(pi, 0x1a5,
- pi->rssical_cache.rssical_phyregs_5G[8]);
- write_phy_reg(pi, 0x1ab,
- pi->rssical_cache.rssical_phyregs_5G[9]);
- write_phy_reg(pi, 0x1b1,
- pi->rssical_cache.rssical_phyregs_5G[10]);
- write_phy_reg(pi, 0x1b7,
- pi->rssical_cache.rssical_phyregs_5G[11]);
+ if (poll_results_min[result_idx] ==
+ NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL)
+ fine_digital_offset[result_idx] =
+ (target_code - NPHY_RSSICAL_MAXREAD - 1);
+
+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+ (s8)
+ fine_digital_offset[result_idx],
+ (result_idx / 2 ==
+ 0) ? RADIO_MIMO_CORESEL_CORE1 :
+ RADIO_MIMO_CORESEL_CORE2,
+ (result_idx % 2 ==
+ 0) ? NPHY_RAIL_I : NPHY_RAIL_Q,
+ rssi_type);
+ }
+
+ mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]);
+ mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]);
+ if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+ NPHY_RSSI_SEL_NB);
+ else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+ NPHY_RSSI_SEL_W1);
+ else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+ NPHY_RSSI_SEL_W2);
+ else
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+ NPHY_RSSI_SEL_W2);
+ if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+ NPHY_RSSI_SEL_NB);
+ else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+ NPHY_RSSI_SEL_W1);
+ else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+ NPHY_RSSI_SEL_W2);
+ else
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+ NPHY_RSSI_SEL_W2);
+
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type);
+
+ write_phy_reg(pi, 0x91, rfctrlintc_state[0]);
+ write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]);
+ write_phy_reg(pi, 0x92, rfctrlintc_state[1]);
+ write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]);
+
+ wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+ wlc_phy_clip_det_nphy(pi, 1, clip_state);
+
+ wlc_phy_resetcca_nphy(pi);
+}
+
+void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi)
+{
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ wlc_phy_rssi_cal_nphy_rev3(pi);
+ } else {
+ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB);
+ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1);
+ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2);
}
}
+int
+wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct d11rxhdr *rxh)
+{
+ s16 rxpwr, rxpwr0, rxpwr1;
+ s16 phyRx0_l, phyRx2_l;
+
+ rxpwr = 0;
+ rxpwr0 = rxh->PhyRxStatus_1 & PRXS1_nphy_PWR0_MASK;
+ rxpwr1 = (rxh->PhyRxStatus_1 & PRXS1_nphy_PWR1_MASK) >> 8;
+
+ if (rxpwr0 > 127)
+ rxpwr0 -= 256;
+ if (rxpwr1 > 127)
+ rxpwr1 -= 256;
+
+ phyRx0_l = rxh->PhyRxStatus_0 & 0x00ff;
+ phyRx2_l = rxh->PhyRxStatus_2 & 0x00ff;
+ if (phyRx2_l > 127)
+ phyRx2_l -= 256;
+
+ if (((rxpwr0 == 16) || (rxpwr0 == 32))) {
+ rxpwr0 = rxpwr1;
+ rxpwr1 = phyRx2_l;
+ }
+
+ if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX)
+ rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1;
+ else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN)
+ rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1;
+ else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG)
+ rxpwr = (rxpwr0 + rxpwr1) >> 1;
+
+ return rxpwr;
+}
+
+static void
+wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, struct cordic_iq *tone_buf,
+ u16 num_samps)
+{
+ u16 t;
+ u32 *data_buf = NULL;
+
+ data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC);
+ if (data_buf == NULL)
+ return;
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+ for (t = 0; t < num_samps; t++)
+ data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) |
+ (((unsigned int)tone_buf[t].q) & 0x3ff);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32,
+ data_buf);
+
+ kfree(data_buf);
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
static u16
wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
u8 dac_test_mode)
{
u8 phy_bw, is_phybw40;
u16 num_samps, t, spur;
- fixed theta = 0, rot = 0;
+ s32 theta = 0, rot = 0;
u32 tbl_len;
- cs32 *tone_buf = NULL;
+ struct cordic_iq *tone_buf = NULL;
is_phybw40 = CHSPEC_IS40(pi->radio_chanspec);
phy_bw = (is_phybw40 == 1) ? 40 : 20;
@@ -22258,18 +23303,17 @@ wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
tbl_len = (phy_bw << 1);
}
- tone_buf = kmalloc(sizeof(cs32) * tbl_len, GFP_ATOMIC);
- if (tone_buf == NULL) {
+ tone_buf = kmalloc(sizeof(struct cordic_iq) * tbl_len, GFP_ATOMIC);
+ if (tone_buf == NULL)
return 0;
- }
num_samps = (u16) tbl_len;
- rot = FIXED((f_kHz * 36) / phy_bw) / 100;
+ rot = ((f_kHz * 36) / phy_bw) / 100;
theta = 0;
for (t = 0; t < num_samps; t++) {
- wlc_phy_cordic(theta, &tone_buf[t]);
+ tone_buf[t] = cordic_calc_iq(theta);
theta += rot;
@@ -22284,54 +23328,6 @@ wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
return num_samps;
}
-int
-wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
- u8 iqmode, u8 dac_test_mode, bool modify_bbmult)
-{
- u16 num_samps;
- u16 loops = 0xffff;
- u16 wait = 0;
-
- num_samps =
- wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, dac_test_mode);
- if (num_samps == 0) {
- return -EBADE;
- }
-
- wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode,
- dac_test_mode, modify_bbmult);
-
- return 0;
-}
-
-static void
-wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, cs32 *tone_buf,
- u16 num_samps)
-{
- u16 t;
- u32 *data_buf = NULL;
-
- data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC);
- if (data_buf == NULL) {
- return;
- }
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- for (t = 0; t < num_samps; t++) {
- data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) |
- (((unsigned int)tone_buf[t].q) & 0x3ff);
- }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32,
- data_buf);
-
- kfree(data_buf);
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
static void
wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
u16 wait, u8 iqmode, u8 dac_test_mode,
@@ -22356,22 +23352,24 @@ wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7);
if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) {
lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
- (0x7 << 8);
+ (0x7 << 8);
lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
- (0x7 << 8);
+ (0x7 << 8);
} else {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 7),
- wlc_phy_read_lpf_bw_ctl_nphy
- (pi, 0), 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 7),
+ wlc_phy_read_lpf_bw_ctl_nphy
+ (pi,
+ 0), 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
pi->nphy_sample_play_lpf_bw_ctl_ovr = true;
lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
- (0x7 << 8);
+ (0x7 << 8);
lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
- (0x7 << 8);
+ (0x7 << 8);
}
}
@@ -22380,7 +23378,7 @@ wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
&bb_mult);
pi->nphy_bb_mult_save =
- BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK);
+ BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK);
}
if (modify_bbmult) {
@@ -22395,11 +23393,11 @@ wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
write_phy_reg(pi, 0xc6, num_samps - 1);
- if (loops != 0xffff) {
+ if (loops != 0xffff)
write_phy_reg(pi, 0xc4, loops - 1);
- } else {
+ else
write_phy_reg(pi, 0xc4, loops);
- }
+
write_phy_reg(pi, 0xc5, wait);
orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
@@ -22420,6 +23418,25 @@ wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
}
+int
+wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
+ u8 iqmode, u8 dac_test_mode, bool modify_bbmult)
+{
+ u16 num_samps;
+ u16 loops = 0xffff;
+ u16 wait = 0;
+
+ num_samps = wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val,
+ dac_test_mode);
+ if (num_samps == 0)
+ return -EBADE;
+
+ wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode,
+ dac_test_mode, modify_bbmult);
+
+ return 0;
+}
+
void wlc_phy_stopplayback_nphy(struct brcms_phy *pi)
{
u16 playback_status;
@@ -22429,13 +23446,11 @@ void wlc_phy_stopplayback_nphy(struct brcms_phy *pi)
wlc_phy_stay_in_carriersearch_nphy(pi, true);
playback_status = read_phy_reg(pi, 0xc7);
- if (playback_status & 0x1) {
+ if (playback_status & 0x1)
or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP);
- } else if (playback_status & 0x2) {
-
+ else if (playback_status & 0x2)
and_phy_reg(pi, 0xc2,
(u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN);
- }
and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2));
@@ -22450,10 +23465,11 @@ void wlc_phy_stopplayback_nphy(struct brcms_phy *pi)
if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) {
if (pi->nphy_sample_play_lpf_bw_ctl_ovr) {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 7),
- 0, 0, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 7),
+ 0, 0, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
pi->nphy_sample_play_lpf_bw_ctl_ovr = false;
}
}
@@ -22462,6 +23478,47 @@ void wlc_phy_stopplayback_nphy(struct brcms_phy *pi)
wlc_phy_stay_in_carriersearch_nphy(pi, false);
}
+static u32 *brcms_phy_get_tx_pwrctrl_tbl(struct brcms_phy *pi)
+{
+ u32 *tx_pwrctrl_tbl = NULL;
+ uint phyrev = pi->pubpi.phy_rev;
+
+ if (PHY_IPA(pi)) {
+ tx_pwrctrl_tbl =
+ wlc_phy_get_ipa_gaintbl_nphy(pi);
+ } else {
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ if (NREV_IS(phyrev, 3))
+ tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev3;
+ else if (NREV_IS(phyrev, 4))
+ tx_pwrctrl_tbl =
+ (pi->srom_fem5g.extpagain == 3) ?
+ nphy_tpc_5GHz_txgain_HiPwrEPA :
+ nphy_tpc_5GHz_txgain_rev4;
+ else
+ tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev5;
+ } else {
+ if (NREV_GE(phyrev, 7)) {
+ if (pi->pubpi.radiorev == 3)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_epa_2057rev3;
+ else if (pi->pubpi.radiorev == 5)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_epa_2057rev5;
+ } else {
+ if (NREV_GE(phyrev, 5) &&
+ (pi->srom_fem2g.extpagain == 3))
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_HiPwrEPA;
+ else
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_rev3;
+ }
+ }
+ }
+ return tx_pwrctrl_tbl;
+}
+
struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi)
{
u16 base_idx[2], curr_gain[2];
@@ -22482,33 +23539,33 @@ struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi)
for (core_no = 0; core_no < 2; core_no++) {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
target_gain.ipa[core_no] =
- curr_gain[core_no] & 0x0007;
+ curr_gain[core_no] & 0x0007;
target_gain.pad[core_no] =
- ((curr_gain[core_no] & 0x00F8) >> 3);
+ ((curr_gain[core_no] & 0x00F8) >> 3);
target_gain.pga[core_no] =
- ((curr_gain[core_no] & 0x0F00) >> 8);
+ ((curr_gain[core_no] & 0x0F00) >> 8);
target_gain.txgm[core_no] =
- ((curr_gain[core_no] & 0x7000) >> 12);
+ ((curr_gain[core_no] & 0x7000) >> 12);
target_gain.txlpf[core_no] =
- ((curr_gain[core_no] & 0x8000) >> 15);
+ ((curr_gain[core_no] & 0x8000) >> 15);
} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
target_gain.ipa[core_no] =
- curr_gain[core_no] & 0x000F;
+ curr_gain[core_no] & 0x000F;
target_gain.pad[core_no] =
- ((curr_gain[core_no] & 0x00F0) >> 4);
+ ((curr_gain[core_no] & 0x00F0) >> 4);
target_gain.pga[core_no] =
- ((curr_gain[core_no] & 0x0F00) >> 8);
+ ((curr_gain[core_no] & 0x0F00) >> 8);
target_gain.txgm[core_no] =
- ((curr_gain[core_no] & 0x7000) >> 12);
+ ((curr_gain[core_no] & 0x7000) >> 12);
} else {
target_gain.ipa[core_no] =
- curr_gain[core_no] & 0x0003;
+ curr_gain[core_no] & 0x0003;
target_gain.pad[core_no] =
- ((curr_gain[core_no] & 0x000C) >> 2);
+ ((curr_gain[core_no] & 0x000C) >> 2);
target_gain.pga[core_no] =
- ((curr_gain[core_no] & 0x0070) >> 4);
+ ((curr_gain[core_no] & 0x0070) >> 4);
target_gain.txgm[core_no] =
- ((curr_gain[core_no] & 0x0380) >> 7);
+ ((curr_gain[core_no] & 0x0380) >> 7);
}
}
} else {
@@ -22518,96 +23575,60 @@ struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi)
base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f;
for (core_no = 0; core_no < 2; core_no++) {
if (NREV_GE(phyrev, 3)) {
- if (PHY_IPA(pi)) {
- tx_pwrctrl_tbl =
- wlc_phy_get_ipa_gaintbl_nphy(pi);
- } else {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (NREV_IS(phyrev, 3)) {
- tx_pwrctrl_tbl =
- nphy_tpc_5GHz_txgain_rev3;
- } else if (NREV_IS(phyrev, 4)) {
- tx_pwrctrl_tbl =
- (pi->srom_fem5g.
- extpagain ==
- 3) ?
- nphy_tpc_5GHz_txgain_HiPwrEPA
- :
- nphy_tpc_5GHz_txgain_rev4;
- } else {
- tx_pwrctrl_tbl =
- nphy_tpc_5GHz_txgain_rev5;
- }
- } else {
- if (NREV_GE(phyrev, 7)) {
- if (pi->pubpi.
- radiorev == 3) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_epa_2057rev3;
- } else if (pi->pubpi.
- radiorev ==
- 5) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_epa_2057rev5;
- }
-
- } else {
- if (NREV_GE(phyrev, 5)
- && (pi->srom_fem2g.
- extpagain ==
- 3)) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_HiPwrEPA;
- } else {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_rev3;
- }
- }
- }
- }
+ tx_pwrctrl_tbl =
+ brcms_phy_get_tx_pwrctrl_tbl(pi);
if (NREV_GE(phyrev, 7)) {
target_gain.ipa[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 16) & 0x7;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 16) & 0x7;
target_gain.pad[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 19) & 0x1f;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 19) & 0x1f;
target_gain.pga[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 24) & 0xf;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 24) & 0xf;
target_gain.txgm[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 28) & 0x7;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 28) & 0x7;
target_gain.txlpf[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 31) & 0x1;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 31) & 0x1;
} else {
target_gain.ipa[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 16) & 0xf;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 16) & 0xf;
target_gain.pad[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 20) & 0xf;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 20) & 0xf;
target_gain.pga[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 24) & 0xf;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 24) & 0xf;
target_gain.txgm[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 28) & 0x7;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 28) & 0x7;
}
} else {
target_gain.ipa[core_no] =
- (nphy_tpc_txgain[base_idx[core_no]] >> 16) &
- 0x3;
+ (nphy_tpc_txgain[base_idx[core_no]] >>
+ 16) & 0x3;
target_gain.pad[core_no] =
- (nphy_tpc_txgain[base_idx[core_no]] >> 18) &
- 0x3;
+ (nphy_tpc_txgain[base_idx[core_no]] >>
+ 18) & 0x3;
target_gain.pga[core_no] =
- (nphy_tpc_txgain[base_idx[core_no]] >> 20) &
- 0x7;
+ (nphy_tpc_txgain[base_idx[core_no]] >>
+ 20) & 0x7;
target_gain.txgm[core_no] =
- (nphy_tpc_txgain[base_idx[core_no]] >> 23) &
- 0x7;
+ (nphy_tpc_txgain[base_idx[core_no]] >>
+ 23) & 0x7;
}
}
}
@@ -22626,26 +23647,23 @@ wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no,
u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
params->txlpf = target_gain.txlpf[core_no];
- }
+
params->txgm = target_gain.txgm[core_no];
params->pga = target_gain.pga[core_no];
params->pad = target_gain.pad[core_no];
params->ipa = target_gain.ipa[core_no];
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
params->cal_gain =
- ((params->txlpf << 15) | (params->
- txgm << 12) | (params->
- pga << 8) |
- (params->pad << 3) | (params->ipa));
- } else {
+ ((params->txlpf << 15) | (params->txgm << 12) |
+ (params->pga << 8) |
+ (params->pad << 3) | (params->ipa));
+ else
params->cal_gain =
- ((params->txgm << 12) | (params->
- pga << 8) | (params->
- pad << 4) |
- (params->ipa));
- }
+ ((params->txgm << 12) | (params->pga << 8) |
+ (params->pad << 4) | (params->ipa));
+
params->ncorr[0] = 0x79;
params->ncorr[1] = 0x79;
params->ncorr[2] = 0x79;
@@ -22654,9 +23672,8 @@ wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no,
} else {
gain_index = ((target_gain.pad[core_no] << 0) |
- (target_gain.pga[core_no] << 4) | (target_gain.
- txgm[core_no]
- << 8));
+ (target_gain.pga[core_no] << 4) |
+ (target_gain.txgm[core_no] << 8));
idx = -1;
for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) {
@@ -22688,37 +23705,39 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
for (core = 0; core <= 1; core++) {
pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MASTER);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MASTER);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- IQCAL_VCM_HG);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ IQCAL_VCM_HG);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- IQCAL_IDAC);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ IQCAL_IDAC);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TSSI_VCM);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0;
pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MUX);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MUX);
if (pi->pubpi.radiorev != 5)
pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TSSIA);
+ READ_RADIO_REG3(pi, RADIO_2057, TX,
+ core,
+ TSSIA);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TSSI_MISC1);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TSSI_MISC1);
if (CHSPEC_IS5G(pi->radio_chanspec)) {
WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
@@ -22734,19 +23753,15 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
if (pi->use_int_tx_iqlo_cal_nphy) {
WRITE_RADIO_REG3(pi, RADIO_2057, TX,
core, TX_SSI_MUX, 0x4);
- if (!
- (pi->
- internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
+ if (!(pi->
+ internal_tx_iqlo_cal_tapoff_intpa_nphy))
WRITE_RADIO_REG3(pi, RADIO_2057,
TX, core,
TSSIA, 0x31);
- } else {
-
+ else
WRITE_RADIO_REG3(pi, RADIO_2057,
TX, core,
TSSIA, 0x21);
- }
}
WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
TSSI_MISC1, 0x00);
@@ -22767,19 +23782,15 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
WRITE_RADIO_REG3(pi, RADIO_2057, TX,
core, TX_SSI_MUX,
0x06);
- if (!
- (pi->
- internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
+ if (!(pi->
+ internal_tx_iqlo_cal_tapoff_intpa_nphy))
WRITE_RADIO_REG3(pi, RADIO_2057,
TX, core,
TSSIG, 0x31);
- } else {
-
+ else
WRITE_RADIO_REG3(pi, RADIO_2057,
TX, core,
TSSIG, 0x21);
- }
}
WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
TSSI_MISC1, 0x00);
@@ -22789,58 +23800,62 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
for (core = 0; core <= 1; core++) {
jtag_core =
- (core ==
- PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+ (core ==
+ PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
- read_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MASTER |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TX_SSI_MASTER |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
- read_radio_reg(pi,
- RADIO_2056_TX_IQCAL_VCM_HG |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_IQCAL_VCM_HG |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
- read_radio_reg(pi,
- RADIO_2056_TX_IQCAL_IDAC |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_IQCAL_IDAC |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
- read_radio_reg(pi,
- RADIO_2056_TX_TSSI_VCM | jtag_core);
+ read_radio_reg(
+ pi,
+ RADIO_2056_TX_TSSI_VCM |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] =
- read_radio_reg(pi,
- RADIO_2056_TX_TX_AMP_DET |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TX_AMP_DET |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
- read_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TX_SSI_MUX |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
- read_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TSSIA | jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
- read_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TSSIG | jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
- read_radio_reg(pi,
- RADIO_2056_TX_TSSI_MISC1 |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TSSI_MISC1 |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] =
- read_radio_reg(pi,
- RADIO_2056_TX_TSSI_MISC2 |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TSSI_MISC2 |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] =
- read_radio_reg(pi,
- RADIO_2056_TX_TSSI_MISC3 |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TSSI_MISC3 |
+ jtag_core);
if (CHSPEC_IS5G(pi->radio_chanspec)) {
write_radio_reg(pi,
@@ -22860,16 +23875,18 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
jtag_core, 0x00);
if (PHY_IPA(pi)) {
- write_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX
- | jtag_core, 0x4);
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TX_SSI_MUX
+ | jtag_core, 0x4);
write_radio_reg(pi,
RADIO_2056_TX_TSSIA |
jtag_core, 0x1);
} else {
- write_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX
- | jtag_core, 0x00);
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TX_SSI_MUX
+ | jtag_core, 0x00);
write_radio_reg(pi,
RADIO_2056_TX_TSSIA |
jtag_core, 0x2f);
@@ -22909,26 +23926,27 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
if (PHY_IPA(pi)) {
- write_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX
- | jtag_core, 0x06);
- if (NREV_LT(pi->pubpi.phy_rev, 5)) {
-
- write_radio_reg(pi,
- RADIO_2056_TX_TSSIG
- | jtag_core,
- 0x11);
- } else {
-
- write_radio_reg(pi,
- RADIO_2056_TX_TSSIG
- | jtag_core,
- 0x1);
- }
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TX_SSI_MUX
+ | jtag_core, 0x06);
+ if (NREV_LT(pi->pubpi.phy_rev, 5))
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TSSIG
+ | jtag_core,
+ 0x11);
+ else
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TSSIG
+ | jtag_core,
+ 0x1);
} else {
- write_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX
- | jtag_core, 0x00);
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TX_SSI_MUX
+ | jtag_core, 0x00);
write_radio_reg(pi,
RADIO_2056_TX_TSSIG |
jtag_core, 0x20);
@@ -22948,23 +23966,23 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
} else {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54);
pi->tx_rx_cal_radio_saveregs[2] =
- read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29);
pi->tx_rx_cal_radio_saveregs[3] =
- read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54);
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
pi->tx_rx_cal_radio_saveregs[5] =
- read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) ==
0) {
@@ -23025,11 +24043,8 @@ static void wlc_phy_txcal_radio_cleanup_nphy(struct brcms_phy *pi)
if (pi->pubpi.radiorev != 5)
WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
TSSIA,
- pi->
- tx_rx_cal_radio_saveregs[(core
- *
- 11) +
- 6]);
+ pi->tx_rx_cal_radio_saveregs
+ [(core * 11) + 6]);
WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG,
pi->
@@ -23043,9 +24058,8 @@ static void wlc_phy_txcal_radio_cleanup_nphy(struct brcms_phy *pi)
}
} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
for (core = 0; core <= 1; core++) {
- jtag_core =
- (core ==
- PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+ jtag_core = (core == PHY_CORE_0) ?
+ RADIO_2056_TX0 : RADIO_2056_TX1;
write_radio_reg(pi,
RADIO_2056_TX_TX_SSI_MASTER | jtag_core,
@@ -23171,23 +24185,22 @@ static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi)
pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91);
pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92);
- if (!(pi->use_int_tx_iqlo_cal_nphy)) {
-
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_PA,
- 1,
- RADIO_MIMO_CORESEL_CORE1
- |
- RADIO_MIMO_CORESEL_CORE2);
- } else {
-
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_PA,
- 0,
- RADIO_MIMO_CORESEL_CORE1
- |
- RADIO_MIMO_CORESEL_CORE2);
- }
+ if (!(pi->use_int_tx_iqlo_cal_nphy))
+ wlc_phy_rfctrlintc_override_nphy(
+ pi,
+ NPHY_RfctrlIntc_override_PA,
+ 1,
+ RADIO_MIMO_CORESEL_CORE1
+ |
+ RADIO_MIMO_CORESEL_CORE2);
+ else
+ wlc_phy_rfctrlintc_override_nphy(
+ pi,
+ NPHY_RfctrlIntc_override_PA,
+ 0,
+ RADIO_MIMO_CORESEL_CORE1
+ |
+ RADIO_MIMO_CORESEL_CORE2);
wlc_phy_rfctrlintc_override_nphy(pi,
NPHY_RfctrlIntc_override_TRSW,
@@ -23205,12 +24218,13 @@ static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi)
0x29b, (0x1 << 0), (0) << 0);
if (NREV_IS(pi->pubpi.phy_rev, 7)
- || NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
- wlc_phy_read_lpf_bw_ctl_nphy
- (pi, 0), 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- }
+ || NREV_GE(pi->pubpi.phy_rev, 8))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 7),
+ wlc_phy_read_lpf_bw_ctl_nphy
+ (pi,
+ 0), 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
if (pi->use_int_tx_iqlo_cal_nphy
&& !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
@@ -23221,25 +24235,30 @@ static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi)
1 << 4);
if (CHSPEC_IS2G(pi->radio_chanspec)) {
- mod_radio_reg(pi,
- RADIO_2057_PAD2G_TUNE_PUS_CORE0,
- 1, 0);
- mod_radio_reg(pi,
- RADIO_2057_PAD2G_TUNE_PUS_CORE1,
- 1, 0);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+ 1, 0);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+ 1, 0);
} else {
- mod_radio_reg(pi,
- RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
- 1, 0);
- mod_radio_reg(pi,
- RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
- 1, 0);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+ 1, 0);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+ 1, 0);
}
} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 3), 0,
- 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 3), 0,
+ 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
}
}
} else {
@@ -23302,11 +24321,11 @@ static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi)
write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
if (NREV_IS(pi->pubpi.phy_rev, 7)
- || NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
- 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- }
+ || NREV_GE(pi->pubpi.phy_rev, 8))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 7), 0, 0,
+ 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
wlc_phy_resetcca_nphy(pi);
@@ -23315,28 +24334,33 @@ static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi)
if (NREV_IS(pi->pubpi.phy_rev, 7)) {
if (CHSPEC_IS2G(pi->radio_chanspec)) {
- mod_radio_reg(pi,
- RADIO_2057_PAD2G_TUNE_PUS_CORE0,
- 1, 1);
- mod_radio_reg(pi,
- RADIO_2057_PAD2G_TUNE_PUS_CORE1,
- 1, 1);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+ 1, 1);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+ 1, 1);
} else {
- mod_radio_reg(pi,
- RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
- 1, 1);
- mod_radio_reg(pi,
- RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
- 1, 1);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+ 1, 1);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+ 1, 1);
}
mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
0);
} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 3), 0,
- 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 3), 0,
+ 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
}
}
} else {
@@ -23356,10 +24380,6 @@ static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi)
}
}
-#define NPHY_CAL_TSSISAMPS 64
-#define NPHY_TEST_TONE_FREQ_40MHz 4000
-#define NPHY_TEST_TONE_FREQ_20MHz 2500
-
void
wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps)
{
@@ -23379,8 +24399,8 @@ wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps)
idle_tssi[1] = (temp <= 31) ? temp : (temp - 64);
tssi_type =
- CHSPEC_IS5G(pi->radio_chanspec) ?
- (u8)NPHY_RSSI_SEL_TSSI_5G : (u8)NPHY_RSSI_SEL_TSSI_2G;
+ CHSPEC_IS5G(pi->radio_chanspec) ?
+ (u8)NPHY_RSSI_SEL_TSSI_5G : (u8)NPHY_RSSI_SEL_TSSI_2G;
wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps);
@@ -23390,17 +24410,15 @@ wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps)
pwrindex[0] = idle_tssi[0] - tssival[0] + 64;
pwrindex[1] = idle_tssi[1] - tssival[1] + 64;
- if (pwrindex[0] < 0) {
+ if (pwrindex[0] < 0)
pwrindex[0] = 0;
- } else if (pwrindex[0] > 63) {
+ else if (pwrindex[0] > 63)
pwrindex[0] = 63;
- }
- if (pwrindex[1] < 0) {
+ if (pwrindex[1] < 0)
pwrindex[1] = 0;
- } else if (pwrindex[1] > 63) {
+ else if (pwrindex[1] > 63)
pwrindex[1] = 63;
- }
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1,
(u32) pwrindex[0], 32, &qdBm_pwrbuf[0]);
@@ -23408,326 +24426,1241 @@ wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps)
(u32) pwrindex[1], 32, &qdBm_pwrbuf[1]);
}
-static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi)
+static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core)
{
- u16 txcal_gain[2];
+ int index;
+ u32 bbmult_scale;
+ u16 bbmult;
+ u16 tblentry;
- pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0];
- pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0];
- wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
- wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+ struct nphy_txiqcal_ladder ladder_lo[] = {
+ {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+ {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
+ {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7}
+ };
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
- txcal_gain);
+ struct nphy_txiqcal_ladder ladder_iq[] = {
+ {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+ {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1},
+ {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
+ };
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40;
- txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40;
- } else {
- txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60;
- txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60;
+ bbmult = (core == PHY_CORE_0) ?
+ ((pi->nphy_txcal_bbmult >> 8) & 0xff) :
+ (pi->nphy_txcal_bbmult & 0xff);
+
+ for (index = 0; index < 18; index++) {
+ bbmult_scale = ladder_lo[index].percent * bbmult;
+ bbmult_scale /= 100;
+
+ tblentry =
+ ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16,
+ &tblentry);
+
+ bbmult_scale = ladder_iq[index].percent * bbmult;
+ bbmult_scale /= 100;
+
+ tblentry =
+ ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32,
+ 16, &tblentry);
}
+}
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
- txcal_gain);
+static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core)
+{
+ u16 tmp;
+ tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee));
+
+ tmp = (tmp & (0x7f << 8)) >> 8;
+ return (u8) tmp;
}
-static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi)
+static void
+wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0, u8 idx1)
{
- bool save_bbmult = false;
- u8 txcal_index_2057_rev5n7 = 0;
- u8 txcal_index_2057_rev3n4n6 = 10;
+ mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0);
+
+ if (NREV_GT(pi->pubpi.phy_rev, 1))
+ mod_phy_reg(pi, 0x222, (0xff << 0), idx1);
+}
+
+static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi)
+{
+ u16 m0m1;
+
+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
+ return m0m1;
+}
+
+static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1)
+{
+ u16 m0m1 = (u16) ((m0 << 8) | m1);
+
+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1);
+ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1);
+}
+
+static void
+wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi,
+ struct nphy_papd_restore_state *state, u8 core)
+{
+ s32 tone_freq;
+ u8 off_core;
+ u16 mixgain = 0;
+
+ off_core = core ^ 0x1;
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ if (NREV_IS(pi->pubpi.phy_rev, 7)
+ || NREV_GE(pi->pubpi.phy_rev, 8))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 7),
+ wlc_phy_read_lpf_bw_ctl_nphy
+ (pi,
+ 0), 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (pi->pubpi.radiorev == 5)
+ mixgain = (core == 0) ? 0x20 : 0x00;
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ mixgain = 0x00;
+ else if ((pi->pubpi.radiorev <= 4)
+ || (pi->pubpi.radiorev == 6))
+ mixgain = 0x00;
+ } else {
+ if ((pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6))
+ mixgain = 0x50;
+ else if ((pi->pubpi.radiorev == 3)
+ || (pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ mixgain = 0x0;
+ }
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
+ mixgain, (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+ 1, (1 << core), 0);
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+ 0, (1 << off_core), 0);
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+ 0, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+ 0, (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+ state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+ 0xa6 : 0xa7);
+ state->afeoverride[core] =
+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+ state->afectrl[off_core] =
+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6);
+ state->afeoverride[off_core] =
+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f);
+
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+ (0x1 << 2), 0);
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+ 0xa5), (0x1 << 2), (0x1 << 2));
+
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6),
+ (0x1 << 2), (0x1 << 2));
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 :
+ 0x8f), (0x1 << 2), (0x1 << 2));
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ state->pwrup[core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_PWRUP);
+ state->atten[core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_ATTEN);
+ state->pwrup[off_core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_2G_PWRUP);
+ state->atten[off_core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_2G_ATTEN);
+
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_PWRUP, 0xc);
- if (pi->use_int_tx_iqlo_cal_nphy) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
if ((pi->pubpi.radiorev == 3) ||
(pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
+ (pi->pubpi.radiorev == 6))
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_ATTEN, 0xf0);
+ else if (pi->pubpi.radiorev == 5)
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_ATTEN,
+ (core == 0) ? 0xf7 : 0xf2);
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_ATTEN, 0xf0);
- pi->nphy_txcal_pwr_idx[0] =
- txcal_index_2057_rev3n4n6;
- pi->nphy_txcal_pwr_idx[1] =
- txcal_index_2057_rev3n4n6;
- wlc_phy_txpwr_index_nphy(pi, 3,
- txcal_index_2057_rev3n4n6,
- false);
- } else {
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_2G_PWRUP, 0x0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_2G_ATTEN, 0xff);
+ } else {
+ state->pwrup[core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_PWRUP);
+ state->atten[core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_ATTEN);
+ state->pwrup[off_core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_5G_PWRUP);
+ state->atten[off_core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_5G_ATTEN);
- pi->nphy_txcal_pwr_idx[0] =
- txcal_index_2057_rev5n7;
- pi->nphy_txcal_pwr_idx[1] =
- txcal_index_2057_rev5n7;
- wlc_phy_txpwr_index_nphy(pi, 3,
- txcal_index_2057_rev5n7,
- false);
- }
- save_bbmult = true;
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_PWRUP, 0xc);
- } else if (NREV_LT(pi->pubpi.phy_rev, 5)) {
- wlc_phy_cal_txgainctrl_nphy(pi, 11, false);
- if (pi->sh->hw_phytxchain != 3) {
- pi->nphy_txcal_pwr_idx[1] =
- pi->nphy_txcal_pwr_idx[0];
- wlc_phy_txpwr_index_nphy(pi, 3,
- pi->
- nphy_txcal_pwr_idx[0],
- true);
- save_bbmult = true;
+ if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_ATTEN, 0xf4);
+
+ else
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_ATTEN, 0xf0);
+
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_5G_PWRUP, 0x0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_5G_ATTEN, 0xff);
+ }
+
+ tone_freq = 4000;
+
+ wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (1) << 13);
+
+ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0);
+
+ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (0) << 13);
+
+ } else {
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0);
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0);
+
+ state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+ 0xa6 : 0xa7);
+ state->afeoverride[core] =
+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+ (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0);
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+ 0xa5),
+ (0x1 << 0) |
+ (0x1 << 1) |
+ (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+
+ state->vga_master[core] =
+ READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER);
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b);
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ state->fbmix[core] =
+ READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+ TXFBMIX_G);
+ state->intpa_master[core] =
+ READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAG_MASTER);
+
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G,
+ 0x03);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAG_MASTER, 0x04);
+ } else {
+ state->fbmix[core] =
+ READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+ TXFBMIX_A);
+ state->intpa_master[core] =
+ READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAA_MASTER);
+
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A,
+ 0x03);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAA_MASTER, 0x04);
+
+ }
+
+ tone_freq = 4000;
+
+ wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (1) << 0);
+
+ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (0) << 0);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+ }
+}
+
+static void
+wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi,
+ struct nphy_papd_restore_state *state)
+{
+ u8 core;
+
+ wlc_phy_stopplayback_nphy(pi);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_PWRUP, 0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_ATTEN,
+ state->atten[core]);
+ } else {
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_PWRUP, 0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_ATTEN,
+ state->atten[core]);
}
+ }
- } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
- if (PHY_IPA(pi)) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- wlc_phy_cal_txgainctrl_nphy(pi, 12,
- false);
- } else {
- pi->nphy_txcal_pwr_idx[0] = 80;
- pi->nphy_txcal_pwr_idx[1] = 80;
- wlc_phy_txpwr_index_nphy(pi, 3, 80,
- false);
- save_bbmult = true;
- }
+ if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2),
+ 1, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ else
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2),
+ 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
+ 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+ write_phy_reg(pi, (core == PHY_CORE_0) ?
+ 0xa6 : 0xa7, state->afectrl[core]);
+ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+ 0xa5, state->afeoverride[core]);
+ }
+
+ wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+ (state->mm & 0xff));
+
+ if (NREV_IS(pi->pubpi.phy_rev, 7)
+ || NREV_GE(pi->pubpi.phy_rev, 8))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 7), 0, 0,
+ 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ } else {
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1);
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1);
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1);
+
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER,
+ state->vga_master[core]);
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+ TXFBMIX_G, state->fbmix[core]);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAG_MASTER,
+ state->intpa_master[core]);
} else {
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+ TXFBMIX_A, state->fbmix[core]);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAA_MASTER,
+ state->intpa_master[core]);
+ }
- wlc_phy_internal_cal_txgain_nphy(pi);
- save_bbmult = true;
+ write_phy_reg(pi, (core == PHY_CORE_0) ?
+ 0xa6 : 0xa7, state->afectrl[core]);
+ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+ 0xa5, state->afeoverride[core]);
+ }
+
+ wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+ (state->mm & 0xff));
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1);
+ }
+}
+
+static void
+wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32 start,
+ u32 end)
+{
+ u32 *buf, *src, *dst, sz;
+
+ sz = end - start + 1;
+
+ buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC);
+ if (NULL == buf)
+ return;
+
+ src = buf;
+ dst = buf + NPHY_PAPD_EPS_TBL_SIZE;
+
+ wlc_phy_table_read_nphy(pi,
+ (core ==
+ PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 :
+ NPHY_TBL_ID_EPSILONTBL1),
+ NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src);
+
+ do {
+ u32 phy_a1, phy_a2;
+ s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7;
+
+ phy_a1 = end - min(end, (winsz >> 1));
+ phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1,
+ end + (winsz >> 1));
+ phy_a3 = phy_a2 - phy_a1 + 1;
+ phy_a6 = 0;
+ phy_a7 = 0;
+
+ do {
+ wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4,
+ &phy_a5);
+ phy_a6 += phy_a4;
+ phy_a7 += phy_a5;
+ } while (phy_a2-- != phy_a1);
+
+ phy_a6 /= phy_a3;
+ phy_a7 /= phy_a3;
+ dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff);
+ } while (end-- != start);
+
+ wlc_phy_table_write_nphy(pi,
+ (core ==
+ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 :
+ NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst);
+
+ kfree(buf);
+}
+
+static void
+wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains,
+ enum phy_cal_mode cal_mode, u8 core)
+{
+ u16 phy_a1, phy_a2, phy_a3;
+ u16 phy_a4, phy_a5;
+ bool phy_a6;
+ u8 phy_a7, m[2];
+ u32 phy_a8 = 0;
+ struct nphy_txgains phy_a9;
+
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
+ return;
+
+ phy_a7 = (core == PHY_CORE_0) ? 1 : 0;
+
+ phy_a6 = ((cal_mode == CAL_GCTRL)
+ || (cal_mode == CAL_SOFT)) ? true : false;
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ phy_a9 = wlc_phy_get_tx_gain_nphy(pi);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ phy_a5 = ((phy_a9.txlpf[core] << 15) |
+ (phy_a9.txgm[core] << 12) |
+ (phy_a9.pga[core] << 8) |
+ (txgains->gains.pad[core] << 3) |
+ (phy_a9.ipa[core]));
+ else
+ phy_a5 = ((phy_a9.txlpf[core] << 15) |
+ (phy_a9.txgm[core] << 12) |
+ (txgains->gains.pga[core] << 8) |
+ (phy_a9.pad[core] << 3) | (phy_a9.ipa[core]));
+
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_txgain,
+ phy_a5, (1 << core), 0);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if ((pi->pubpi.radiorev <= 4)
+ || (pi->pubpi.radiorev == 6))
+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ?
+ 60 : 79;
+ else
+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ?
+ 45 : 64;
+ } else {
+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107;
+ }
+
+ m[phy_a7] = 0;
+ wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+ phy_a2 = 63;
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if ((pi->pubpi.radiorev == 4)
+ || (pi->pubpi.radiorev == 6)) {
+ phy_a1 = 30;
+ phy_a3 = 30;
+ } else {
+ phy_a1 = 25;
+ phy_a3 = 25;
+ }
+ } else {
+ if ((pi->pubpi.radiorev == 5)
+ || (pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8)) {
+ phy_a1 = 25;
+ phy_a3 = 25;
+ } else {
+ phy_a1 = 35;
+ phy_a3 = 35;
}
+ }
- } else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
- if (PHY_IPA(pi)) {
+ if (cal_mode == CAL_GCTRL) {
+ if ((pi->pubpi.radiorev == 5)
+ && (CHSPEC_IS2G(pi->radio_chanspec)))
+ phy_a1 = 55;
+ else if (((pi->pubpi.radiorev == 7) &&
+ (CHSPEC_IS2G(pi->radio_chanspec))) ||
+ ((pi->pubpi.radiorev == 8) &&
+ (CHSPEC_IS2G(pi->radio_chanspec))))
+ phy_a1 = 60;
+ else
+ phy_a1 = 63;
+
+ } else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) {
+
+ phy_a1 = 35;
+ phy_a3 = 35;
+ }
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (1) << 0);
+
+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (0) << 0);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (1) << 13);
+
+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (0) << 13);
+
+ write_phy_reg(pi, 0x2a1, 0x80);
+ write_phy_reg(pi, 0x2a2, 0x100);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 4), (11) << 4);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 8), (11) << 8);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 0), (0x3) << 0);
+
+ write_phy_reg(pi, 0x2e5, 0x20);
+
+ mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+ mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+ mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+ 1, ((core == 0) ? 1 : 2), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+ 0, ((core == 0) ? 2 : 1), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+ write_phy_reg(pi, 0x2be, 1);
+ SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+ 0, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+ wlc_phy_table_write_nphy(pi,
+ (core ==
+ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+ : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+ 32, &phy_a8);
+
+ if (cal_mode != CAL_GCTRL) {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ wlc_phy_a1_nphy(pi, core, 5, 0, 35);
+ }
+
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_txgain,
+ phy_a5, (1 << core), 1);
+
+ } else {
+
+ if (txgains) {
+ if (txgains->useindex) {
+ phy_a4 = 15 - ((txgains->index) >> 3);
if (CHSPEC_IS2G(pi->radio_chanspec)) {
- wlc_phy_cal_txgainctrl_nphy(pi, 12,
- false);
+ if (NREV_GE(pi->pubpi.phy_rev, 6))
+ phy_a5 = 0x00f7 | (phy_a4 << 8);
+
+ else
+ if (NREV_IS(pi->pubpi.phy_rev, 5))
+ phy_a5 = 0x10f7 | (phy_a4 << 8);
+ else
+ phy_a5 = 0x50f7 | (phy_a4 << 8);
} else {
- wlc_phy_cal_txgainctrl_nphy(pi, 14,
- false);
+ phy_a5 = 0x70f7 | (phy_a4 << 8);
}
+ wlc_phy_rfctrl_override_nphy(pi,
+ (0x1 << 13),
+ phy_a5,
+ (1 << core), 0);
} else {
-
- wlc_phy_internal_cal_txgain_nphy(pi);
- save_bbmult = true;
+ wlc_phy_rfctrl_override_nphy(pi,
+ (0x1 << 13),
+ 0x5bf7,
+ (1 << core), 0);
}
}
- } else {
- wlc_phy_cal_txgainctrl_nphy(pi, 10, false);
- }
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 45 : 64;
+ else
+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107;
- if (save_bbmult) {
- wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
- &pi->nphy_txcal_bbmult);
+ m[phy_a7] = 0;
+ wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+ phy_a2 = 63;
+
+ if (cal_mode == CAL_FULL) {
+ phy_a1 = 25;
+ phy_a3 = 25;
+ } else if (cal_mode == CAL_SOFT) {
+ phy_a1 = 25;
+ phy_a3 = 25;
+ } else if (cal_mode == CAL_GCTRL) {
+ phy_a1 = 63;
+ phy_a3 = 25;
+ } else {
+
+ phy_a1 = 25;
+ phy_a3 = 25;
+ }
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (1) << 0);
+
+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (0) << 0);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (1) << 13);
+
+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (0) << 13);
+
+ write_phy_reg(pi, 0x2a1, 0x20);
+ write_phy_reg(pi, 0x2a2, 0x60);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0xf << 4), (9) << 4);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0xf << 8), (9) << 8);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0xf << 0), (0x2) << 0);
+
+ write_phy_reg(pi, 0x2e5, 0x20);
+ } else {
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 11), (1) << 11);
+
+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 11), (0) << 11);
+
+ write_phy_reg(pi, 0x2a1, 0x80);
+ write_phy_reg(pi, 0x2a2, 0x600);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 4), (0) << 4);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 8), (0) << 8);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 0), (0x3) << 0);
+
+ mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8);
+
+ }
+
+ mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+ mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+ mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0);
+
+ write_phy_reg(pi, 0x2be, 1);
+ SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+
+ wlc_phy_table_write_nphy(pi,
+ (core ==
+ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+ : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+ 32, &phy_a8);
+
+ if (cal_mode != CAL_GCTRL)
+ wlc_phy_a1_nphy(pi, core, 5, 0, 40);
}
}
-void
-wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower,
- bool debug)
+static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core)
{
- int gainctrl_loopidx;
- uint core;
- u16 m0m1, curr_m0m1;
- s32 delta_power;
- s32 txpwrindex;
- s32 qdBm_power[2];
- u16 orig_BBConfig;
- u16 phy_saveregs[4];
- u32 freq_test;
- u16 ampl_test = 250;
- uint stepsize;
- bool phyhang_avoid_state = false;
+ int phy_a1;
+ int phy_a2;
+ bool phy_a3;
+ struct nphy_ipa_txcalgains phy_a4;
+ bool phy_a5 = false;
+ bool phy_a6 = true;
+ s32 phy_a7, phy_a8;
+ u32 phy_a9;
+ int phy_a10;
+ bool phy_a11 = false;
+ int phy_a12;
+ u8 phy_a13 = 0;
+ u8 phy_a14;
+ u8 *phy_a15 = NULL;
+
+ phy_a4.useindex = true;
+ phy_a12 = start_gain;
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- stepsize = 2;
- } else {
+ phy_a2 = 20;
+ phy_a1 = 1;
- stepsize = 1;
- }
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (pi->pubpi.radiorev == 5) {
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- freq_test = 5000;
- } else {
- freq_test = 2500;
- }
+ phy_a15 = pad_gain_codes_used_2057rev5;
+ phy_a13 =
+ sizeof(pad_gain_codes_used_2057rev5) /
+ sizeof(pad_gain_codes_used_2057rev5
+ [0]) - 1;
- wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
- wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+ } else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8)) {
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
+ phy_a15 = pad_gain_codes_used_2057rev7;
+ phy_a13 =
+ sizeof(pad_gain_codes_used_2057rev7) /
+ sizeof(pad_gain_codes_used_2057rev7
+ [0]) - 1;
- phyhang_avoid_state = pi->phyhang_avoid;
- pi->phyhang_avoid = false;
+ } else {
- phy_saveregs[0] = read_phy_reg(pi, 0x91);
- phy_saveregs[1] = read_phy_reg(pi, 0x92);
- phy_saveregs[2] = read_phy_reg(pi, 0xe7);
- phy_saveregs[3] = read_phy_reg(pi, 0xec);
- wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1,
- RADIO_MIMO_CORESEL_CORE1 |
- RADIO_MIMO_CORESEL_CORE2);
+ phy_a15 = pad_all_gain_codes_2057;
+ phy_a13 = sizeof(pad_all_gain_codes_2057) /
+ sizeof(pad_all_gain_codes_2057[0]) -
+ 1;
+ }
- if (!debug) {
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_TRSW,
- 0x2, RADIO_MIMO_CORESEL_CORE1);
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_TRSW,
- 0x8, RADIO_MIMO_CORESEL_CORE2);
- } else {
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_TRSW,
- 0x1, RADIO_MIMO_CORESEL_CORE1);
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_TRSW,
- 0x7, RADIO_MIMO_CORESEL_CORE2);
- }
+ } else {
- orig_BBConfig = read_phy_reg(pi, 0x01);
- mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+ phy_a15 = pga_all_gain_codes_2057;
+ phy_a13 = sizeof(pga_all_gain_codes_2057) /
+ sizeof(pga_all_gain_codes_2057[0]) - 1;
+ }
- wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+ phy_a14 = 0;
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core];
+ for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ phy_a4.gains.pad[core] =
+ (u16) phy_a15[phy_a12];
+ else
+ phy_a4.gains.pga[core] =
+ (u16) phy_a15[phy_a12];
- for (gainctrl_loopidx = 0; gainctrl_loopidx < 2;
- gainctrl_loopidx++) {
- wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
- false);
+ wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
- if (core == PHY_CORE_0) {
- curr_m0m1 = m0m1 & 0xff00;
- } else {
- curr_m0m1 = m0m1 & 0x00ff;
+ wlc_phy_table_read_nphy(pi,
+ (core ==
+ PHY_CORE_0 ?
+ NPHY_TBL_ID_EPSILONTBL0 :
+ NPHY_TBL_ID_EPSILONTBL1), 1,
+ 63, 32, &phy_a9);
+
+ wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
+
+ phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
+ (phy_a8 == 4095) || (phy_a8 == -4096));
+
+ if (!phy_a6 && (phy_a3 != phy_a5)) {
+ if (!phy_a3)
+ phy_a12 -= (u8) phy_a1;
+
+ phy_a11 = true;
+ break;
}
- wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1);
- wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1);
+ if (phy_a3)
+ phy_a12 += (u8) phy_a1;
+ else
+ phy_a12 -= (u8) phy_a1;
- udelay(50);
+ if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) {
+ if (phy_a12 < phy_a14)
+ phy_a12 = phy_a14;
+ else
+ phy_a12 = phy_a13;
- wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
- NPHY_CAL_TSSISAMPS);
+ phy_a11 = true;
+ break;
+ }
- pi->nphy_bb_mult_save = 0;
- wlc_phy_stopplayback_nphy(pi);
+ phy_a6 = false;
+ phy_a5 = phy_a3;
+ }
- delta_power = (dBm_targetpower * 4) - qdBm_power[core];
+ } else {
+ phy_a2 = 10;
+ phy_a1 = 8;
+ for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
+ phy_a4.index = (u8) phy_a12;
+ wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
- txpwrindex -= stepsize * delta_power;
- if (txpwrindex < 0) {
- txpwrindex = 0;
- } else if (txpwrindex > 127) {
- txpwrindex = 127;
+ wlc_phy_table_read_nphy(pi,
+ (core ==
+ PHY_CORE_0 ?
+ NPHY_TBL_ID_EPSILONTBL0 :
+ NPHY_TBL_ID_EPSILONTBL1), 1,
+ 63, 32, &phy_a9);
+
+ wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
+
+ phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
+ (phy_a8 == 4095) || (phy_a8 == -4096));
+
+ if (!phy_a6 && (phy_a3 != phy_a5)) {
+ if (!phy_a3)
+ phy_a12 -= (u8) phy_a1;
+
+ phy_a11 = true;
+ break;
}
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (NREV_IS(pi->pubpi.phy_rev, 4) &&
- (pi->srom_fem5g.extpagain == 3)) {
- if (txpwrindex < 30) {
- txpwrindex = 30;
- }
- }
- } else {
- if (NREV_GE(pi->pubpi.phy_rev, 5) &&
- (pi->srom_fem2g.extpagain == 3)) {
- if (txpwrindex < 50) {
- txpwrindex = 50;
- }
- }
+ if (phy_a3)
+ phy_a12 += (u8) phy_a1;
+ else
+ phy_a12 -= (u8) phy_a1;
+
+ if ((phy_a12 < 0) || (phy_a12 > 127)) {
+ if (phy_a12 < 0)
+ phy_a12 = 0;
+ else
+ phy_a12 = 127;
+
+ phy_a11 = true;
+ break;
}
- wlc_phy_txpwr_index_nphy(pi, (1 << core),
- (u8) txpwrindex, true);
+ phy_a6 = false;
+ phy_a5 = phy_a3;
}
- pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex;
+ }
- if (debug) {
- u16 radio_gain;
- u16 dbg_m0m1;
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ return (u8) phy_a15[phy_a12];
+ else
+ return (u8) phy_a12;
- wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+}
- wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
- false);
+static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal)
+{
+ struct nphy_ipa_txcalgains phy_b1[2];
+ struct nphy_papd_restore_state phy_b2;
+ bool phy_b3;
+ u8 phy_b4;
+ u8 phy_b5;
+ s16 phy_b6, phy_b7, phy_b8;
+ u16 phy_b9;
+ s16 phy_b10, phy_b11, phy_b12;
- wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
- wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1);
+ phy_b11 = 0;
+ phy_b12 = 0;
+ phy_b7 = 0;
+ phy_b8 = 0;
+ phy_b6 = 0;
- udelay(100);
+ if (pi->nphy_papd_skip == 1)
+ return;
- wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
- NPHY_CAL_TSSISAMPS);
+ phy_b3 = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ if (!phy_b3)
+ wlapi_suspend_mac_and_wait(pi->sh->physhim);
- wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16,
- &radio_gain);
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
- mdelay(4000);
- pi->nphy_bb_mult_save = 0;
- wlc_phy_stopplayback_nphy(pi);
+ pi->nphy_force_papd_cal = false;
+
+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++)
+ pi->nphy_papd_tx_gain_at_last_cal[phy_b5] =
+ wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5);
+
+ pi->nphy_papd_last_cal = pi->sh->now;
+ pi->nphy_papd_recal_counter++;
+
+ phy_b4 = pi->nphy_txpwrctrl;
+ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32,
+ nphy_papd_scaltbl);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32,
+ nphy_papd_scaltbl);
+
+ phy_b9 = read_phy_reg(pi, 0x01);
+ mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+ s32 i, val = 0;
+ for (i = 0; i < 64; i++)
+ wlc_phy_table_write_nphy(pi,
+ ((phy_b5 ==
+ PHY_CORE_0) ?
+ NPHY_TBL_ID_EPSILONTBL0 :
+ NPHY_TBL_ID_EPSILONTBL1), 1,
+ i, 32, &val);
+ }
+
+ wlc_phy_ipa_restore_tx_digi_filts_nphy(pi);
+
+ phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi);
+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+ wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if ((pi->pubpi.radiorev == 3)
+ || (pi->pubpi.radiorev == 4)
+ || (pi->pubpi.radiorev == 6)) {
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ 23;
+ } else if (pi->pubpi.radiorev == 5) {
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ 0;
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ wlc_phy_a3_nphy(
+ pi,
+ pi->
+ nphy_papd_cal_gain_index
+ [phy_b5],
+ phy_b5);
+
+ } else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8)) {
+
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ 0;
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ wlc_phy_a3_nphy(
+ pi,
+ pi->
+ nphy_papd_cal_gain_index
+ [phy_b5],
+ phy_b5);
+
+ }
+
+ phy_b1[phy_b5].gains.pad[phy_b5] =
+ pi->nphy_papd_cal_gain_index[phy_b5];
+
+ } else {
+ pi->nphy_papd_cal_gain_index[phy_b5] = 0;
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ wlc_phy_a3_nphy(
+ pi,
+ pi->
+ nphy_papd_cal_gain_index
+ [phy_b5], phy_b5);
+ phy_b1[phy_b5].gains.pga[phy_b5] =
+ pi->nphy_papd_cal_gain_index[phy_b5];
+ }
+ } else {
+ phy_b1[phy_b5].useindex = true;
+ phy_b1[phy_b5].index = 16;
+ phy_b1[phy_b5].index =
+ wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index,
+ phy_b5);
+
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ 15 - ((phy_b1[phy_b5].index) >> 3);
}
+
+ switch (pi->nphy_papd_cal_type) {
+ case 0:
+ wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5);
+ break;
+ case 1:
+ wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5);
+ break;
+ }
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
}
- wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true);
- wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true);
+ if (NREV_LT(pi->pubpi.phy_rev, 7))
+ wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
- wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult);
+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+ int eps_offset = 0;
- write_phy_reg(pi, 0x01, orig_BBConfig);
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (pi->pubpi.radiorev == 3)
+ eps_offset = -2;
+ else if (pi->pubpi.radiorev == 5)
+ eps_offset = 3;
+ else
+ eps_offset = -1;
+ } else {
+ eps_offset = 2;
+ }
- write_phy_reg(pi, 0x91, phy_saveregs[0]);
- write_phy_reg(pi, 0x92, phy_saveregs[1]);
- write_phy_reg(pi, 0xe7, phy_saveregs[2]);
- write_phy_reg(pi, 0xec, phy_saveregs[3]);
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5];
+ phy_b10 = 0;
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6)) {
+ phy_b12 = -(
+ nphy_papd_padgain_dlt_2g_2057rev3n4
+ [phy_b8] + 1) / 2;
+ phy_b10 = -1;
+ } else if (pi->pubpi.radiorev == 5) {
+ phy_b12 = -(
+ nphy_papd_padgain_dlt_2g_2057rev5
+ [phy_b8] + 1) / 2;
+ } else if ((pi->pubpi.radiorev == 7) ||
+ (pi->pubpi.radiorev == 8)) {
+ phy_b12 = -(
+ nphy_papd_padgain_dlt_2g_2057rev7
+ [phy_b8] + 1) / 2;
+ }
+ } else {
+ phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5];
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6))
+ phy_b11 =
+ -(nphy_papd_pgagain_dlt_5g_2057
+ [phy_b7]
+ + 1) / 2;
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ phy_b11 = -(
+ nphy_papd_pgagain_dlt_5g_2057rev7
+ [phy_b7] + 1) / 2;
- pi->phyhang_avoid = phyhang_avoid_state;
+ phy_b10 = -9;
+ }
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ phy_b6 =
+ -60 + 27 + eps_offset + phy_b12 +
+ phy_b10;
+ else
+ phy_b6 =
+ -60 + 27 + eps_offset + phy_b11 +
+ phy_b10;
-static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core)
-{
- int index;
- u32 bbmult_scale;
- u16 bbmult;
- u16 tblentry;
+ mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
+ 0x29c, (0x1ff << 7), (phy_b6) << 7);
- struct nphy_txiqcal_ladder ladder_lo[] = {
- {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
- {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
- {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7}
- };
+ pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
+ } else {
+ if (NREV_LT(pi->pubpi.phy_rev, 5))
+ eps_offset = 4;
+ else
+ eps_offset = 2;
- struct nphy_txiqcal_ladder ladder_iq[] = {
- {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
- {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1},
- {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
- };
+ phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3);
- bbmult = (core == PHY_CORE_0) ?
- ((pi->nphy_txcal_bbmult >> 8) & 0xff) : (pi->
- nphy_txcal_bbmult & 0xff);
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ phy_b11 =
+ -(nphy_papd_pga_gain_delta_ipa_2g[
+ phy_b7] +
+ 1) / 2;
+ phy_b10 = 0;
+ } else {
+ phy_b11 =
+ -(nphy_papd_pga_gain_delta_ipa_5g[
+ phy_b7] +
+ 1) / 2;
+ phy_b10 = -9;
+ }
- for (index = 0; index < 18; index++) {
- bbmult_scale = ladder_lo[index].percent * bbmult;
- bbmult_scale /= 100;
+ phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10;
- tblentry =
- ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16,
- &tblentry);
+ mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
+ 0x29c, (0x1ff << 7), (phy_b6) << 7);
- bbmult_scale = ladder_iq[index].percent * bbmult;
- bbmult_scale /= 100;
+ pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
+ }
+ }
+
+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (0) << 13);
+
+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (0) << 13);
+
+ } else {
+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 11), (0) << 11);
+
+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 11), (0) << 11);
- tblentry =
- ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32,
- 16, &tblentry);
}
+ pi->nphy_papdcomp = NPHY_PAPD_COMP_ON;
+
+ write_phy_reg(pi, 0x01, phy_b9);
+
+ wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+
+ wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4);
+ if (phy_b4 == PHY_TPC_HW_OFF) {
+ wlc_phy_txpwr_index_nphy(pi, (1 << 0),
+ (s8) (pi->nphy_txpwrindex[0].
+ index_internal), false);
+ wlc_phy_txpwr_index_nphy(pi, (1 << 1),
+ (s8) (pi->nphy_txpwrindex[1].
+ index_internal), false);
+ }
+
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+ if (!phy_b3)
+ wlapi_enable_mac(pi->sh->physhim);
}
void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
@@ -23738,11 +25671,6 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
bool restore_tx_gain = false;
bool mphase;
- if (NORADIO_ENAB(pi->pubpi)) {
- wlc_phy_cal_perical_mphase_reset(pi);
- return;
- }
-
if (PHY_MUTED(pi))
return;
@@ -23751,19 +25679,18 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
else if (caltype == PHY_PERICAL_PARTIAL)
fullcal = false;
- if (pi->cal_type_override != PHY_PERICAL_AUTO) {
+ if (pi->cal_type_override != PHY_PERICAL_AUTO)
fullcal =
- (pi->cal_type_override == PHY_PERICAL_FULL) ? true : false;
- }
+ (pi->cal_type_override ==
+ PHY_PERICAL_FULL) ? true : false;
if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) {
if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec)
wlc_phy_cal_perical_mphase_restart(pi);
}
- if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) {
+ if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL))
wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
- }
wlapi_suspend_mac_and_wait(pi->sh->physhim);
@@ -23772,9 +25699,9 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) ||
(pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) {
pi->nphy_cal_orig_pwr_idx[0] =
- (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f);
+ (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f);
pi->nphy_cal_orig_pwr_idx[1] =
- (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f);
+ (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f);
if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) {
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2,
@@ -23803,7 +25730,8 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
target_gain = pi->nphy_cal_target_gain;
}
if (0 ==
- wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, mphase)) {
+ wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal,
+ mphase)) {
if (PHY_IPA(pi))
wlc_phy_a4(pi, true);
@@ -23815,13 +25743,9 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
wlc_phyreg_enter((struct brcms_phy_pub *) pi);
if (0 == wlc_phy_cal_rxiq_nphy(pi, target_gain,
- (pi->
- first_cal_after_assoc
- || (pi->
- cal_type_override
- ==
- PHY_PERICAL_FULL))
- ? 2 : 0, false)) {
+ (pi->first_cal_after_assoc ||
+ (pi->cal_type_override ==
+ PHY_PERICAL_FULL)) ? 2 : 0, false)) {
wlc_phy_savecal_nphy(pi);
wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
@@ -23829,9 +25753,8 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
pi->nphy_perical_last = pi->sh->now;
}
}
- if (caltype != PHY_PERICAL_AUTO) {
+ if (caltype != PHY_PERICAL_AUTO)
wlc_phy_rssi_cal_nphy(pi);
- }
if (pi->first_cal_after_assoc
|| (pi->cal_type_override == PHY_PERICAL_FULL)) {
@@ -23840,18 +25763,17 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
}
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_radio205x_vcocal_nphy(pi);
- }
} else {
switch (pi->mphase_cal_phase_id) {
case MPHASE_CAL_STATE_INIT:
pi->nphy_perical_last = pi->sh->now;
pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_precal_txgain_nphy(pi);
- }
+
pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
pi->mphase_cal_phase_id++;
break;
@@ -23866,8 +25788,8 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
pi->nphy_rxcal_active = true;
if (wlc_phy_cal_txiqlo_nphy
- (pi, pi->nphy_cal_target_gain, fullcal,
- true) != 0) {
+ (pi, pi->nphy_cal_target_gain, fullcal,
+ true) != 0) {
wlc_phy_cal_perical_mphase_reset(pi);
break;
@@ -23875,20 +25797,19 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
if (NREV_LE(pi->pubpi.phy_rev, 2) &&
(pi->mphase_cal_phase_id ==
- MPHASE_CAL_STATE_TXPHASE4)) {
+ MPHASE_CAL_STATE_TXPHASE4))
pi->mphase_cal_phase_id += 2;
- } else {
+ else
pi->mphase_cal_phase_id++;
- }
break;
case MPHASE_CAL_STATE_PAPDCAL:
if ((pi->radar_percal_mask & 0x2) != 0)
pi->nphy_rxcal_active = true;
- if (PHY_IPA(pi)) {
+ if (PHY_IPA(pi))
wlc_phy_a4(pi, true);
- }
+
pi->mphase_cal_phase_id++;
break;
@@ -23899,9 +25820,8 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
(pi->first_cal_after_assoc ||
(pi->cal_type_override ==
PHY_PERICAL_FULL)) ? 2 : 0,
- false) == 0) {
+ false) == 0)
wlc_phy_savecal_nphy(pi);
- }
pi->mphase_cal_phase_id++;
break;
@@ -23912,16 +25832,15 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
wlc_phy_rssi_cal_nphy(pi);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_radio205x_vcocal_nphy(pi);
- }
+
restore_tx_gain = true;
- if (pi->first_cal_after_assoc) {
+ if (pi->first_cal_after_assoc)
pi->mphase_cal_phase_id++;
- } else {
+ else
wlc_phy_cal_perical_mphase_reset(pi);
- }
break;
@@ -23962,15 +25881,15 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
} else {
wlc_phy_txpwr_index_nphy(pi, (1 << 0),
(s8) (pi->
- nphy_txpwrindex
- [0].
- index_internal),
+ nphy_txpwrindex
+ [0].
+ index_internal),
false);
wlc_phy_txpwr_index_nphy(pi, (1 << 1),
(s8) (pi->
- nphy_txpwrindex
- [1].
- index_internal),
+ nphy_txpwrindex
+ [1].
+ index_internal),
false);
}
}
@@ -24007,35 +25926,35 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901,
- 0x1902,
+ 0x1902,
0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607,
- 0x6407
+ 0x6407
};
u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400,
- 0x3200,
+ 0x3200,
0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406,
- 0x6407
+ 0x6407
};
u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201,
- 0x1202,
+ 0x1202,
0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207,
- 0x4707
+ 0x4707
};
u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900,
- 0x2300,
+ 0x2300,
0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706,
- 0x4707
+ 0x4707
};
u16 tbl_tx_iqlo_cal_startcoefs[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000
+ 0x0000
};
u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
@@ -24071,11 +25990,10 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
pi->phyhang_avoid = false;
}
- if (CHSPEC_IS40(pi->radio_chanspec)) {
+ if (CHSPEC_IS40(pi->radio_chanspec))
phy_bw = 40;
- } else {
+ else
phy_bw = 20;
- }
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
@@ -24117,11 +26035,10 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
16, tbl_ptr);
}
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
write_phy_reg(pi, 0xc2, 0x8ad9);
- } else {
+ else
write_phy_reg(pi, 0xc2, 0x8aa9);
- }
max_val = 250;
tone_freq = (phy_bw == 20) ? 2500 : 5000;
@@ -24131,7 +26048,8 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
bcmerror = 0;
} else {
bcmerror =
- wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, false);
+ wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0,
+ false);
}
if (bcmerror == 0) {
@@ -24139,19 +26057,15 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
tbl_ptr = pi->mphase_txcal_bestcoeffs;
tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
tbl_len -= 2;
- }
} else {
if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) {
tbl_ptr = pi->nphy_txiqlocal_bestc;
tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
tbl_len -= 2;
- }
} else {
fullcal = true;
@@ -24159,14 +26073,12 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
tbl_ptr =
tbl_tx_iqlo_cal_startcoefs_nphyrev3;
- tbl_len =
- ARRAY_SIZE
- (tbl_tx_iqlo_cal_startcoefs_nphyrev3);
+ tbl_len = ARRAY_SIZE(
+ tbl_tx_iqlo_cal_startcoefs_nphyrev3);
} else {
tbl_ptr = tbl_tx_iqlo_cal_startcoefs;
- tbl_len =
- ARRAY_SIZE
- (tbl_tx_iqlo_cal_startcoefs);
+ tbl_len = ARRAY_SIZE(
+ tbl_tx_iqlo_cal_startcoefs);
}
}
}
@@ -24175,21 +26087,22 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
if (fullcal) {
max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
- ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) :
- ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal);
+ ARRAY_SIZE(
+ tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) :
+ ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal);
} else {
max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
- ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal_nphyrev3) :
- ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal);
+ ARRAY_SIZE(
+ tbl_tx_iqlo_cal_cmds_recal_nphyrev3) :
+ ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal);
}
if (mphase) {
cal_cnt = pi->mphase_txcal_cmdidx;
- if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) {
+ if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds)
num_cals = cal_cnt + pi->mphase_txcal_numcmds;
- } else {
+ else
num_cals = max_cal_cmds;
- }
} else {
cal_cnt = 0;
num_cals = max_cal_cmds;
@@ -24199,13 +26112,14 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
if (fullcal) {
cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
- tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3
- [cal_cnt] :
- tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt];
+ tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3
+ [cal_cnt] :
+ tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt];
} else {
cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
- tbl_tx_iqlo_cal_cmds_recal_nphyrev3[cal_cnt]
- : tbl_tx_iqlo_cal_cmds_recal[cal_cnt];
+ tbl_tx_iqlo_cal_cmds_recal_nphyrev3[
+ cal_cnt]
+ : tbl_tx_iqlo_cal_cmds_recal[cal_cnt];
}
core_no = ((cal_cmd & 0x3000) >> 12);
@@ -24216,15 +26130,16 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
PHY_IPA(pi)
&& (CHSPEC_IS2G(pi->radio_chanspec)))) {
if (!ladder_updated[core_no]) {
- wlc_phy_update_txcal_ladder_nphy(pi,
- core_no);
+ wlc_phy_update_txcal_ladder_nphy(
+ pi,
+ core_no);
ladder_updated[core_no] = true;
}
}
val =
- (cal_params[core_no].
- ncorr[cal_type] << 8) | NPHY_N_GCTL;
+ (cal_params[core_no].
+ ncorr[cal_type] << 8) | NPHY_N_GCTL;
write_phy_reg(pi, 0xc1, val);
if ((cal_type == 1) || (cal_type == 3)
@@ -24272,8 +26187,8 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
}
mphase_cal_lastphase =
- (NREV_LE(pi->pubpi.phy_rev, 2)) ?
- MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5;
+ (NREV_LE(pi->pubpi.phy_rev, 2)) ?
+ MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5;
if (!mphase
|| (pi->mphase_cal_phase_id == mphase_cal_lastphase)) {
@@ -24303,10 +26218,9 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
16, tbl_buf);
tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
tbl_len -= 2;
- }
+
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
tbl_len, 96, 16,
pi->nphy_txiqlocal_bestc);
@@ -24315,10 +26229,9 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
} else {
tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
tbl_len -= 2;
- }
+
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
tbl_len, 96, 16,
pi->mphase_txcal_bestcoeffs);
@@ -24343,9 +26256,8 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
wlc_phy_tx_iq_war_nphy(pi);
}
- if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 4))
pi->phyhang_avoid = phyhang_avoid_state;
- }
wlc_phy_stay_in_carriersearch_nphy(pi, false);
@@ -24387,18 +26299,6 @@ static void wlc_phy_reapply_txcal_coeffs_nphy(struct brcms_phy *pi)
}
}
-static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi)
-{
- struct nphy_iq_comp tx_comp;
-
- wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, (void *)&tx_comp);
-
- wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0);
- wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0);
- wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1);
- wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1);
-}
-
void
wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write,
struct nphy_iq_comp *pcomp)
@@ -24438,14 +26338,17 @@ wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est,
if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) {
for (core = 0; core < pi->pubpi.phy_corenum; core++) {
est[core].i_pwr =
- (read_phy_reg(pi, NPHY_IqestipwrAccHi(core)) << 16)
- | read_phy_reg(pi, NPHY_IqestipwrAccLo(core));
+ (read_phy_reg(pi,
+ NPHY_IqestipwrAccHi(core)) << 16)
+ | read_phy_reg(pi, NPHY_IqestipwrAccLo(core));
est[core].q_pwr =
- (read_phy_reg(pi, NPHY_IqestqpwrAccHi(core)) << 16)
- | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core));
+ (read_phy_reg(pi,
+ NPHY_IqestqpwrAccHi(core)) << 16)
+ | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core));
est[core].iq_prod =
- (read_phy_reg(pi, NPHY_IqestIqAccHi(core)) << 16) |
- read_phy_reg(pi, NPHY_IqestIqAccLo(core));
+ (read_phy_reg(pi,
+ NPHY_IqestIqAccHi(core)) << 16) |
+ read_phy_reg(pi, NPHY_IqestIqAccLo(core));
}
}
}
@@ -24470,7 +26373,7 @@ static void wlc_phy_calc_rx_iq_comp_nphy(struct brcms_phy *pi, u8 core_mask)
new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0;
wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
- cal_try:
+cal_try:
wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0);
new_comp = old_comp;
@@ -24561,7 +26464,7 @@ static void wlc_phy_calc_rx_iq_comp_nphy(struct brcms_phy *pi, u8 core_mask)
if (bcmerror != 0) {
printk(KERN_DEBUG "%s: Failed, cnt = %d\n", __func__,
- cal_retry);
+ cal_retry);
if (cal_retry < CAL_RETRY_CNT) {
cal_retry++;
@@ -24584,121 +26487,125 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core)
if (rx_core == PHY_CORE_0) {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP);
+ read_radio_reg(pi,
+ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN);
+ read_radio_reg(pi,
+ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN);
write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
- 0x3);
+ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+ 0x3);
write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
- 0xaf);
+ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+ 0xaf);
} else {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP);
+ read_radio_reg(pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN);
-
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
- 0x3);
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
- 0x7f);
+ read_radio_reg(pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN);
+
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+ 0x3);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+ 0x7f);
}
} else {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP);
+ read_radio_reg(pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN);
-
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
- 0x3);
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
- 0xaf);
+ read_radio_reg(pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN);
+
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+ 0x3);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+ 0xaf);
} else {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP);
+ read_radio_reg(pi,
+ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN);
+ read_radio_reg(pi,
+ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN);
write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
- 0x3);
+ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+ 0x3);
write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
- 0x7f);
+ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+ 0x7f);
}
}
} else {
if (rx_core == PHY_CORE_0) {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2056_TX_RXIQCAL_TXMUX |
- RADIO_2056_TX1);
+ read_radio_reg(pi,
+ RADIO_2056_TX_RXIQCAL_TXMUX |
+ RADIO_2056_TX1);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2056_RX_RXIQCAL_RXMUX |
- RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RXIQCAL_RXMUX |
+ RADIO_2056_RX0);
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[2] =
- read_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RXSPARE2 |
+ RADIO_2056_RX0);
pi->tx_rx_cal_radio_saveregs[3] =
- read_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX1);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TXSPARE2 |
+ RADIO_2056_TX1);
}
if (CHSPEC_IS5G(pi->radio_chanspec)) {
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_LNAA_MASTER
+ | RADIO_2056_RX0);
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX0, 0x40);
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_MASTER
+ | RADIO_2056_RX0, 0x40);
write_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX1, bias_a);
+ RADIO_2056_TX_TXSPARE2 |
+ RADIO_2056_TX1, bias_a);
write_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX0, bias_a);
+ RADIO_2056_RX_RXSPARE2 |
+ RADIO_2056_RX0, bias_a);
} else {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAA_TUNE
- | RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_LNAA_TUNE
+ | RADIO_2056_RX0);
offtune_val =
- (pi->
- tx_rx_cal_radio_saveregs[2] & 0xF0)
- >> 8;
+ (pi->tx_rx_cal_radio_saveregs
+ [2] & 0xF0) >> 8;
offtune_val =
- (offtune_val <= 0x7) ? 0xF : 0;
+ (offtune_val <= 0x7) ? 0xF : 0;
mod_radio_reg(pi,
RADIO_2056_RX_LNAA_TUNE |
@@ -24715,34 +26622,41 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core)
} else {
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX0);
-
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX0, 0x40);
-
- write_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX1, bias_g);
-
- write_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX0, bias_g);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX0);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX0, 0x40);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TXSPARE2
+ |
+ RADIO_2056_TX1, bias_g);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_RXSPARE2
+ |
+ RADIO_2056_RX0, bias_g);
} else {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAG_TUNE
- | RADIO_2056_RX0);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_TUNE
+ | RADIO_2056_RX0);
offtune_val =
- (pi->
- tx_rx_cal_radio_saveregs[2] & 0xF0)
- >> 8;
+ (pi->
+ tx_rx_cal_radio_saveregs[2] &
+ 0xF0) >> 8;
offtune_val =
- (offtune_val <= 0x7) ? 0xF : 0;
+ (offtune_val <= 0x7) ? 0xF : 0;
mod_radio_reg(pi,
RADIO_2056_RX_LNAG_TUNE |
@@ -24760,56 +26674,63 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core)
} else {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2056_TX_RXIQCAL_TXMUX |
- RADIO_2056_TX0);
+ read_radio_reg(pi,
+ RADIO_2056_TX_RXIQCAL_TXMUX |
+ RADIO_2056_TX0);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2056_RX_RXIQCAL_RXMUX |
- RADIO_2056_RX1);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RXIQCAL_RXMUX |
+ RADIO_2056_RX1);
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[2] =
- read_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX1);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RXSPARE2 |
+ RADIO_2056_RX1);
pi->tx_rx_cal_radio_saveregs[3] =
- read_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX0);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TXSPARE2 |
+ RADIO_2056_TX0);
}
if (CHSPEC_IS5G(pi->radio_chanspec)) {
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX1);
-
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX1, 0x40);
-
- write_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX0, bias_a);
-
- write_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX1, bias_a);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_MASTER
+ | RADIO_2056_RX1);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_MASTER |
+ RADIO_2056_RX1, 0x40);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TXSPARE2
+ |
+ RADIO_2056_TX0, bias_a);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_RXSPARE2
+ |
+ RADIO_2056_RX1, bias_a);
} else {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAA_TUNE
- | RADIO_2056_RX1);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_TUNE
+ | RADIO_2056_RX1);
offtune_val =
- (pi->
- tx_rx_cal_radio_saveregs[2] & 0xF0)
- >> 8;
+ (pi->
+ tx_rx_cal_radio_saveregs[2] &
+ 0xF0) >> 8;
offtune_val =
- (offtune_val <= 0x7) ? 0xF : 0;
+ (offtune_val <= 0x7) ? 0xF : 0;
mod_radio_reg(pi,
RADIO_2056_RX_LNAA_TUNE |
@@ -24826,33 +26747,40 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core)
} else {
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX1);
-
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX1, 0x40);
-
- write_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX0, bias_g);
-
- write_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX1, bias_g);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX1);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX1, 0x40);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TXSPARE2
+ |
+ RADIO_2056_TX0, bias_g);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_RXSPARE2
+ |
+ RADIO_2056_RX1, bias_g);
} else {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAG_TUNE
- | RADIO_2056_RX1);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_TUNE
+ | RADIO_2056_RX1);
offtune_val =
- (pi->
- tx_rx_cal_radio_saveregs[2] & 0xF0)
- >> 8;
+ (pi->
+ tx_rx_cal_radio_saveregs[2] &
+ 0xF0) >> 8;
offtune_val =
- (offtune_val <= 0x7) ? 0xF : 0;
+ (offtune_val <= 0x7) ? 0xF : 0;
mod_radio_reg(pi,
RADIO_2056_RX_LNAG_TUNE |
@@ -24876,46 +26804,54 @@ static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core)
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
if (rx_core == PHY_CORE_0) {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
- pi->
- tx_rx_cal_radio_saveregs[0]);
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
- pi->
- tx_rx_cal_radio_saveregs[1]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+ pi->
+ tx_rx_cal_radio_saveregs[0]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+ pi->
+ tx_rx_cal_radio_saveregs[1]);
} else {
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
- pi->
- tx_rx_cal_radio_saveregs[0]);
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
- pi->
- tx_rx_cal_radio_saveregs[1]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+ pi->
+ tx_rx_cal_radio_saveregs[0]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+ pi->
+ tx_rx_cal_radio_saveregs[1]);
}
} else {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
- pi->
- tx_rx_cal_radio_saveregs[0]);
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
- pi->
- tx_rx_cal_radio_saveregs[1]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+ pi->
+ tx_rx_cal_radio_saveregs[0]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+ pi->
+ tx_rx_cal_radio_saveregs[1]);
} else {
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
- pi->
- tx_rx_cal_radio_saveregs[0]);
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
- pi->
- tx_rx_cal_radio_saveregs[1]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+ pi->
+ tx_rx_cal_radio_saveregs[0]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+ pi->
+ tx_rx_cal_radio_saveregs[1]);
}
}
@@ -24946,37 +26882,39 @@ static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core)
}
if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (pi->pubpi.radiorev >= 5) {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX0,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- } else {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_TUNE
- | RADIO_2056_RX0,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- }
+ if (pi->pubpi.radiorev >= 5)
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_MASTER
+ | RADIO_2056_RX0,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
+ else
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_TUNE
+ | RADIO_2056_RX0,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
} else {
- if (pi->pubpi.radiorev >= 5) {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX0,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- } else {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_TUNE
- | RADIO_2056_RX0,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- }
+ if (pi->pubpi.radiorev >= 5)
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX0,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
+ else
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_TUNE
+ | RADIO_2056_RX0,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
}
} else {
@@ -25005,37 +26943,39 @@ static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core)
}
if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (pi->pubpi.radiorev >= 5) {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX1,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- } else {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_TUNE
- | RADIO_2056_RX1,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- }
+ if (pi->pubpi.radiorev >= 5)
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_MASTER
+ | RADIO_2056_RX1,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
+ else
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_TUNE
+ | RADIO_2056_RX1,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
} else {
- if (pi->pubpi.radiorev >= 5) {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX1,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- } else {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_TUNE
- | RADIO_2056_RX1,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- }
+ if (pi->pubpi.radiorev >= 5)
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX1,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
+ else
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_TUNE
+ | RADIO_2056_RX1,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
}
}
}
@@ -25046,18 +26986,16 @@ static void wlc_phy_rxcal_physetup_nphy(struct brcms_phy *pi, u8 rx_core)
u8 tx_core;
u16 rx_antval, tx_antval;
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
tx_core = rx_core;
- } else {
+ else
tx_core = (rx_core == PHY_CORE_0) ? 1 : 0;
- }
pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2);
pi->tx_rx_cal_phy_saveregs[1] =
- read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7);
+ read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7);
pi->tx_rx_cal_phy_saveregs[2] =
- read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5);
+ read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5);
pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91);
pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92);
pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a);
@@ -25122,17 +27060,19 @@ static void wlc_phy_rxcal_physetup_nphy(struct brcms_phy *pi, u8 rx_core)
NPHY_REV7_RFCTRLOVERRIDE_ID2);
wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0,
NPHY_REV7_RFCTRLOVERRIDE_ID1);
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 7),
- 2, 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- } else {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 7),
- 0, 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- }
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 7),
+ 2, 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ else
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 7),
+ 0, 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
0, 0, 0,
NPHY_REV7_RFCTRLOVERRIDE_ID1);
@@ -25203,26 +27143,24 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core,
struct phy_iq_est est[PHY_CORE_MAX];
u8 tx_core;
struct nphy_iq_comp save_comp, zero_comp;
- u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, thresh_pwr =
- 10000;
+ u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0,
+ thresh_pwr = 10000;
s16 desired_log2_pwr, actual_log2_pwr, delta_pwr;
bool gainctrl_done = false;
u8 mix_tia_gain = 3;
s8 optim_gaintbl_index = 0, prev_gaintbl_index = 0;
s8 curr_gaintbl_index = 3;
u8 gainctrl_dirn = NPHY_RXCAL_GAIN_INIT;
- struct nphy_ipa_txrxgain *nphy_rxcal_gaintbl;
+ const struct nphy_ipa_txrxgain *nphy_rxcal_gaintbl;
u16 hpvga, lpf_biq1, lpf_biq0, lna2, lna1;
int fine_gain_idx;
s8 txpwrindex;
u16 nphy_rxcal_txgain[2];
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
tx_core = rx_core;
- } else {
+ else
tx_core = 1 - rx_core;
- }
num_samps = 1024;
desired_log2_pwr = (cal_type == 0) ? 13 : 13;
@@ -25232,45 +27170,42 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core,
wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp);
if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
mix_tia_gain = 3;
- } else if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+ else if (NREV_GE(pi->pubpi.phy_rev, 4))
mix_tia_gain = 4;
- } else {
+ else
mix_tia_gain = 6;
- }
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7;
- } else {
+ else
nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz;
- }
} else {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7;
- } else {
+ else
nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz;
- }
}
do {
hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ?
- 0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga;
+ 0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga;
lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1;
lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0;
lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2;
lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1;
txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex;
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_rxgain,
- ((lpf_biq1 << 12) |
- (lpf_biq0 << 8) |
- (mix_tia_gain <<
- 4) | (lna2 << 2)
- | lna1), 0x3, 0);
- } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_rxgain,
+ ((lpf_biq1 << 12) |
+ (lpf_biq0 << 8) |
+ (mix_tia_gain << 4) | (lna2 << 2)
+ | lna1), 0x3, 0);
+ else
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
((hpvga << 12) |
(lpf_biq1 << 10) |
@@ -25278,7 +27213,6 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core,
(mix_tia_gain << 4) |
(lna2 << 2) | lna1), 0x3,
0);
- }
pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex;
@@ -25367,27 +27301,28 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core,
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
fine_gain_idx = (int)lpf_biq1 + delta_pwr;
- if (fine_gain_idx + (int)lpf_biq0 > 10) {
+ if (fine_gain_idx + (int)lpf_biq0 > 10)
lpf_biq1 = 10 - lpf_biq0;
- } else {
+ else
lpf_biq1 = (u16) max(fine_gain_idx, 0);
- }
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_rxgain,
- ((lpf_biq1 << 12) |
- (lpf_biq0 << 8) |
- (mix_tia_gain << 4) |
- (lna2 << 2) | lna1), 0x3,
- 0);
+
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_rxgain,
+ ((lpf_biq1 << 12) |
+ (lpf_biq0 << 8) |
+ (mix_tia_gain << 4) |
+ (lna2 << 2) | lna1), 0x3,
+ 0);
} else {
hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0);
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
- ((hpvga << 12) | (lpf_biq1 << 10) |
- (lpf_biq0 << 8) | (mix_tia_gain <<
- 4) | (lna2 <<
- 2) |
+ ((hpvga << 12) |
+ (lpf_biq1 << 10) |
+ (lpf_biq0 << 8) |
+ (mix_tia_gain << 4) |
+ (lna2 << 2) |
lna1), 0x3, 0);
-
}
if (rxgain != NULL) {
@@ -25444,9 +27379,8 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
u16 num_samps, log_num_samps = 10;
struct phy_iq_est est[PHY_CORE_MAX];
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
return 0;
- }
num_samps = (1 << log_num_samps);
@@ -25465,20 +27399,21 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
if (core_idx == 0) {
radio_addr_offset_rx = RADIO_2056_RX0;
radio_addr_offset_tx =
- (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+ (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
} else {
radio_addr_offset_rx = RADIO_2056_RX1;
radio_addr_offset_tx =
- (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0;
+ (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0;
}
orig_txlpf_rccal_lpc_ovr_val =
- read_radio_reg(pi,
- (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx));
+ read_radio_reg(pi,
+ (RADIO_2056_TX_TXLPF_RCCAL |
+ radio_addr_offset_tx));
orig_rxlpf_rccal_hpc_ovr_val =
- read_radio_reg(pi,
- (RADIO_2056_RX_RXLPF_RCCAL_HPC |
- radio_addr_offset_rx));
+ read_radio_reg(pi,
+ (RADIO_2056_RX_RXLPF_RCCAL_HPC |
+ radio_addr_offset_rx));
orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1);
@@ -25549,17 +27484,18 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
- if (core_idx == 0) {
+ if (core_idx == 0)
ref_iq_vals =
- max_t(u32, (est[0].i_pwr +
- est[0].q_pwr) >> (log_num_samps + 1),
- 1);
- } else {
+ max_t(u32, (est[0].i_pwr +
+ est[0].q_pwr) >>
+ (log_num_samps + 1),
+ 1);
+ else
ref_iq_vals =
- max_t(u32, (est[1].i_pwr +
- est[1].q_pwr) >> (log_num_samps + 1),
- 1);
- }
+ max_t(u32, (est[1].i_pwr +
+ est[1].q_pwr) >>
+ (log_num_samps + 1),
+ 1);
wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP,
0, 1, false);
@@ -25568,20 +27504,19 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
- if (core_idx == 0) {
- target_iq_vals =
- (est[0].i_pwr + est[0].q_pwr) >> (log_num_samps +
- 1);
- } else {
+ if (core_idx == 0)
+ target_iq_vals = (est[0].i_pwr + est[0].q_pwr) >>
+ (log_num_samps + 1);
+ else
target_iq_vals =
- (est[1].i_pwr + est[1].q_pwr) >> (log_num_samps +
- 1);
- }
+ (est[1].i_pwr +
+ est[1].q_pwr) >> (log_num_samps + 1);
+
pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals);
- if (rccal_stepsize == 0) {
+ if (rccal_stepsize == 0)
rccal_stepsize--;
- } else if (rccal_stepsize == 1) {
+ else if (rccal_stepsize == 1) {
last_rccal_val = rccal_val;
rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1;
last_pwr_ratio = pwr_ratio;
@@ -25594,21 +27529,20 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
if (rccal_stepsize == -1) {
best_rccal_val =
- (ABS((int)last_pwr_ratio - (int)target_pwr_ratio) <
- ABS((int)pwr_ratio -
- (int)target_pwr_ratio)) ? last_rccal_val :
- rccal_val;
+ (abs((int)last_pwr_ratio -
+ (int)target_pwr_ratio) <
+ abs((int)pwr_ratio -
+ (int)target_pwr_ratio)) ? last_rccal_val :
+ rccal_val;
if (CHSPEC_IS40(pi->radio_chanspec)) {
if ((best_rccal_val > 140)
- || (best_rccal_val < 135)) {
+ || (best_rccal_val < 135))
best_rccal_val = 138;
- }
} else {
if ((best_rccal_val > 142)
- || (best_rccal_val < 137)) {
+ || (best_rccal_val < 137))
best_rccal_val = 140;
- }
}
write_radio_reg(pi,
@@ -25649,7 +27583,7 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
return best_rccal_val - 0x80;
}
-#define WAIT_FOR_SCOPE 4000
+#define WAIT_FOR_SCOPE 4000
static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
struct nphy_txgains target_gain,
u8 cal_type, bool debug)
@@ -25687,12 +27621,12 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
rxcore_state = wlc_phy_rxcore_getstate_nphy(
- (struct brcms_phy_pub *) pi);
+ (struct brcms_phy_pub *) pi);
for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
skip_rxiqcal =
- ((rxcore_state & (1 << rx_core)) == 0) ? true : false;
+ ((rxcore_state & (1 << rx_core)) == 0) ? true : false;
wlc_phy_rxcal_physetup_nphy(pi, rx_core);
@@ -25703,7 +27637,8 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0);
wlc_phy_tx_tone_nphy(pi,
- (CHSPEC_IS40(pi->radio_chanspec)) ?
+ (CHSPEC_IS40(
+ pi->radio_chanspec)) ?
NPHY_RXCAL_TONEFREQ_40MHz :
NPHY_RXCAL_TONEFREQ_20MHz,
NPHY_RXCAL_TONEAMP, 0, cal_type,
@@ -25721,23 +27656,21 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
if (rx_core == PHY_CORE_1) {
- if (rxcore_state == 1) {
+ if (rxcore_state == 1)
wlc_phy_rxcore_setstate_nphy(
(struct brcms_phy_pub *) pi, 3);
- }
wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL,
1);
best_rccal[rx_core] =
- wlc_phy_rc_sweep_nphy(pi, rx_core, 1);
+ wlc_phy_rc_sweep_nphy(pi, rx_core, 1);
pi->nphy_rccal_value = best_rccal[rx_core];
- if (rxcore_state == 1) {
+ if (rxcore_state == 1)
wlc_phy_rxcore_setstate_nphy(
(struct brcms_phy_pub *) pi,
rxcore_state);
- }
}
}
@@ -25756,18 +27689,22 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
rxlpf_rccal_hpc =
- (((int)best_rccal[rx_core] - 12) >> 1) + 10;
+ (((int)best_rccal[rx_core] - 12) >> 1) + 10;
txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10;
if (PHY_IPA(pi)) {
- txlpf_rccal_lpc += IS40MHZ(pi) ? 24 : 12;
- txlpf_idac = IS40MHZ(pi) ? 0x0e : 0x13;
+ txlpf_rccal_lpc +=
+ (pi->bw == WL_CHANSPEC_BW_40) ? 24 : 12;
+ txlpf_idac = (pi->bw == WL_CHANSPEC_BW_40) ?
+ 0x0e : 0x13;
WRITE_RADIO_REG2(pi, RADIO_2056, TX, rx_core,
TXLPF_IDAC_4, txlpf_idac);
}
- rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), 0);
- txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), 0);
+ rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31),
+ 0);
+ txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31),
+ 0);
write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC |
((rx_core ==
@@ -25787,21 +27724,21 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
wlc_phy_resetcca_nphy(pi);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_rxgain,
- 0, 0x3, 1);
- } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_rxgain,
+ 0, 0x3, 1);
+ else
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
- }
+
wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
gain_save);
- if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 4))
pi->phyhang_avoid = phyhang_avoid_state;
- }
wlc_phy_stay_in_carriersearch_nphy(pi, false);
@@ -25835,10 +27772,8 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
wlc_phy_stay_in_carriersearch_nphy(pi, true);
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
+ if (NREV_LT(pi->pubpi.phy_rev, 2))
wlc_phy_reapply_txcal_coeffs_nphy(pi);
- }
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
@@ -25874,19 +27809,16 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
((0x1 << 1) | (0x1 << 2)));
or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2)));
- if (((pi->nphy_rxcalparams) & 0xff000000)) {
-
+ if (((pi->nphy_rxcalparams) & 0xff000000))
write_phy_reg(pi,
(rx_core == PHY_CORE_0) ? 0x91 : 0x92,
- (CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 :
- 0x110));
- } else {
-
+ (CHSPEC_IS5G(pi->radio_chanspec) ?
+ 0x140 : 0x110));
+ else
write_phy_reg(pi,
(rx_core == PHY_CORE_0) ? 0x91 : 0x92,
- (CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 :
- 0x120));
- }
+ (CHSPEC_IS5G(pi->radio_chanspec) ?
+ 0x180 : 0x120));
write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92,
(CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 :
@@ -25926,7 +27858,7 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
use_hpf_num = 1;
curr_hpf = curr_hpf1;
actual_log2_pwr =
- wlc_phy_nbits(tot_pwr[2]);
+ wlc_phy_nbits(tot_pwr[2]);
} else {
if (tot_pwr[0] > 10000) {
curr_lna = lna_vals[1];
@@ -25935,7 +27867,8 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
use_hpf_num = 1;
curr_hpf = curr_hpf1;
actual_log2_pwr =
- wlc_phy_nbits(tot_pwr[1]);
+ wlc_phy_nbits(
+ tot_pwr[1]);
} else {
curr_lna = lna_vals[0];
curr_hpf1 = hpf1_vals[0];
@@ -25943,18 +27876,18 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
use_hpf_num = 2;
curr_hpf = curr_hpf2;
actual_log2_pwr =
- wlc_phy_nbits(tot_pwr[0]);
+ wlc_phy_nbits(
+ tot_pwr[0]);
}
}
hpf_change = desired_log2_pwr - actual_log2_pwr;
curr_hpf += hpf_change;
curr_hpf = max(min_t(u16, curr_hpf, 10), 0);
- if (use_hpf_num == 1) {
+ if (use_hpf_num == 1)
curr_hpf1 = curr_hpf;
- } else {
+ else
curr_hpf2 = curr_hpf;
- }
}
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10),
@@ -25967,15 +27900,12 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
if (first_playtone) {
bcmerror = wlc_phy_tx_tone_nphy(pi, 4000,
- (u16) (pi->
- nphy_rxcalparams
- &
- 0xffff),
- 0, 0, true);
+ (u16) (pi->nphy_rxcalparams &
+ 0xffff), 0, 0, true);
first_playtone = false;
} else {
- phy_bw =
- (CHSPEC_IS40(pi->radio_chanspec)) ? 40 : 20;
+ phy_bw = (CHSPEC_IS40(pi->radio_chanspec)) ?
+ 40 : 20;
wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff,
0, 0, 0, true);
}
@@ -25986,12 +27916,10 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
wlc_phy_rx_iq_est_nphy(pi, est,
num_samps, 32,
0);
- i_pwr =
- (est[rx_core].i_pwr +
- num_samps / 2) / num_samps;
- q_pwr =
- (est[rx_core].q_pwr +
- num_samps / 2) / num_samps;
+ i_pwr = (est[rx_core].i_pwr +
+ num_samps / 2) / num_samps;
+ q_pwr = (est[rx_core].q_pwr +
+ num_samps / 2) / num_samps;
tot_pwr[gain_pass] = i_pwr + q_pwr;
} else {
@@ -26038,1350 +27966,14 @@ int
wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
u8 cal_type, bool debug)
{
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
cal_type = 0;
- }
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type,
debug);
- } else {
+ else
return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug);
- }
-}
-
-static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
-{
- int j, type = 2;
- u16 addr_offset = 0x2c5;
-
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, addr_offset + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
- }
-}
-
-static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
-{
- int j, type;
- u16 addr_offset[] = { 0x186, 0x195,
- 0x2c5
- };
-
- for (type = 0; type < 3; type++) {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, addr_offset[type] + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
- }
- }
-
- if (IS40MHZ(pi)) {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, 0x186 + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
- }
- } else {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, 0x186 + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[5]
- [j]);
- }
- }
-
- if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, 0x2c5 + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[6]
- [j]);
- }
- }
- }
-}
-
-static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi)
-{
- int j;
-
- if (IS40MHZ(pi)) {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, 0x195 + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]);
- }
- } else {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, 0x186 + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
- }
- }
-}
-
-static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi)
-{
- u16 m0m1;
-
- wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
-
- return m0m1;
-}
-
-static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1)
-{
- u16 m0m1 = (u16) ((m0 << 8) | m1);
-
- wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1);
- wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1);
-}
-
-static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi)
-{
- u32 *tx_pwrctrl_tbl = NULL;
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- if ((pi->pubpi.radiorev == 4)
- || (pi->pubpi.radiorev == 6)) {
-
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_ipa_2g_2057rev4n6;
- } else if (pi->pubpi.radiorev == 3) {
-
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_ipa_2g_2057rev3;
- } else if (pi->pubpi.radiorev == 5) {
-
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_ipa_2g_2057rev5;
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_ipa_2g_2057rev7;
- }
-
- } else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
-
- tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
- } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-
- tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
- } else {
-
- tx_pwrctrl_tbl = nphy_tpc_txgain_ipa;
- }
-
- } else {
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
-
- tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057;
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_ipa_5g_2057rev7;
- }
-
- } else {
- tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g;
- }
- }
-
- return tx_pwrctrl_tbl;
-}
-
-static void
-wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi,
- struct nphy_papd_restore_state *state, u8 core)
-{
- s32 tone_freq;
- u8 off_core;
- u16 mixgain = 0;
-
- off_core = core ^ 0x1;
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- if (NREV_IS(pi->pubpi.phy_rev, 7)
- || NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
- wlc_phy_read_lpf_bw_ctl_nphy
- (pi, 0), 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (pi->pubpi.radiorev == 5) {
- mixgain = (core == 0) ? 0x20 : 0x00;
-
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- mixgain = 0x00;
-
- } else if ((pi->pubpi.radiorev <= 4)
- || (pi->pubpi.radiorev == 6)) {
-
- mixgain = 0x00;
- }
-
- } else {
- if ((pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
-
- mixgain = 0x50;
- } else if ((pi->pubpi.radiorev == 3)
- || (pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- mixgain = 0x0;
- }
- }
-
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
- mixgain, (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_tx_pu,
- 1, (1 << core), 0);
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_tx_pu,
- 0, (1 << off_core), 0);
-
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
- 0, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
- 0, (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
- state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
- 0xa6 : 0xa7);
- state->afeoverride[core] =
- read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
- state->afectrl[off_core] =
- read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6);
- state->afeoverride[off_core] =
- read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f);
-
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
- (0x1 << 2), 0);
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
- 0xa5), (0x1 << 2), (0x1 << 2));
-
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6),
- (0x1 << 2), (0x1 << 2));
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 :
- 0x8f), (0x1 << 2), (0x1 << 2));
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- state->pwrup[core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_PWRUP);
- state->atten[core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_ATTEN);
- state->pwrup[off_core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_2G_PWRUP);
- state->atten[off_core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_2G_ATTEN);
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_PWRUP, 0xc);
-
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_ATTEN, 0xf0);
-
- } else if (pi->pubpi.radiorev == 5) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_ATTEN,
- (core == 0) ? 0xf7 : 0xf2);
-
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_ATTEN, 0xf0);
-
- }
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_2G_PWRUP, 0x0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_2G_ATTEN, 0xff);
-
- } else {
- state->pwrup[core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_PWRUP);
- state->atten[core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_ATTEN);
- state->pwrup[off_core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_5G_PWRUP);
- state->atten[off_core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_5G_ATTEN);
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_PWRUP, 0xc);
-
- if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_ATTEN, 0xf4);
-
- } else {
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_ATTEN, 0xf0);
- }
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_5G_PWRUP, 0x0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_5G_ATTEN, 0xff);
- }
-
- tone_freq = 4000;
-
- wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (1) << 13);
-
- mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0);
-
- mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (0) << 13);
-
- } else {
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0);
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0);
-
- state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
- 0xa6 : 0xa7);
- state->afeoverride[core] =
- read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
-
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
- (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0);
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
- 0xa5),
- (0x1 << 0) |
- (0x1 << 1) |
- (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
-
- state->vga_master[core] =
- READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER);
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b);
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- state->fbmix[core] =
- READ_RADIO_REG2(pi, RADIO_2056, RX, core,
- TXFBMIX_G);
- state->intpa_master[core] =
- READ_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAG_MASTER);
-
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G,
- 0x03);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAG_MASTER, 0x04);
- } else {
- state->fbmix[core] =
- READ_RADIO_REG2(pi, RADIO_2056, RX, core,
- TXFBMIX_A);
- state->intpa_master[core] =
- READ_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAA_MASTER);
-
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A,
- 0x03);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAA_MASTER, 0x04);
-
- }
-
- tone_freq = 4000;
-
- wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (1) << 0);
-
- mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (0) << 0);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
- }
-}
-
-static void
-wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi,
- struct nphy_papd_restore_state *state)
-{
- u8 core;
-
- wlc_phy_stopplayback_nphy(pi);
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_PWRUP, 0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_ATTEN,
- state->atten[core]);
- } else {
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_PWRUP, 0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_ATTEN,
- state->atten[core]);
- }
- }
-
- if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
- 1, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- } else {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
- 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- }
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
- 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
- write_phy_reg(pi, (core == PHY_CORE_0) ?
- 0xa6 : 0xa7, state->afectrl[core]);
- write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
- 0xa5, state->afeoverride[core]);
- }
-
- wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
- (state->mm & 0xff));
-
- if (NREV_IS(pi->pubpi.phy_rev, 7)
- || NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
- 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- }
- } else {
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1);
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1);
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1);
-
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER,
- state->vga_master[core]);
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
- TXFBMIX_G, state->fbmix[core]);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAG_MASTER,
- state->intpa_master[core]);
- } else {
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
- TXFBMIX_A, state->fbmix[core]);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAA_MASTER,
- state->intpa_master[core]);
- }
-
- write_phy_reg(pi, (core == PHY_CORE_0) ?
- 0xa6 : 0xa7, state->afectrl[core]);
- write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
- 0xa5, state->afeoverride[core]);
- }
-
- wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
- (state->mm & 0xff));
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1);
- }
-}
-
-static void
-wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32 start,
- u32 end)
-{
- u32 *buf, *src, *dst, sz;
-
- sz = end - start + 1;
-
- buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC);
- if (NULL == buf) {
- return;
- }
-
- src = buf;
- dst = buf + NPHY_PAPD_EPS_TBL_SIZE;
-
- wlc_phy_table_read_nphy(pi,
- (core ==
- PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 :
- NPHY_TBL_ID_EPSILONTBL1),
- NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src);
-
- do {
- u32 phy_a1, phy_a2;
- s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7;
-
- phy_a1 = end - min(end, (winsz >> 1));
- phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, end + (winsz >> 1));
- phy_a3 = phy_a2 - phy_a1 + 1;
- phy_a6 = 0;
- phy_a7 = 0;
-
- do {
- wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4,
- &phy_a5);
- phy_a6 += phy_a4;
- phy_a7 += phy_a5;
- } while (phy_a2-- != phy_a1);
-
- phy_a6 /= phy_a3;
- phy_a7 /= phy_a3;
- dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff);
- } while (end-- != start);
-
- wlc_phy_table_write_nphy(pi,
- (core ==
- PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 :
- NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst);
-
- kfree(buf);
-}
-
-static void
-wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains,
- enum phy_cal_mode cal_mode, u8 core)
-{
- u16 phy_a1, phy_a2, phy_a3;
- u16 phy_a4, phy_a5;
- bool phy_a6;
- u8 phy_a7, m[2];
- u32 phy_a8 = 0;
- struct nphy_txgains phy_a9;
-
- if (NREV_LT(pi->pubpi.phy_rev, 3))
- return;
-
- phy_a7 = (core == PHY_CORE_0) ? 1 : 0;
-
- phy_a6 = ((cal_mode == CAL_GCTRL)
- || (cal_mode == CAL_SOFT)) ? true : false;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- phy_a9 = wlc_phy_get_tx_gain_nphy(pi);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- phy_a5 = ((phy_a9.txlpf[core] << 15) |
- (phy_a9.txgm[core] << 12) |
- (phy_a9.pga[core] << 8) |
- (txgains->gains.pad[core] << 3) |
- (phy_a9.ipa[core]));
- } else {
- phy_a5 = ((phy_a9.txlpf[core] << 15) |
- (phy_a9.txgm[core] << 12) |
- (txgains->gains.pga[core] << 8) |
- (phy_a9.pad[core] << 3) | (phy_a9.ipa[core]));
- }
-
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_txgain,
- phy_a5, (1 << core), 0);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if ((pi->pubpi.radiorev <= 4)
- || (pi->pubpi.radiorev == 6)) {
-
- m[core] = IS40MHZ(pi) ? 60 : 79;
- } else {
-
- m[core] = IS40MHZ(pi) ? 45 : 64;
- }
-
- } else {
- m[core] = IS40MHZ(pi) ? 75 : 107;
- }
-
- m[phy_a7] = 0;
- wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
-
- phy_a2 = 63;
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if ((pi->pubpi.radiorev == 4)
- || (pi->pubpi.radiorev == 6)) {
- phy_a1 = 30;
- phy_a3 = 30;
- } else {
- phy_a1 = 25;
- phy_a3 = 25;
- }
- } else {
- if ((pi->pubpi.radiorev == 5)
- || (pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
- phy_a1 = 25;
- phy_a3 = 25;
- } else {
- phy_a1 = 35;
- phy_a3 = 35;
- }
- }
-
- if (cal_mode == CAL_GCTRL) {
- if ((pi->pubpi.radiorev == 5)
- && (CHSPEC_IS2G(pi->radio_chanspec))) {
- phy_a1 = 55;
- } else if (((pi->pubpi.radiorev == 7) &&
- (CHSPEC_IS2G(pi->radio_chanspec))) ||
- ((pi->pubpi.radiorev == 8) &&
- (CHSPEC_IS2G(pi->radio_chanspec)))) {
- phy_a1 = 60;
- } else {
- phy_a1 = 63;
- }
-
- } else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) {
-
- phy_a1 = 35;
- phy_a3 = 35;
- }
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (1) << 0);
-
- mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (0) << 0);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (1) << 13);
-
- mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (0) << 13);
-
- write_phy_reg(pi, 0x2a1, 0x80);
- write_phy_reg(pi, 0x2a2, 0x100);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 4), (11) << 4);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 8), (11) << 8);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 0), (0x3) << 0);
-
- write_phy_reg(pi, 0x2e5, 0x20);
-
- mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
-
- mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
-
- mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
-
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
- 1, ((core == 0) ? 1 : 2), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
- 0, ((core == 0) ? 2 : 1), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
- write_phy_reg(pi, 0x2be, 1);
- SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
-
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
- 0, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
- wlc_phy_table_write_nphy(pi,
- (core ==
- PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
- : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
- 32, &phy_a8);
-
- if (cal_mode != CAL_GCTRL) {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- wlc_phy_a1_nphy(pi, core, 5, 0, 35);
- }
- }
-
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_txgain,
- phy_a5, (1 << core), 1);
-
- } else {
-
- if (txgains) {
- if (txgains->useindex) {
- phy_a4 = 15 - ((txgains->index) >> 3);
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (NREV_GE(pi->pubpi.phy_rev, 6))
- phy_a5 = 0x00f7 | (phy_a4 << 8);
-
- else
- if (NREV_IS(pi->pubpi.phy_rev, 5))
- phy_a5 = 0x10f7 | (phy_a4 << 8);
- else
- phy_a5 = 0x50f7 | (phy_a4 << 8);
- } else {
- phy_a5 = 0x70f7 | (phy_a4 << 8);
- }
- wlc_phy_rfctrl_override_nphy(pi,
- (0x1 << 13),
- phy_a5,
- (1 << core), 0);
- } else {
- wlc_phy_rfctrl_override_nphy(pi,
- (0x1 << 13),
- 0x5bf7,
- (1 << core), 0);
- }
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- m[core] = IS40MHZ(pi) ? 45 : 64;
- } else {
- m[core] = IS40MHZ(pi) ? 75 : 107;
- }
-
- m[phy_a7] = 0;
- wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
-
- phy_a2 = 63;
-
- if (cal_mode == CAL_FULL) {
- phy_a1 = 25;
- phy_a3 = 25;
- } else if (cal_mode == CAL_SOFT) {
- phy_a1 = 25;
- phy_a3 = 25;
- } else if (cal_mode == CAL_GCTRL) {
- phy_a1 = 63;
- phy_a3 = 25;
- } else {
-
- phy_a1 = 25;
- phy_a3 = 25;
- }
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (1) << 0);
-
- mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (0) << 0);
-
- if (NREV_GE(pi->pubpi.phy_rev, 6)) {
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (1) << 13);
-
- mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (0) << 13);
-
- write_phy_reg(pi, 0x2a1, 0x20);
- write_phy_reg(pi, 0x2a2, 0x60);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0xf << 4), (9) << 4);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0xf << 8), (9) << 8);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0xf << 0), (0x2) << 0);
-
- write_phy_reg(pi, 0x2e5, 0x20);
- } else {
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 11), (1) << 11);
-
- mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 11), (0) << 11);
-
- write_phy_reg(pi, 0x2a1, 0x80);
- write_phy_reg(pi, 0x2a2, 0x600);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 4), (0) << 4);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 8), (0) << 8);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 0), (0x3) << 0);
-
- mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8);
-
- }
-
- mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
-
- mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
-
- mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0);
-
- write_phy_reg(pi, 0x2be, 1);
- SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
-
- wlc_phy_table_write_nphy(pi,
- (core ==
- PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
- : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
- 32, &phy_a8);
-
- if (cal_mode != CAL_GCTRL) {
- wlc_phy_a1_nphy(pi, core, 5, 0, 40);
- }
- }
-}
-
-static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core)
-{
- int phy_a1;
- int phy_a2;
- bool phy_a3;
- struct nphy_ipa_txcalgains phy_a4;
- bool phy_a5 = false;
- bool phy_a6 = true;
- s32 phy_a7, phy_a8;
- u32 phy_a9;
- int phy_a10;
- bool phy_a11 = false;
- int phy_a12;
- u8 phy_a13 = 0;
- u8 phy_a14;
- u8 *phy_a15 = NULL;
-
- phy_a4.useindex = true;
- phy_a12 = start_gain;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- phy_a2 = 20;
- phy_a1 = 1;
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (pi->pubpi.radiorev == 5) {
-
- phy_a15 = pad_gain_codes_used_2057rev5;
- phy_a13 = sizeof(pad_gain_codes_used_2057rev5) /
- sizeof(pad_gain_codes_used_2057rev5[0]) - 1;
-
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- phy_a15 = pad_gain_codes_used_2057rev7;
- phy_a13 = sizeof(pad_gain_codes_used_2057rev7) /
- sizeof(pad_gain_codes_used_2057rev7[0]) - 1;
-
- } else {
-
- phy_a15 = pad_all_gain_codes_2057;
- phy_a13 = sizeof(pad_all_gain_codes_2057) /
- sizeof(pad_all_gain_codes_2057[0]) - 1;
- }
-
- } else {
-
- phy_a15 = pga_all_gain_codes_2057;
- phy_a13 = sizeof(pga_all_gain_codes_2057) /
- sizeof(pga_all_gain_codes_2057[0]) - 1;
- }
-
- phy_a14 = 0;
-
- for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- phy_a4.gains.pad[core] =
- (u16) phy_a15[phy_a12];
- } else {
- phy_a4.gains.pga[core] =
- (u16) phy_a15[phy_a12];
- }
-
- wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
-
- wlc_phy_table_read_nphy(pi,
- (core ==
- PHY_CORE_0 ?
- NPHY_TBL_ID_EPSILONTBL0 :
- NPHY_TBL_ID_EPSILONTBL1), 1,
- 63, 32, &phy_a9);
-
- wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
-
- phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
- (phy_a8 == 4095) || (phy_a8 == -4096));
-
- if (!phy_a6 && (phy_a3 != phy_a5)) {
- if (!phy_a3) {
- phy_a12 -= (u8) phy_a1;
- }
- phy_a11 = true;
- break;
- }
-
- if (phy_a3)
- phy_a12 += (u8) phy_a1;
- else
- phy_a12 -= (u8) phy_a1;
-
- if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) {
- if (phy_a12 < phy_a14) {
- phy_a12 = phy_a14;
- } else {
- phy_a12 = phy_a13;
- }
- phy_a11 = true;
- break;
- }
-
- phy_a6 = false;
- phy_a5 = phy_a3;
- }
-
- } else {
- phy_a2 = 10;
- phy_a1 = 8;
- for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
- phy_a4.index = (u8) phy_a12;
- wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
-
- wlc_phy_table_read_nphy(pi,
- (core ==
- PHY_CORE_0 ?
- NPHY_TBL_ID_EPSILONTBL0 :
- NPHY_TBL_ID_EPSILONTBL1), 1,
- 63, 32, &phy_a9);
-
- wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
-
- phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
- (phy_a8 == 4095) || (phy_a8 == -4096));
-
- if (!phy_a6 && (phy_a3 != phy_a5)) {
- if (!phy_a3) {
- phy_a12 -= (u8) phy_a1;
- }
- phy_a11 = true;
- break;
- }
-
- if (phy_a3)
- phy_a12 += (u8) phy_a1;
- else
- phy_a12 -= (u8) phy_a1;
-
- if ((phy_a12 < 0) || (phy_a12 > 127)) {
- if (phy_a12 < 0) {
- phy_a12 = 0;
- } else {
- phy_a12 = 127;
- }
- phy_a11 = true;
- break;
- }
-
- phy_a6 = false;
- phy_a5 = phy_a3;
- }
-
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- return (u8) phy_a15[phy_a12];
- } else {
- return (u8) phy_a12;
- }
-
-}
-
-static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal)
-{
- struct nphy_ipa_txcalgains phy_b1[2];
- struct nphy_papd_restore_state phy_b2;
- bool phy_b3;
- u8 phy_b4;
- u8 phy_b5;
- s16 phy_b6, phy_b7, phy_b8;
- u16 phy_b9;
- s16 phy_b10, phy_b11, phy_b12;
-
- phy_b11 = 0;
- phy_b12 = 0;
- phy_b7 = 0;
- phy_b8 = 0;
- phy_b6 = 0;
-
- if (pi->nphy_papd_skip == 1)
- return;
-
- phy_b3 =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
- if (!phy_b3) {
- wlapi_suspend_mac_and_wait(pi->sh->physhim);
- }
-
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- pi->nphy_force_papd_cal = false;
-
- for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++)
- pi->nphy_papd_tx_gain_at_last_cal[phy_b5] =
- wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5);
-
- pi->nphy_papd_last_cal = pi->sh->now;
- pi->nphy_papd_recal_counter++;
-
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
- phy_b4 = pi->nphy_txpwrctrl;
- wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32,
- nphy_papd_scaltbl);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32,
- nphy_papd_scaltbl);
-
- phy_b9 = read_phy_reg(pi, 0x01);
- mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
-
- for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
- s32 i, val = 0;
- for (i = 0; i < 64; i++) {
- wlc_phy_table_write_nphy(pi,
- ((phy_b5 ==
- PHY_CORE_0) ?
- NPHY_TBL_ID_EPSILONTBL0 :
- NPHY_TBL_ID_EPSILONTBL1), 1,
- i, 32, &val);
- }
- }
-
- wlc_phy_ipa_restore_tx_digi_filts_nphy(pi);
-
- phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi);
- for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
- wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5);
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
- if ((pi->pubpi.radiorev == 3)
- || (pi->pubpi.radiorev == 4)
- || (pi->pubpi.radiorev == 6)) {
-
- pi->nphy_papd_cal_gain_index[phy_b5] =
- 23;
-
- } else if (pi->pubpi.radiorev == 5) {
-
- pi->nphy_papd_cal_gain_index[phy_b5] =
- 0;
- pi->nphy_papd_cal_gain_index[phy_b5] =
- wlc_phy_a3_nphy(pi,
- pi->
- nphy_papd_cal_gain_index
- [phy_b5], phy_b5);
-
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- pi->nphy_papd_cal_gain_index[phy_b5] =
- 0;
- pi->nphy_papd_cal_gain_index[phy_b5] =
- wlc_phy_a3_nphy(pi,
- pi->
- nphy_papd_cal_gain_index
- [phy_b5], phy_b5);
-
- }
-
- phy_b1[phy_b5].gains.pad[phy_b5] =
- pi->nphy_papd_cal_gain_index[phy_b5];
-
- } else {
- pi->nphy_papd_cal_gain_index[phy_b5] = 0;
- pi->nphy_papd_cal_gain_index[phy_b5] =
- wlc_phy_a3_nphy(pi,
- pi->
- nphy_papd_cal_gain_index
- [phy_b5], phy_b5);
- phy_b1[phy_b5].gains.pga[phy_b5] =
- pi->nphy_papd_cal_gain_index[phy_b5];
- }
- } else {
- phy_b1[phy_b5].useindex = true;
- phy_b1[phy_b5].index = 16;
- phy_b1[phy_b5].index =
- wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index, phy_b5);
-
- pi->nphy_papd_cal_gain_index[phy_b5] =
- 15 - ((phy_b1[phy_b5].index) >> 3);
- }
-
- switch (pi->nphy_papd_cal_type) {
- case 0:
- wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5);
- break;
- case 1:
- wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5);
- break;
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
- }
- }
-
- if (NREV_LT(pi->pubpi.phy_rev, 7)) {
- wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
- }
-
- for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
- int eps_offset = 0;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (pi->pubpi.radiorev == 3) {
- eps_offset = -2;
- } else if (pi->pubpi.radiorev == 5) {
- eps_offset = 3;
- } else {
- eps_offset = -1;
- }
- } else {
- eps_offset = 2;
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5];
- phy_b10 = 0;
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
- phy_b12 =
- -
- (nphy_papd_padgain_dlt_2g_2057rev3n4
- [phy_b8]
- + 1) / 2;
- phy_b10 = -1;
- } else if (pi->pubpi.radiorev == 5) {
- phy_b12 =
- -(nphy_papd_padgain_dlt_2g_2057rev5
- [phy_b8]
- + 1) / 2;
- } else if ((pi->pubpi.radiorev == 7) ||
- (pi->pubpi.radiorev == 8)) {
- phy_b12 =
- -(nphy_papd_padgain_dlt_2g_2057rev7
- [phy_b8]
- + 1) / 2;
- }
- } else {
- phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5];
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
- phy_b11 =
- -(nphy_papd_pgagain_dlt_5g_2057
- [phy_b7]
- + 1) / 2;
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
- phy_b11 =
- -(nphy_papd_pgagain_dlt_5g_2057rev7
- [phy_b7]
- + 1) / 2;
- }
-
- phy_b10 = -9;
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- phy_b6 =
- -60 + 27 + eps_offset + phy_b12 + phy_b10;
- } else {
- phy_b6 =
- -60 + 27 + eps_offset + phy_b11 + phy_b10;
- }
-
- mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
- 0x29c, (0x1ff << 7), (phy_b6) << 7);
-
- pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
- } else {
- if (NREV_LT(pi->pubpi.phy_rev, 5)) {
- eps_offset = 4;
- } else {
- eps_offset = 2;
- }
-
- phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- phy_b11 =
- -(nphy_papd_pga_gain_delta_ipa_2g[phy_b7] +
- 1) / 2;
- phy_b10 = 0;
- } else {
- phy_b11 =
- -(nphy_papd_pga_gain_delta_ipa_5g[phy_b7] +
- 1) / 2;
- phy_b10 = -9;
- }
-
- phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10;
-
- mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
- 0x29c, (0x1ff << 7), (phy_b6) << 7);
-
- pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
- }
- }
-
- mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
- mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
- if (NREV_GE(pi->pubpi.phy_rev, 6)) {
- mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (0) << 13);
-
- mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (0) << 13);
-
- } else {
- mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 11), (0) << 11);
-
- mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 11), (0) << 11);
-
- }
- pi->nphy_papdcomp = NPHY_PAPD_COMP_ON;
-
- write_phy_reg(pi, 0x01, phy_b9);
-
- wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
-
- wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4);
- if (phy_b4 == PHY_TPC_HW_OFF) {
- wlc_phy_txpwr_index_nphy(pi, (1 << 0),
- (s8) (pi->nphy_txpwrindex[0].
- index_internal), false);
- wlc_phy_txpwr_index_nphy(pi, (1 << 1),
- (s8) (pi->nphy_txpwrindex[1].
- index_internal), false);
- }
-
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
- if (!phy_b3) {
- wlapi_enable_mac(pi->sh->physhim);
- }
}
void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
@@ -27423,11 +28015,10 @@ void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
}
}
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
txpi[0] = txpi[1] = 30;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ else if (NREV_GE(pi->pubpi.phy_rev, 3))
txpi[0] = txpi[1] = 40;
- }
if (NREV_LT(pi->pubpi.phy_rev, 7)) {
@@ -27447,37 +28038,36 @@ void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
if (NREV_GE(phyrev, 3)) {
if (PHY_IPA(pi)) {
u32 *tx_gaintbl =
- wlc_phy_get_ipa_gaintbl_nphy(pi);
+ wlc_phy_get_ipa_gaintbl_nphy(pi);
txgain = tx_gaintbl[txpi[core]];
} else {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
if (NREV_IS(phyrev, 3)) {
txgain =
- nphy_tpc_5GHz_txgain_rev3
- [txpi[core]];
+ nphy_tpc_5GHz_txgain_rev3
+ [txpi[core]];
} else if (NREV_IS(phyrev, 4)) {
- txgain =
- (pi->srom_fem5g.extpagain ==
- 3) ?
- nphy_tpc_5GHz_txgain_HiPwrEPA
- [txpi[core]] :
- nphy_tpc_5GHz_txgain_rev4
- [txpi[core]];
+ txgain = (
+ pi->srom_fem5g.extpagain ==
+ 3) ?
+ nphy_tpc_5GHz_txgain_HiPwrEPA
+ [txpi[core]] :
+ nphy_tpc_5GHz_txgain_rev4
+ [txpi[core]];
} else {
txgain =
- nphy_tpc_5GHz_txgain_rev5
- [txpi[core]];
+ nphy_tpc_5GHz_txgain_rev5
+ [txpi[core]];
}
} else {
if (NREV_GE(phyrev, 5) &&
(pi->srom_fem2g.extpagain == 3)) {
txgain =
- nphy_tpc_txgain_HiPwrEPA
- [txpi[core]];
+ nphy_tpc_txgain_HiPwrEPA
+ [txpi[core]];
} else {
- txgain =
- nphy_tpc_txgain_rev3[txpi
- [core]];
+ txgain = nphy_tpc_txgain_rev3
+ [txpi[core]];
}
}
}
@@ -27497,12 +28087,12 @@ void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
- if (NREV_GE(phyrev, 3)) {
+ if (NREV_GE(phyrev, 3))
mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
0xa5), (0x1 << 8), (0x1 << 8));
- } else {
+ else
mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
- }
+
write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain);
wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
@@ -27562,9 +28152,8 @@ wlc_phy_txpwr_nphy_po_apply(u8 *srom_max, u8 pwr_offset,
{
u8 rate;
- for (rate = rate_start; rate <= rate_end; rate++) {
+ for (rate = rate_start; rate <= rate_end; rate++)
srom_max[rate] -= 2 * pwr_offset;
- }
}
void
@@ -27603,7 +28192,8 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
u16 pwr_offsets1[2], *pwr_offsets2 = NULL;
u8 *tx_srom_max_rate = NULL;
- for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
+ for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP);
+ band_num++) {
switch (band_num) {
case 0:
@@ -27619,7 +28209,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
pwr_offsets1[0] = (u16) (pi->ofdm2gpo & 0xffff);
pwr_offsets1[1] =
- (u16) (pi->ofdm2gpo >> 16) & 0xffff;
+ (u16) (pi->ofdm2gpo >> 16) & 0xffff;
pwr_offsets2 = pi->mcs2gpo;
@@ -27636,7 +28226,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
pwr_offsets1[0] = (u16) (pi->ofdm5gpo & 0xffff);
pwr_offsets1[1] =
- (u16) (pi->ofdm5gpo >> 16) & 0xffff;
+ (u16) (pi->ofdm5gpo >> 16) & 0xffff;
pwr_offsets2 = pi->mcs5gpo;
@@ -27653,7 +28243,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
pwr_offsets1[0] = (u16) (pi->ofdm5glpo & 0xffff);
pwr_offsets1[1] =
- (u16) (pi->ofdm5glpo >> 16) & 0xffff;
+ (u16) (pi->ofdm5glpo >> 16) & 0xffff;
pwr_offsets2 = pi->mcs5glpo;
@@ -27670,7 +28260,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
pwr_offsets1[0] = (u16) (pi->ofdm5ghpo & 0xffff);
pwr_offsets1[1] =
- (u16) (pi->ofdm5ghpo >> 16) & 0xffff;
+ (u16) (pi->ofdm5ghpo >> 16) & 0xffff;
pwr_offsets2 = pi->mcs5ghpo;
@@ -27696,12 +28286,10 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
TXP_FIRST_MCS_20_CDD,
TXP_LAST_MCS_20_CDD);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
TXP_FIRST_MCS_20_CDD,
TXP_LAST_MCS_20_CDD);
- }
wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
TXP_FIRST_OFDM_20_CDD,
@@ -27713,13 +28301,11 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
TXP_FIRST_MCS_20_STBC,
TXP_LAST_MCS_20_STBC);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
tmp_stbcpo,
TXP_FIRST_MCS_20_STBC,
TXP_LAST_MCS_20_STBC);
- }
wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
&pwr_offsets2[2], tmp_max_pwr,
@@ -27773,294 +28359,26 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
} else {
for (rate1 = TXP_FIRST_OFDM_40_SISO, rate2 =
- TXP_FIRST_OFDM; rate1 <= TXP_LAST_MCS_40_SDM;
+ TXP_FIRST_OFDM;
+ rate1 <= TXP_LAST_MCS_40_SDM;
rate1++, rate2++)
tx_srom_max_rate[rate1] =
- tx_srom_max_rate[rate2];
+ tx_srom_max_rate[rate2];
}
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
tmp_bw40po,
TXP_FIRST_OFDM_40_SISO,
TXP_LAST_MCS_40_SDM);
- }
tx_srom_max_rate[TXP_MCS_32] =
- tx_srom_max_rate[TXP_FIRST_MCS_40_CDD];
+ tx_srom_max_rate[TXP_FIRST_MCS_40_CDD];
}
return;
}
-static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
-{
- u16 bw40po, cddpo, stbcpo, bwduppo;
- uint band_num;
-
- if (pi->sh->sromrev >= 9) {
-
- return;
- }
-
- bw40po = (u16) PHY_GETINTVAR(pi, "bw40po");
- pi->bw402gpo = bw40po & 0xf;
- pi->bw405gpo = (bw40po & 0xf0) >> 4;
- pi->bw405glpo = (bw40po & 0xf00) >> 8;
- pi->bw405ghpo = (bw40po & 0xf000) >> 12;
-
- cddpo = (u16) PHY_GETINTVAR(pi, "cddpo");
- pi->cdd2gpo = cddpo & 0xf;
- pi->cdd5gpo = (cddpo & 0xf0) >> 4;
- pi->cdd5glpo = (cddpo & 0xf00) >> 8;
- pi->cdd5ghpo = (cddpo & 0xf000) >> 12;
-
- stbcpo = (u16) PHY_GETINTVAR(pi, "stbcpo");
- pi->stbc2gpo = stbcpo & 0xf;
- pi->stbc5gpo = (stbcpo & 0xf0) >> 4;
- pi->stbc5glpo = (stbcpo & 0xf00) >> 8;
- pi->stbc5ghpo = (stbcpo & 0xf000) >> 12;
-
- bwduppo = (u16) PHY_GETINTVAR(pi, "bwduppo");
- pi->bwdup2gpo = bwduppo & 0xf;
- pi->bwdup5gpo = (bwduppo & 0xf0) >> 4;
- pi->bwdup5glpo = (bwduppo & 0xf00) >> 8;
- pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12;
-
- for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
- switch (band_num) {
- case 0:
-
- pi->nphy_txpid2g[PHY_CORE_0] =
- (u8) PHY_GETINTVAR(pi, "txpid2ga0");
- pi->nphy_txpid2g[PHY_CORE_1] =
- (u8) PHY_GETINTVAR(pi, "txpid2ga1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
- (s8) PHY_GETINTVAR(pi, "maxp2ga0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g =
- (s8) PHY_GETINTVAR(pi, "maxp2ga1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 =
- (s16) PHY_GETINTVAR(pi, "pa2gw0a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 =
- (s16) PHY_GETINTVAR(pi, "pa2gw0a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 =
- (s16) PHY_GETINTVAR(pi, "pa2gw1a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 =
- (s16) PHY_GETINTVAR(pi, "pa2gw1a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 =
- (s16) PHY_GETINTVAR(pi, "pa2gw2a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 =
- (s16) PHY_GETINTVAR(pi, "pa2gw2a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g =
- (s8) PHY_GETINTVAR(pi, "itt2ga0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g =
- (s8) PHY_GETINTVAR(pi, "itt2ga1");
-
- pi->cck2gpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
-
- pi->ofdm2gpo = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
-
- pi->mcs2gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
- pi->mcs2gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs2gpo1");
- pi->mcs2gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs2gpo2");
- pi->mcs2gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs2gpo3");
- pi->mcs2gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs2gpo4");
- pi->mcs2gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs2gpo5");
- pi->mcs2gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs2gpo6");
- pi->mcs2gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs2gpo7");
- break;
- case 1:
-
- pi->nphy_txpid5g[PHY_CORE_0] =
- (u8) PHY_GETINTVAR(pi, "txpid5ga0");
- pi->nphy_txpid5g[PHY_CORE_1] =
- (u8) PHY_GETINTVAR(pi, "txpid5ga1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
- (s8) PHY_GETINTVAR(pi, "maxp5ga0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
- (s8) PHY_GETINTVAR(pi, "maxp5ga1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5gw0a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5gw0a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5gw1a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5gw1a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5gw2a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5gw2a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm =
- (s8) PHY_GETINTVAR(pi, "itt5ga0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm =
- (s8) PHY_GETINTVAR(pi, "itt5ga1");
-
- pi->ofdm5gpo = (u32) PHY_GETINTVAR(pi, "ofdm5gpo");
-
- pi->mcs5gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs5gpo0");
- pi->mcs5gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs5gpo1");
- pi->mcs5gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs5gpo2");
- pi->mcs5gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs5gpo3");
- pi->mcs5gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs5gpo4");
- pi->mcs5gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs5gpo5");
- pi->mcs5gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs5gpo6");
- pi->mcs5gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs5gpo7");
- break;
- case 2:
-
- pi->nphy_txpid5gl[0] =
- (u8) PHY_GETINTVAR(pi, "txpid5gla0");
- pi->nphy_txpid5gl[1] =
- (u8) PHY_GETINTVAR(pi, "txpid5gla1");
- pi->nphy_pwrctrl_info[0].max_pwr_5gl =
- (s8) PHY_GETINTVAR(pi, "maxp5gla0");
- pi->nphy_pwrctrl_info[1].max_pwr_5gl =
- (s8) PHY_GETINTVAR(pi, "maxp5gla1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5glw0a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5glw0a1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5glw1a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5glw1a1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5glw2a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5glw2a1");
- pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0;
- pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0;
-
- pi->ofdm5glpo = (u32) PHY_GETINTVAR(pi, "ofdm5glpo");
-
- pi->mcs5glpo[0] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo0");
- pi->mcs5glpo[1] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo1");
- pi->mcs5glpo[2] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo2");
- pi->mcs5glpo[3] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo3");
- pi->mcs5glpo[4] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo4");
- pi->mcs5glpo[5] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo5");
- pi->mcs5glpo[6] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo6");
- pi->mcs5glpo[7] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo7");
- break;
- case 3:
-
- pi->nphy_txpid5gh[0] =
- (u8) PHY_GETINTVAR(pi, "txpid5gha0");
- pi->nphy_txpid5gh[1] =
- (u8) PHY_GETINTVAR(pi, "txpid5gha1");
- pi->nphy_pwrctrl_info[0].max_pwr_5gh =
- (s8) PHY_GETINTVAR(pi, "maxp5gha0");
- pi->nphy_pwrctrl_info[1].max_pwr_5gh =
- (s8) PHY_GETINTVAR(pi, "maxp5gha1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw0a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw0a1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw1a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw1a1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw2a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw2a1");
- pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0;
- pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0;
-
- pi->ofdm5ghpo = (u32) PHY_GETINTVAR(pi, "ofdm5ghpo");
-
- pi->mcs5ghpo[0] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo0");
- pi->mcs5ghpo[1] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo1");
- pi->mcs5ghpo[2] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo2");
- pi->mcs5ghpo[3] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo3");
- pi->mcs5ghpo[4] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo4");
- pi->mcs5ghpo[5] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo5");
- pi->mcs5ghpo[6] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo6");
- pi->mcs5ghpo[7] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo7");
- break;
- }
- }
-
- wlc_phy_txpwr_apply_nphy(pi);
-}
-
-static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi)
-{
-
- pi->antswitch = (u8) PHY_GETINTVAR(pi, "antswitch");
- pi->aa2g = (u8) PHY_GETINTVAR(pi, "aa2g");
- pi->aa5g = (u8) PHY_GETINTVAR(pi, "aa5g");
-
- pi->srom_fem2g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos2g");
- pi->srom_fem2g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain2g");
- pi->srom_fem2g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange2g");
- pi->srom_fem2g.triso = (u8) PHY_GETINTVAR(pi, "triso2g");
- pi->srom_fem2g.antswctrllut = (u8) PHY_GETINTVAR(pi, "antswctl2g");
-
- pi->srom_fem5g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos5g");
- pi->srom_fem5g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain5g");
- pi->srom_fem5g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange5g");
- pi->srom_fem5g.triso = (u8) PHY_GETINTVAR(pi, "triso5g");
- if (PHY_GETVAR(pi, "antswctl5g")) {
-
- pi->srom_fem5g.antswctrllut =
- (u8) PHY_GETINTVAR(pi, "antswctl5g");
- } else {
-
- pi->srom_fem5g.antswctrllut =
- (u8) PHY_GETINTVAR(pi, "antswctl2g");
- }
-
- wlc_phy_txpower_ipa_upd(pi);
-
- pi->phy_txcore_disable_temp = (s16) PHY_GETINTVAR(pi, "tempthresh");
- if (pi->phy_txcore_disable_temp == 0) {
- pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
- }
-
- pi->phy_tempsense_offset = (s8) PHY_GETINTVAR(pi, "tempoffset");
- if (pi->phy_tempsense_offset != 0) {
- if (pi->phy_tempsense_offset >
- (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) {
- pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET;
- } else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT +
- NPHY_SROM_MINTEMPOFFSET)) {
- pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET;
- } else {
- pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT;
- }
- }
-
- pi->phy_txcore_enable_temp =
- pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP;
-
- pi->phycal_tempdelta = (u8) PHY_GETINTVAR(pi, "phycal_tempdelta");
- if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) {
- pi->phycal_tempdelta = 0;
- }
-
- wlc_phy_txpwr_srom_read_ppr_nphy(pi);
-
- return true;
-}
-
void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi)
{
u8 tx_pwr_ctrl_state;
@@ -28081,512 +28399,10 @@ void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi)
wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
}
-static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi)
-{
- u32 idx;
- u16 iqloCalbuf[7];
- u32 iqcomp, locomp, curr_locomp;
- s8 locomp_i, locomp_q;
- s8 curr_locomp_i, curr_locomp_q;
- u32 tbl_id, tbl_len, tbl_offset;
- u32 regval[128];
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf);
-
- tbl_len = 128;
- tbl_offset = 320;
- for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
- tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
- iqcomp =
- (tbl_id ==
- 26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) |
- (iqloCalbuf[1] & 0x3ff)
- : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) |
- (iqloCalbuf[3] & 0x3ff);
-
- for (idx = 0; idx < tbl_len; idx++) {
- regval[idx] = iqcomp;
- }
- wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
- regval);
- }
-
- tbl_offset = 448;
- for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
- tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
-
- locomp =
- (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]);
- locomp_i = (s8) ((locomp >> 8) & 0xff);
- locomp_q = (s8) ((locomp) & 0xff);
- for (idx = 0; idx < tbl_len; idx++) {
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- curr_locomp_i = locomp_i;
- curr_locomp_q = locomp_q;
- } else {
- curr_locomp_i = (s8) ((locomp_i *
- nphy_tpc_loscale[idx] +
- 128) >> 8);
- curr_locomp_q =
- (s8) ((locomp_q * nphy_tpc_loscale[idx] +
- 128) >> 8);
- }
- curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8);
- curr_locomp |= (u32) (curr_locomp_q & 0xff);
- regval[idx] = curr_locomp;
- }
- wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
- regval);
- }
-
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
- wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF);
- wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF);
- }
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi)
-{
- u8 core;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MASTER, 0x5);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MUX, 0xe);
-
- if (pi->pubpi.radiorev != 5)
- WRITE_RADIO_REG3(pi, RADIO_2057, TX,
- core, TSSIA, 0);
-
- if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX,
- core, TSSIG, 0x1);
- } else {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX,
- core, TSSIG, 0x31);
- }
- } else {
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MASTER, 0x9);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MUX, 0xc);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TSSIG, 0);
-
- if (pi->pubpi.radiorev != 5) {
- if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057,
- TX, core,
- TSSIA, 0x1);
- } else {
-
- WRITE_RADIO_REG3(pi, RADIO_2057,
- TX, core,
- TSSIA, 0x31);
- }
- }
- }
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
- 0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
- 0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
- 0x3);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
- 0x0);
- }
- } else {
- WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31,
- (CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 :
- 0x80);
- WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0);
- WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29);
-
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG,
- 0x0);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC,
- 0x0);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM,
- 0x3);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET,
- 0x0);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1,
- 0x8);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2,
- 0x0);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3,
- 0x0);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TX_SSI_MASTER, 0x5);
-
- if (pi->pubpi.radiorev != 5)
- WRITE_RADIO_REG2(pi, RADIO_2056, TX,
- core, TSSIA, 0x0);
- if (NREV_GE(pi->pubpi.phy_rev, 5)) {
-
- WRITE_RADIO_REG2(pi, RADIO_2056, TX,
- core, TSSIG, 0x31);
- } else {
- WRITE_RADIO_REG2(pi, RADIO_2056, TX,
- core, TSSIG, 0x11);
- }
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TX_SSI_MUX, 0xe);
- } else {
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TX_SSI_MASTER, 0x9);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TSSIA, 0x31);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TSSIG, 0x0);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TX_SSI_MUX, 0xc);
- }
- }
- }
-}
-
-static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi)
-{
- s32 rssi_buf[4];
- s32 int_val;
-
- if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi))
-
- return;
-
- if (PHY_IPA(pi)) {
- wlc_phy_ipa_internal_tssi_setup_nphy(pi);
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
- 0, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0);
- }
-
- wlc_phy_stopplayback_nphy(pi);
-
- wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false);
-
- udelay(20);
- int_val =
- wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf,
- 1);
- wlc_phy_stopplayback_nphy(pi);
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0);
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
- 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1);
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
- (u8) ((int_val >> 24) & 0xff);
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
- (u8) ((int_val >> 24) & 0xff);
-
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
- (u8) ((int_val >> 8) & 0xff);
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
- (u8) ((int_val >> 8) & 0xff);
- } else {
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
- (u8) ((int_val >> 24) & 0xff);
-
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
- (u8) ((int_val >> 8) & 0xff);
-
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
- (u8) ((int_val >> 16) & 0xff);
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
- (u8) ((int_val) & 0xff);
- }
-
-}
-
-static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
-{
- u32 idx;
- s16 a1[2], b0[2], b1[2];
- s8 target_pwr_qtrdbm[2];
- s32 num, den, pwr_est;
- u8 chan_freq_range;
- u8 idle_tssi[2];
- u32 tbl_id, tbl_len, tbl_offset;
- u32 regval[64];
- u8 core;
-
- if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
- wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
- (void)R_REG(&pi->regs->maccontrol);
- udelay(1);
- }
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- or_phy_reg(pi, 0x122, (0x1 << 0));
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15)));
- } else {
-
- or_phy_reg(pi, 0x1e7, (0x1 << 15));
- }
-
- if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
- wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
-
- if (pi->sh->sromrev < 4) {
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
- target_pwr_qtrdbm[0] = 13 * 4;
- target_pwr_qtrdbm[1] = 13 * 4;
- a1[0] = -424;
- a1[1] = -424;
- b0[0] = 5612;
- b0[1] = 5612;
- b1[1] = -1393;
- b1[0] = -1393;
- } else {
-
- chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
- switch (chan_freq_range) {
- case WL_CHAN_FREQ_RANGE_2G:
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
- target_pwr_qtrdbm[0] =
- pi->nphy_pwrctrl_info[0].max_pwr_2g;
- target_pwr_qtrdbm[1] =
- pi->nphy_pwrctrl_info[1].max_pwr_2g;
- a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1;
- a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1;
- b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0;
- b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0;
- b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1;
- b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1;
- break;
- case WL_CHAN_FREQ_RANGE_5GL:
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
- target_pwr_qtrdbm[0] =
- pi->nphy_pwrctrl_info[0].max_pwr_5gl;
- target_pwr_qtrdbm[1] =
- pi->nphy_pwrctrl_info[1].max_pwr_5gl;
- a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1;
- a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1;
- b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0;
- b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0;
- b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1;
- b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1;
- break;
- case WL_CHAN_FREQ_RANGE_5GM:
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
- target_pwr_qtrdbm[0] =
- pi->nphy_pwrctrl_info[0].max_pwr_5gm;
- target_pwr_qtrdbm[1] =
- pi->nphy_pwrctrl_info[1].max_pwr_5gm;
- a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1;
- a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1;
- b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0;
- b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0;
- b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1;
- b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1;
- break;
- case WL_CHAN_FREQ_RANGE_5GH:
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
- target_pwr_qtrdbm[0] =
- pi->nphy_pwrctrl_info[0].max_pwr_5gh;
- target_pwr_qtrdbm[1] =
- pi->nphy_pwrctrl_info[1].max_pwr_5gh;
- a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1;
- a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1;
- b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0;
- b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0;
- b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1;
- b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1;
- break;
- default:
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
- target_pwr_qtrdbm[0] = 13 * 4;
- target_pwr_qtrdbm[1] = 13 * 4;
- a1[0] = -424;
- a1[1] = -424;
- b0[0] = 5612;
- b0[1] = 5612;
- b1[1] = -1393;
- b1[0] = -1393;
- break;
- }
- }
-
- target_pwr_qtrdbm[0] = (s8) pi->tx_power_max;
- target_pwr_qtrdbm[1] = (s8) pi->tx_power_max;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if (pi->srom_fem2g.tssipos) {
- or_phy_reg(pi, 0x1e9, (0x1 << 14));
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- for (core = 0; core <= 1; core++) {
- if (PHY_IPA(pi)) {
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- WRITE_RADIO_REG3(pi, RADIO_2057,
- TX, core,
- TX_SSI_MUX,
- 0xe);
- } else {
- WRITE_RADIO_REG3(pi, RADIO_2057,
- TX, core,
- TX_SSI_MUX,
- 0xc);
- }
- } else {
- }
- }
- } else {
- if (PHY_IPA(pi)) {
-
- write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
- RADIO_2056_TX0,
- (CHSPEC_IS5G
- (pi->
- radio_chanspec)) ? 0xc : 0xe);
- write_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX |
- RADIO_2056_TX1,
- (CHSPEC_IS5G
- (pi->
- radio_chanspec)) ? 0xc : 0xe);
- } else {
-
- write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
- RADIO_2056_TX0, 0x11);
- write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
- RADIO_2056_TX1, 0x11);
- }
- }
- }
-
- if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
- wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
- (void)R_REG(&pi->regs->maccontrol);
- udelay(1);
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- mod_phy_reg(pi, 0x1e7, (0x7f << 0),
- (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
- } else {
- mod_phy_reg(pi, 0x1e7, (0x7f << 0),
- (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- mod_phy_reg(pi, 0x222, (0xff << 0),
- (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
- } else if (NREV_GT(pi->pubpi.phy_rev, 1)) {
- mod_phy_reg(pi, 0x222, (0xff << 0),
- (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
- }
-
- if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
- wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
-
- write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0));
-
- write_phy_reg(pi, 0x1e9,
- (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8));
-
- write_phy_reg(pi, 0x1ea,
- (target_pwr_qtrdbm[0] << 0) |
- (target_pwr_qtrdbm[1] << 8));
-
- tbl_len = 64;
- tbl_offset = 0;
- for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
- tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
-
- for (idx = 0; idx < tbl_len; idx++) {
- num =
- 8 * (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx);
- den = 32768 + a1[tbl_id - 26] * idx;
- pwr_est = max(((4 * num + den / 2) / den), -8);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
- if (idx <=
- (uint) (31 - idle_tssi[tbl_id - 26] + 1))
- pwr_est =
- max(pwr_est,
- target_pwr_qtrdbm[tbl_id - 26] +
- 1);
- }
- regval[idx] = (u32) pwr_est;
- }
- wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
- regval);
- }
-
- wlc_phy_txpwr_limit_to_tbl_nphy(pi);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8,
- pi->adj_pwr_tbl_nphy);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8,
- pi->adj_pwr_tbl_nphy);
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
static bool wlc_phy_txpwr_ison_nphy(struct brcms_phy *pi)
{
return read_phy_reg((pi), 0x1e7) & ((0x1 << 15) |
- (0x1 << 14) | (0x1 << 13));
-}
-
-static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core)
-{
- u16 tmp;
- tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee));
-
- tmp = (tmp & (0x7f << 8)) >> 8;
- return (u8) tmp;
-}
-
-static void
-wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0, u8 idx1)
-{
- mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0);
-
- if (NREV_GT(pi->pubpi.phy_rev, 1))
- mod_phy_reg(pi, 0x222, (0xff << 0), idx1);
+ (0x1 << 14) | (0x1 << 13));
}
u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi)
@@ -28600,12 +28416,9 @@ u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi)
tmp = (pwr_idx[0] << 8) | pwr_idx[1];
} else {
- tmp =
- ((pi->nphy_txpwrindex[PHY_CORE_0].
- index_internal & 0xff) << 8) | (pi->
- nphy_txpwrindex
- [PHY_CORE_1].
- index_internal & 0xff);
+ tmp = ((pi->nphy_txpwrindex[PHY_CORE_0].index_internal & 0xff)
+ << 8) |
+ (pi->nphy_txpwrindex[PHY_CORE_1].index_internal & 0xff);
}
return tmp;
@@ -28618,13 +28431,12 @@ void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi)
|| (wlc_phy_txpwr_ison_nphy(pi)
&&
(((u32)
- ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) -
+ abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) -
pi->nphy_papd_tx_gain_at_last_cal[0]) >= 4)
|| ((u32)
- ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) -
- pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4))))) {
+ abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) -
+ pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4)))))
wlc_phy_a4(pi, true);
- }
}
void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
@@ -28655,32 +28467,29 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
for (core = 0; core < pi->pubpi.phy_corenum;
core++)
pi->nphy_txpwr_idx[core] =
- wlc_phy_txpwr_idx_cur_get_nphy(pi,
- (u8)
- core);
+ wlc_phy_txpwr_idx_cur_get_nphy(
+ pi,
+ (u8) core);
}
}
tbl_len = 84;
tbl_offset = 64;
- for (ctr = 0; ctr < tbl_len; ctr++) {
+ for (ctr = 0; ctr < tbl_len; ctr++)
regval[ctr] = 0;
- }
wlc_phy_table_write_nphy(pi, 26, tbl_len, tbl_offset, 16,
regval);
wlc_phy_table_write_nphy(pi, 27, tbl_len, tbl_offset, 16,
regval);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
and_phy_reg(pi, 0x1e7,
(u16) (~((0x1 << 15) |
- (0x1 << 14) | (0x1 << 13))));
- } else {
+ (0x1 << 14) | (0x1 << 13))));
+ else
and_phy_reg(pi, 0x1e7,
(u16) (~((0x1 << 14) | (0x1 << 13))));
- }
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
or_phy_reg(pi, 0x8f, (0x1 << 8));
@@ -28694,7 +28503,8 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
else if (NREV_LT(pi->pubpi.phy_rev, 2))
mod_phy_reg(pi, 0xdc, 0x00ff, 0x5a);
- if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
+ if (NREV_LT(pi->pubpi.phy_rev, 2) &&
+ pi->bw == WL_CHANSPEC_BW_40)
wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
MHF1_IQSWAP_WAR, BRCM_BAND_ALL);
@@ -28730,7 +28540,7 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
if ((pi->nphy_txpwr_idx[0] != 128)
- && (pi->nphy_txpwr_idx[1] != 128)) {
+ && (pi->nphy_txpwr_idx[1] != 128))
wlc_phy_txpwr_idx_cur_set_nphy(pi,
pi->
nphy_txpwr_idx
@@ -28738,7 +28548,6 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
pi->
nphy_txpwr_idx
[1]);
- }
}
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
@@ -28753,7 +28562,8 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
else if (NREV_LT(pi->pubpi.phy_rev, 2))
mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
- if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
+ if (NREV_LT(pi->pubpi.phy_rev, 2) &&
+ pi->bw == WL_CHANSPEC_BW_40)
wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
0x0, BRCM_BAND_ALL);
@@ -28799,17 +28609,14 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- if ((core_mask & (1 << core)) == 0) {
+ if ((core_mask & (1 << core)) == 0)
continue;
- }
txpwrctl_tbl = (core == PHY_CORE_0) ? 26 : 27;
if (txpwrindex < 0) {
- if (pi->nphy_txpwrindex[core].index < 0) {
-
+ if (pi->nphy_txpwrindex[core].index < 0)
continue;
- }
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
mod_phy_reg(pi, 0x8f,
@@ -28842,29 +28649,21 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
if (restore_cals) {
-
- wlc_phy_table_write_nphy(pi, 15, 2,
- (80 + 2 * core), 16,
- (void *)&pi->
- nphy_txpwrindex[core].
- iqcomp_a);
-
- wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
- 16,
- &pi->
- nphy_txpwrindex[core].
- locomp);
- wlc_phy_table_write_nphy(pi, 15, 1, (93 + core),
- 16,
- (void *)&pi->
- nphy_txpwrindex[core].
- locomp);
+ wlc_phy_table_write_nphy(
+ pi, 15, 2, (80 + 2 * core), 16,
+ &pi->nphy_txpwrindex[core].iqcomp_a);
+ wlc_phy_table_write_nphy(
+ pi, 15, 1, (85 + core), 16,
+ &pi->nphy_txpwrindex[core].locomp);
+ wlc_phy_table_write_nphy(
+ pi, 15, 1, (93 + core), 16,
+ &pi->nphy_txpwrindex[core].locomp);
}
wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
pi->nphy_txpwrindex[core].index_internal =
- pi->nphy_txpwrindex[core].index_internal_save;
+ pi->nphy_txpwrindex[core].index_internal_save;
} else {
if (pi->nphy_txpwrindex[core].index < 0) {
@@ -28879,14 +28678,13 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
AfectrlOverride);
} else {
pi->nphy_txpwrindex[core].
- AfectrlOverride =
- read_phy_reg(pi, 0xa5);
+ AfectrlOverride =
+ read_phy_reg(pi, 0xa5);
}
pi->nphy_txpwrindex[core].AfeCtrlDacGain =
- read_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0xaa : 0xab);
+ read_phy_reg(pi, (core == PHY_CORE_0) ?
+ 0xaa : 0xab);
wlc_phy_table_read_nphy(pi, 7, 1,
(0x110 + core), 16,
@@ -28898,23 +28696,23 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
&tmpval);
tmpval >>= ((core == PHY_CORE_0) ? 8 : 0);
tmpval &= 0xff;
- pi->nphy_txpwrindex[core].bbmult =
- (u8) tmpval;
+ pi->nphy_txpwrindex[core].bbmult = (u8) tmpval;
wlc_phy_table_read_nphy(pi, 15, 2,
(80 + 2 * core), 16,
- (void *)&pi->
+ &pi->
nphy_txpwrindex[core].
iqcomp_a);
wlc_phy_table_read_nphy(pi, 15, 1, (85 + core),
16,
- (void *)&pi->
+ &pi->
nphy_txpwrindex[core].
locomp);
pi->nphy_txpwrindex[core].index_internal_save =
- pi->nphy_txpwrindex[core].index_internal;
+ pi->nphy_txpwrindex[core].
+ index_internal;
}
tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
@@ -28927,22 +28725,22 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
(tx_ind0 + txpwrindex), 32,
&txgain);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- rad_gain =
- (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1);
- } else {
- rad_gain =
- (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1);
- }
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
+ rad_gain = (txgain >> 16) &
+ ((1 << (32 - 16 + 1)) - 1);
+ else
+ rad_gain = (txgain >> 16) &
+ ((1 << (28 - 16 + 1)) - 1);
+
dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
0xa5), (0x1 << 8), (0x1 << 8));
- } else {
+ else
mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
- }
+
write_phy_reg(pi, (core == PHY_CORE_0) ?
0xaa : 0xab, dac_gain);
@@ -28951,9 +28749,8 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
- m1m2 |=
- ((core ==
- PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0));
+ m1m2 |= ((core == PHY_CORE_0) ?
+ (bbmult << 8) : (bbmult << 0));
wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
@@ -28974,23 +28771,20 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
(lo_ind0 + txpwrindex), 32,
&locomp);
- if (restore_cals) {
+ if (restore_cals)
wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
16, &locomp);
- }
if (NREV_IS(pi->pubpi.phy_rev, 1))
wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
if (PHY_IPA(pi)) {
wlc_phy_table_read_nphy(pi,
- (core ==
- PHY_CORE_0 ?
- NPHY_TBL_ID_CORE1TXPWRCTL
- :
- NPHY_TBL_ID_CORE2TXPWRCTL),
- 1, 576 + txpwrindex, 32,
- &rfpwr_offset);
+ (core == PHY_CORE_0 ?
+ NPHY_TBL_ID_CORE1TXPWRCTL :
+ NPHY_TBL_ID_CORE2TXPWRCTL),
+ 1, 576 + txpwrindex, 32,
+ &rfpwr_offset);
mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
0x29b, (0x1ff << 4),
@@ -29046,7 +28840,7 @@ void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable)
if (enable) {
if (pi->nphy_deaf_count == 0) {
pi->classifier_state =
- wlc_phy_classifier_nphy(pi, 0, 0);
+ wlc_phy_classifier_nphy(pi, 0, 0);
wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
wlc_phy_clip_det_nphy(pi, 0, pi->clip_state);
wlc_phy_clip_det_nphy(pi, 1, clip_off);
@@ -29074,9 +28868,9 @@ void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode)
if (mode) {
if (pi->nphy_deaf_count == 0)
wlc_phy_stay_in_carriersearch_nphy(pi, true);
- } else {
- if (pi->nphy_deaf_count > 0)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
+ } else if (pi->nphy_deaf_count > 0) {
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
}
+
wlapi_enable_mac(pi->sh->physhim);
}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c b/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c
index 01ff0c8eb4b9..faf1ebe76068 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c
@@ -17,89 +17,95 @@
#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.
-*/
+ * 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.
-*/
+ * 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) {
+ if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000)
result = 0x7fffffff;
- } else {
+ 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.
-*/
+ * 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) {
+ if (op1 < 0 && op2 < 0 && result > 0)
result = 0x80000000;
- } else if (op1 > 0 && op2 > 0 && result < 0) {
+ 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.
-*/
+ * 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) {
+ if (temp > (s32) 0x7fff)
result = (s16) 0x7fff;
- } else if (temp < (s32) 0xffff8000) {
+ else if (temp < (s32) 0xffff8000)
result = (s16) 0xffff8000;
- } else {
+ 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.
-*/
+ * 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) {
+ if (temp > (s32) 0x7fff)
result = (s16) 0x7fff;
- } else if (temp < (s32) 0xffff8000) {
+ else if (temp < (s32) 0xffff8000)
result = (s16) 0xffff8000;
- } else {
+ 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.
-*/
+ * 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;
@@ -110,20 +116,21 @@ s32 qm_shl32(s32 op, int shift)
else if (shift < -31)
shift = -31;
if (shift >= 0) {
- for (i = 0; i < shift; i++) {
+ 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.
-*/
+ * 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;
@@ -134,29 +141,29 @@ s16 qm_shl16(s16 op, int shift)
else if (shift < -15)
shift = -15;
if (shift > 0) {
- for (i = 0; i < shift; i++) {
+ 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.
-*/
+ * 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
-*/
+ * 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;
@@ -208,28 +215,30 @@ static const s16 log_table[] = {
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 */
+#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.
-*/
+ * 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;
@@ -248,12 +257,13 @@ void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
*/
qN = qN + s16norm - 30;
- /* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the MSB */
+ /* 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);
+ 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);
@@ -263,23 +273,27 @@ void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16)));
/* look the log value in the table. */
- s32log = log_table[s16tableIndex]; /* q.15 format */
+ s32log = log_table[s16tableIndex]; /* q.15 format */
- /* interpolate using the offset. */
- s16errorApproximation = (s16) qm_mulu16(u16offset, (u16) (log_table[s16tableIndex + 1] - log_table[s16tableIndex])); /* q.15 */
+ /* interpolate using the offset. q.15 format. */
+ s16errorApproximation = (s16) qm_mulu16(u16offset,
+ (u16) (log_table[s16tableIndex + 1] -
+ log_table[s16tableIndex]));
- s32log = qm_add16((s16) s32log, s16errorApproximation); /* q.15 format */
+ /* 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 */
+ 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 */
- s32log = qm_shl32(s32log, s16norm - 16); /* q.15+s16norm-16 format */
+ /* 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)
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c
index 023d05aa97ad..622c01ca72c5 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c
@@ -17,7 +17,7 @@
#include <types.h>
#include "phytbl_lcn.h"
-const u32 dot11lcn_gain_tbl_rev0[] = {
+static const u32 dot11lcn_gain_tbl_rev0[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -116,7 +116,7 @@ const u32 dot11lcn_gain_tbl_rev0[] = {
0x00000000,
};
-const u32 dot11lcn_gain_tbl_rev1[] = {
+static const u32 dot11lcn_gain_tbl_rev1[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -215,7 +215,7 @@ const u32 dot11lcn_gain_tbl_rev1[] = {
0x00000000,
};
-const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = {
+static const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = {
0x0401,
0x0402,
0x0403,
@@ -256,7 +256,7 @@ const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = {
0x0000,
};
-const u32 dot11lcn_gain_idx_tbl_rev0[] = {
+static const u32 dot11lcn_gain_idx_tbl_rev0[] = {
0x00000000,
0x00000000,
0x10000000,
@@ -407,7 +407,7 @@ const u32 dot11lcn_gain_idx_tbl_rev0[] = {
0x0000001c,
};
-const u16 dot11lcn_aux_gain_idx_tbl_2G[] = {
+static const u16 dot11lcn_aux_gain_idx_tbl_2G[] = {
0x0000,
0x0000,
0x0000,
@@ -448,7 +448,7 @@ const u16 dot11lcn_aux_gain_idx_tbl_2G[] = {
0x0000
};
-const u8 dot11lcn_gain_val_tbl_2G[] = {
+static const u8 dot11lcn_gain_val_tbl_2G[] = {
0xfc,
0x02,
0x08,
@@ -519,7 +519,7 @@ const u8 dot11lcn_gain_val_tbl_2G[] = {
0x00
};
-const u32 dot11lcn_gain_idx_tbl_2G[] = {
+static const u32 dot11lcn_gain_idx_tbl_2G[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -674,7 +674,7 @@ const u32 dot11lcn_gain_idx_tbl_2G[] = {
0x00000000
};
-const u32 dot11lcn_gain_tbl_2G[] = {
+static const u32 dot11lcn_gain_tbl_2G[] = {
0x00000000,
0x00000004,
0x00000008,
@@ -773,7 +773,7 @@ const u32 dot11lcn_gain_tbl_2G[] = {
0x00000000
};
-const u32 dot11lcn_gain_tbl_extlna_2G[] = {
+static const u32 dot11lcn_gain_tbl_extlna_2G[] = {
0x00000000,
0x00000004,
0x00000008,
@@ -872,7 +872,7 @@ const u32 dot11lcn_gain_tbl_extlna_2G[] = {
0x00000000
};
-const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = {
+static const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = {
0x0400,
0x0400,
0x0400,
@@ -913,7 +913,7 @@ const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = {
0x0000
};
-const u8 dot11lcn_gain_val_tbl_extlna_2G[] = {
+static const u8 dot11lcn_gain_val_tbl_extlna_2G[] = {
0xfc,
0x02,
0x08,
@@ -984,7 +984,7 @@ const u8 dot11lcn_gain_val_tbl_extlna_2G[] = {
0x00
};
-const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = {
+static const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = {
0x00000000,
0x00000040,
0x00000000,
@@ -1139,7 +1139,7 @@ const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = {
0x00000000
};
-const u32 dot11lcn_aux_gain_idx_tbl_5G[] = {
+static const u32 dot11lcn_aux_gain_idx_tbl_5G[] = {
0x0000,
0x0000,
0x0000,
@@ -1180,7 +1180,7 @@ const u32 dot11lcn_aux_gain_idx_tbl_5G[] = {
0x0000
};
-const u32 dot11lcn_gain_val_tbl_5G[] = {
+static const u32 dot11lcn_gain_val_tbl_5G[] = {
0xf7,
0xfd,
0x00,
@@ -1251,7 +1251,7 @@ const u32 dot11lcn_gain_val_tbl_5G[] = {
0x00
};
-const u32 dot11lcn_gain_idx_tbl_5G[] = {
+static const u32 dot11lcn_gain_idx_tbl_5G[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -1406,7 +1406,7 @@ const u32 dot11lcn_gain_idx_tbl_5G[] = {
0x00000000
};
-const u32 dot11lcn_gain_tbl_5G[] = {
+static const u32 dot11lcn_gain_tbl_5G[] = {
0x00000000,
0x00000040,
0x00000080,
@@ -1520,7 +1520,7 @@ const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[] = {
,
};
-const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev1[] = {
+static const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev1[] = {
{&dot11lcn_gain_tbl_rev1,
sizeof(dot11lcn_gain_tbl_rev1) / sizeof(dot11lcn_gain_tbl_rev1[0]), 18,
0, 32}
@@ -1611,10 +1611,6 @@ const u32 dot11lcnphytbl_rx_gain_info_sz_rev0 =
sizeof(dot11lcnphytbl_rx_gain_info_rev0) /
sizeof(dot11lcnphytbl_rx_gain_info_rev0[0]);
-const u32 dot11lcnphytbl_rx_gain_info_sz_rev1 =
- sizeof(dot11lcnphytbl_rx_gain_info_rev1) /
- sizeof(dot11lcnphytbl_rx_gain_info_rev1[0]);
-
const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz =
sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2) /
sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2[0]);
@@ -1623,7 +1619,7 @@ const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz =
sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2) /
sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2[0]);
-const u16 dot11lcn_min_sig_sq_tbl_rev0[] = {
+static const u16 dot11lcn_min_sig_sq_tbl_rev0[] = {
0x014d,
0x014d,
0x014d,
@@ -1690,7 +1686,7 @@ const u16 dot11lcn_min_sig_sq_tbl_rev0[] = {
0x014d,
};
-const u16 dot11lcn_noise_scale_tbl_rev0[] = {
+static const u16 dot11lcn_noise_scale_tbl_rev0[] = {
0x0000,
0x0000,
0x0000,
@@ -1757,7 +1753,7 @@ const u16 dot11lcn_noise_scale_tbl_rev0[] = {
0x0000,
};
-const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = {
+static const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = {
0x000141f8,
0x000021f8,
0x000021fb,
@@ -1770,7 +1766,7 @@ const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = {
0x0000024b,
};
-const u32 dot11lcn_ps_ctrl_tbl_rev0[] = {
+static const u32 dot11lcn_ps_ctrl_tbl_rev0[] = {
0x00100001,
0x00200010,
0x00300001,
@@ -1793,7 +1789,7 @@ const u32 dot11lcn_ps_ctrl_tbl_rev0[] = {
0x00600f22,
};
-const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = {
+static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = {
0x0007,
0x0005,
0x0006,
@@ -1861,7 +1857,7 @@ const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = {
};
-const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = {
+static const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = {
0x0007,
0x0005,
0x0002,
@@ -1928,7 +1924,7 @@ const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = {
0x0002,
};
-const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
+static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
0x0002,
0x0008,
0x0004,
@@ -1995,7 +1991,7 @@ const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
0x0001,
};
-const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
+static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
0x000a,
0x0009,
0x0006,
@@ -2062,7 +2058,7 @@ const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
0x0005,
};
-const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
+static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
0x0004,
0x0004,
0x0002,
@@ -2129,7 +2125,7 @@ const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
0x0002,
};
-const u8 dot11lcn_nf_table_rev0[] = {
+static const u8 dot11lcn_nf_table_rev0[] = {
0x5f,
0x36,
0x29,
@@ -2148,7 +2144,7 @@ const u8 dot11lcn_nf_table_rev0[] = {
0x1f,
};
-const u8 dot11lcn_gain_val_tbl_rev0[] = {
+static const u8 dot11lcn_gain_val_tbl_rev0[] = {
0x09,
0x0f,
0x14,
@@ -2211,7 +2207,7 @@ const u8 dot11lcn_gain_val_tbl_rev0[] = {
0x00,
};
-const u8 dot11lcn_spur_tbl_rev0[] = {
+static const u8 dot11lcn_spur_tbl_rev0[] = {
0x01,
0x01,
0x01,
@@ -2342,7 +2338,7 @@ const u8 dot11lcn_spur_tbl_rev0[] = {
0x01,
};
-const u16 dot11lcn_unsup_mcs_tbl_rev0[] = {
+static const u16 dot11lcn_unsup_mcs_tbl_rev0[] = {
0x001a,
0x0034,
0x004e,
@@ -2499,7 +2495,7 @@ const u16 dot11lcn_unsup_mcs_tbl_rev0[] = {
0x06f6,
};
-const u16 dot11lcn_iq_local_tbl_rev0[] = {
+static const u16 dot11lcn_iq_local_tbl_rev0[] = {
0x0200,
0x0300,
0x0400,
@@ -2610,7 +2606,7 @@ const u16 dot11lcn_iq_local_tbl_rev0[] = {
0x0000,
};
-const u32 dot11lcn_papd_compdelta_tbl_rev0[] = {
+static const u32 dot11lcn_papd_compdelta_tbl_rev0[] = {
0x00080000,
0x00080000,
0x00080000,
@@ -2834,26 +2830,26 @@ const struct phytbl_info dot11lcnphytbl_info_rev0[] = {
const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313 = {
&dot11lcn_sw_ctrl_tbl_4313_rev0,
- sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) /
- sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) /
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16
};
const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa = {
&dot11lcn_sw_ctrl_tbl_4313_epa_rev0,
- sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) /
- sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) /
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16
};
const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa = {
&dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo,
- sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) /
- sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) /
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16
};
const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250 = {
&dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0,
- sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) /
- sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) /
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16
};
const u32 dot11lcnphytbl_info_sz_rev0 =
@@ -2861,778 +2857,394 @@ const u32 dot11lcnphytbl_info_sz_rev0 =
const struct lcnphy_tx_gain_tbl_entry
dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = {
- {3, 0, 31, 0, 72,}
- ,
- {3, 0, 31, 0, 70,}
- ,
- {3, 0, 31, 0, 68,}
- ,
- {3, 0, 30, 0, 67,}
- ,
- {3, 0, 29, 0, 68,}
- ,
- {3, 0, 28, 0, 68,}
- ,
- {3, 0, 27, 0, 69,}
- ,
- {3, 0, 26, 0, 70,}
- ,
- {3, 0, 25, 0, 70,}
- ,
- {3, 0, 24, 0, 71,}
- ,
- {3, 0, 23, 0, 72,}
- ,
- {3, 0, 23, 0, 70,}
- ,
- {3, 0, 22, 0, 71,}
- ,
- {3, 0, 21, 0, 72,}
- ,
- {3, 0, 21, 0, 70,}
- ,
- {3, 0, 21, 0, 68,}
- ,
- {3, 0, 21, 0, 66,}
- ,
- {3, 0, 21, 0, 64,}
- ,
- {3, 0, 21, 0, 63,}
- ,
- {3, 0, 20, 0, 64,}
- ,
- {3, 0, 19, 0, 65,}
- ,
- {3, 0, 19, 0, 64,}
- ,
- {3, 0, 18, 0, 65,}
- ,
- {3, 0, 18, 0, 64,}
- ,
- {3, 0, 17, 0, 65,}
- ,
- {3, 0, 17, 0, 64,}
- ,
- {3, 0, 16, 0, 65,}
- ,
- {3, 0, 16, 0, 64,}
- ,
- {3, 0, 16, 0, 62,}
- ,
- {3, 0, 16, 0, 60,}
- ,
- {3, 0, 16, 0, 58,}
- ,
- {3, 0, 15, 0, 61,}
- ,
- {3, 0, 15, 0, 59,}
- ,
- {3, 0, 14, 0, 61,}
- ,
- {3, 0, 14, 0, 60,}
- ,
- {3, 0, 14, 0, 58,}
- ,
- {3, 0, 13, 0, 60,}
- ,
- {3, 0, 13, 0, 59,}
- ,
- {3, 0, 12, 0, 62,}
- ,
- {3, 0, 12, 0, 60,}
- ,
- {3, 0, 12, 0, 58,}
- ,
- {3, 0, 11, 0, 62,}
- ,
- {3, 0, 11, 0, 60,}
- ,
- {3, 0, 11, 0, 59,}
- ,
- {3, 0, 11, 0, 57,}
- ,
- {3, 0, 10, 0, 61,}
- ,
- {3, 0, 10, 0, 59,}
- ,
- {3, 0, 10, 0, 57,}
- ,
- {3, 0, 9, 0, 62,}
- ,
- {3, 0, 9, 0, 60,}
- ,
- {3, 0, 9, 0, 58,}
- ,
- {3, 0, 9, 0, 57,}
- ,
- {3, 0, 8, 0, 62,}
- ,
- {3, 0, 8, 0, 60,}
- ,
- {3, 0, 8, 0, 58,}
- ,
- {3, 0, 8, 0, 57,}
- ,
- {3, 0, 8, 0, 55,}
- ,
- {3, 0, 7, 0, 61,}
- ,
- {3, 0, 7, 0, 60,}
- ,
- {3, 0, 7, 0, 58,}
- ,
- {3, 0, 7, 0, 56,}
- ,
- {3, 0, 7, 0, 55,}
- ,
- {3, 0, 6, 0, 62,}
- ,
- {3, 0, 6, 0, 60,}
- ,
- {3, 0, 6, 0, 58,}
- ,
- {3, 0, 6, 0, 57,}
- ,
- {3, 0, 6, 0, 55,}
- ,
- {3, 0, 6, 0, 54,}
- ,
- {3, 0, 6, 0, 52,}
- ,
- {3, 0, 5, 0, 61,}
- ,
- {3, 0, 5, 0, 59,}
- ,
- {3, 0, 5, 0, 57,}
- ,
- {3, 0, 5, 0, 56,}
- ,
- {3, 0, 5, 0, 54,}
- ,
- {3, 0, 5, 0, 53,}
- ,
- {3, 0, 5, 0, 51,}
- ,
- {3, 0, 4, 0, 62,}
- ,
- {3, 0, 4, 0, 60,}
- ,
- {3, 0, 4, 0, 58,}
- ,
- {3, 0, 4, 0, 57,}
- ,
- {3, 0, 4, 0, 55,}
- ,
- {3, 0, 4, 0, 54,}
- ,
- {3, 0, 4, 0, 52,}
- ,
- {3, 0, 4, 0, 51,}
- ,
- {3, 0, 4, 0, 49,}
- ,
- {3, 0, 4, 0, 48,}
- ,
- {3, 0, 4, 0, 46,}
- ,
- {3, 0, 3, 0, 60,}
- ,
- {3, 0, 3, 0, 58,}
- ,
- {3, 0, 3, 0, 57,}
- ,
- {3, 0, 3, 0, 55,}
- ,
- {3, 0, 3, 0, 54,}
- ,
- {3, 0, 3, 0, 52,}
- ,
- {3, 0, 3, 0, 51,}
- ,
- {3, 0, 3, 0, 49,}
- ,
- {3, 0, 3, 0, 48,}
- ,
- {3, 0, 3, 0, 46,}
- ,
- {3, 0, 3, 0, 45,}
- ,
- {3, 0, 3, 0, 44,}
- ,
- {3, 0, 3, 0, 43,}
- ,
- {3, 0, 3, 0, 41,}
- ,
- {3, 0, 2, 0, 61,}
- ,
- {3, 0, 2, 0, 59,}
- ,
- {3, 0, 2, 0, 57,}
- ,
- {3, 0, 2, 0, 56,}
- ,
- {3, 0, 2, 0, 54,}
- ,
- {3, 0, 2, 0, 53,}
- ,
- {3, 0, 2, 0, 51,}
- ,
- {3, 0, 2, 0, 50,}
- ,
- {3, 0, 2, 0, 48,}
- ,
- {3, 0, 2, 0, 47,}
- ,
- {3, 0, 2, 0, 46,}
- ,
- {3, 0, 2, 0, 44,}
- ,
- {3, 0, 2, 0, 43,}
- ,
- {3, 0, 2, 0, 42,}
- ,
- {3, 0, 2, 0, 41,}
- ,
- {3, 0, 2, 0, 39,}
- ,
- {3, 0, 2, 0, 38,}
- ,
- {3, 0, 2, 0, 37,}
- ,
- {3, 0, 2, 0, 36,}
- ,
- {3, 0, 2, 0, 35,}
- ,
- {3, 0, 2, 0, 34,}
- ,
- {3, 0, 2, 0, 33,}
- ,
- {3, 0, 2, 0, 32,}
- ,
- {3, 0, 1, 0, 63,}
- ,
- {3, 0, 1, 0, 61,}
- ,
- {3, 0, 1, 0, 59,}
- ,
- {3, 0, 1, 0, 57,}
- ,
+ {3, 0, 31, 0, 72},
+ {3, 0, 31, 0, 70},
+ {3, 0, 31, 0, 68},
+ {3, 0, 30, 0, 67},
+ {3, 0, 29, 0, 68},
+ {3, 0, 28, 0, 68},
+ {3, 0, 27, 0, 69},
+ {3, 0, 26, 0, 70},
+ {3, 0, 25, 0, 70},
+ {3, 0, 24, 0, 71},
+ {3, 0, 23, 0, 72},
+ {3, 0, 23, 0, 70},
+ {3, 0, 22, 0, 71},
+ {3, 0, 21, 0, 72},
+ {3, 0, 21, 0, 70},
+ {3, 0, 21, 0, 68},
+ {3, 0, 21, 0, 66},
+ {3, 0, 21, 0, 64},
+ {3, 0, 21, 0, 63},
+ {3, 0, 20, 0, 64},
+ {3, 0, 19, 0, 65},
+ {3, 0, 19, 0, 64},
+ {3, 0, 18, 0, 65},
+ {3, 0, 18, 0, 64},
+ {3, 0, 17, 0, 65},
+ {3, 0, 17, 0, 64},
+ {3, 0, 16, 0, 65},
+ {3, 0, 16, 0, 64},
+ {3, 0, 16, 0, 62},
+ {3, 0, 16, 0, 60},
+ {3, 0, 16, 0, 58},
+ {3, 0, 15, 0, 61},
+ {3, 0, 15, 0, 59},
+ {3, 0, 14, 0, 61},
+ {3, 0, 14, 0, 60},
+ {3, 0, 14, 0, 58},
+ {3, 0, 13, 0, 60},
+ {3, 0, 13, 0, 59},
+ {3, 0, 12, 0, 62},
+ {3, 0, 12, 0, 60},
+ {3, 0, 12, 0, 58},
+ {3, 0, 11, 0, 62},
+ {3, 0, 11, 0, 60},
+ {3, 0, 11, 0, 59},
+ {3, 0, 11, 0, 57},
+ {3, 0, 10, 0, 61},
+ {3, 0, 10, 0, 59},
+ {3, 0, 10, 0, 57},
+ {3, 0, 9, 0, 62},
+ {3, 0, 9, 0, 60},
+ {3, 0, 9, 0, 58},
+ {3, 0, 9, 0, 57},
+ {3, 0, 8, 0, 62},
+ {3, 0, 8, 0, 60},
+ {3, 0, 8, 0, 58},
+ {3, 0, 8, 0, 57},
+ {3, 0, 8, 0, 55},
+ {3, 0, 7, 0, 61},
+ {3, 0, 7, 0, 60},
+ {3, 0, 7, 0, 58},
+ {3, 0, 7, 0, 56},
+ {3, 0, 7, 0, 55},
+ {3, 0, 6, 0, 62},
+ {3, 0, 6, 0, 60},
+ {3, 0, 6, 0, 58},
+ {3, 0, 6, 0, 57},
+ {3, 0, 6, 0, 55},
+ {3, 0, 6, 0, 54},
+ {3, 0, 6, 0, 52},
+ {3, 0, 5, 0, 61},
+ {3, 0, 5, 0, 59},
+ {3, 0, 5, 0, 57},
+ {3, 0, 5, 0, 56},
+ {3, 0, 5, 0, 54},
+ {3, 0, 5, 0, 53},
+ {3, 0, 5, 0, 51},
+ {3, 0, 4, 0, 62},
+ {3, 0, 4, 0, 60},
+ {3, 0, 4, 0, 58},
+ {3, 0, 4, 0, 57},
+ {3, 0, 4, 0, 55},
+ {3, 0, 4, 0, 54},
+ {3, 0, 4, 0, 52},
+ {3, 0, 4, 0, 51},
+ {3, 0, 4, 0, 49},
+ {3, 0, 4, 0, 48},
+ {3, 0, 4, 0, 46},
+ {3, 0, 3, 0, 60},
+ {3, 0, 3, 0, 58},
+ {3, 0, 3, 0, 57},
+ {3, 0, 3, 0, 55},
+ {3, 0, 3, 0, 54},
+ {3, 0, 3, 0, 52},
+ {3, 0, 3, 0, 51},
+ {3, 0, 3, 0, 49},
+ {3, 0, 3, 0, 48},
+ {3, 0, 3, 0, 46},
+ {3, 0, 3, 0, 45},
+ {3, 0, 3, 0, 44},
+ {3, 0, 3, 0, 43},
+ {3, 0, 3, 0, 41},
+ {3, 0, 2, 0, 61},
+ {3, 0, 2, 0, 59},
+ {3, 0, 2, 0, 57},
+ {3, 0, 2, 0, 56},
+ {3, 0, 2, 0, 54},
+ {3, 0, 2, 0, 53},
+ {3, 0, 2, 0, 51},
+ {3, 0, 2, 0, 50},
+ {3, 0, 2, 0, 48},
+ {3, 0, 2, 0, 47},
+ {3, 0, 2, 0, 46},
+ {3, 0, 2, 0, 44},
+ {3, 0, 2, 0, 43},
+ {3, 0, 2, 0, 42},
+ {3, 0, 2, 0, 41},
+ {3, 0, 2, 0, 39},
+ {3, 0, 2, 0, 38},
+ {3, 0, 2, 0, 37},
+ {3, 0, 2, 0, 36},
+ {3, 0, 2, 0, 35},
+ {3, 0, 2, 0, 34},
+ {3, 0, 2, 0, 33},
+ {3, 0, 2, 0, 32},
+ {3, 0, 1, 0, 63},
+ {3, 0, 1, 0, 61},
+ {3, 0, 1, 0, 59},
+ {3, 0, 1, 0, 57},
};
const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = {
- {7, 0, 31, 0, 72,}
- ,
- {7, 0, 31, 0, 70,}
- ,
- {7, 0, 31, 0, 68,}
- ,
- {7, 0, 30, 0, 67,}
- ,
- {7, 0, 29, 0, 68,}
- ,
- {7, 0, 28, 0, 68,}
- ,
- {7, 0, 27, 0, 69,}
- ,
- {7, 0, 26, 0, 70,}
- ,
- {7, 0, 25, 0, 70,}
- ,
- {7, 0, 24, 0, 71,}
- ,
- {7, 0, 23, 0, 72,}
- ,
- {7, 0, 23, 0, 70,}
- ,
- {7, 0, 22, 0, 71,}
- ,
- {7, 0, 21, 0, 72,}
- ,
- {7, 0, 21, 0, 70,}
- ,
- {7, 0, 21, 0, 68,}
- ,
- {7, 0, 21, 0, 66,}
- ,
- {7, 0, 21, 0, 64,}
- ,
- {7, 0, 21, 0, 63,}
- ,
- {7, 0, 20, 0, 64,}
- ,
- {7, 0, 19, 0, 65,}
- ,
- {7, 0, 19, 0, 64,}
- ,
- {7, 0, 18, 0, 65,}
- ,
- {7, 0, 18, 0, 64,}
- ,
- {7, 0, 17, 0, 65,}
- ,
- {7, 0, 17, 0, 64,}
- ,
- {7, 0, 16, 0, 65,}
- ,
- {7, 0, 16, 0, 64,}
- ,
- {7, 0, 16, 0, 62,}
- ,
- {7, 0, 16, 0, 60,}
- ,
- {7, 0, 16, 0, 58,}
- ,
- {7, 0, 15, 0, 61,}
- ,
- {7, 0, 15, 0, 59,}
- ,
- {7, 0, 14, 0, 61,}
- ,
- {7, 0, 14, 0, 60,}
- ,
- {7, 0, 14, 0, 58,}
- ,
- {7, 0, 13, 0, 60,}
- ,
- {7, 0, 13, 0, 59,}
- ,
- {7, 0, 12, 0, 62,}
- ,
- {7, 0, 12, 0, 60,}
- ,
- {7, 0, 12, 0, 58,}
- ,
- {7, 0, 11, 0, 62,}
- ,
- {7, 0, 11, 0, 60,}
- ,
- {7, 0, 11, 0, 59,}
- ,
- {7, 0, 11, 0, 57,}
- ,
- {7, 0, 10, 0, 61,}
- ,
- {7, 0, 10, 0, 59,}
- ,
- {7, 0, 10, 0, 57,}
- ,
- {7, 0, 9, 0, 62,}
- ,
- {7, 0, 9, 0, 60,}
- ,
- {7, 0, 9, 0, 58,}
- ,
- {7, 0, 9, 0, 57,}
- ,
- {7, 0, 8, 0, 62,}
- ,
- {7, 0, 8, 0, 60,}
- ,
- {7, 0, 8, 0, 58,}
- ,
- {7, 0, 8, 0, 57,}
- ,
- {7, 0, 8, 0, 55,}
- ,
- {7, 0, 7, 0, 61,}
- ,
- {7, 0, 7, 0, 60,}
- ,
- {7, 0, 7, 0, 58,}
- ,
- {7, 0, 7, 0, 56,}
- ,
- {7, 0, 7, 0, 55,}
- ,
- {7, 0, 6, 0, 62,}
- ,
- {7, 0, 6, 0, 60,}
- ,
- {7, 0, 6, 0, 58,}
- ,
- {7, 0, 6, 0, 57,}
- ,
- {7, 0, 6, 0, 55,}
- ,
- {7, 0, 6, 0, 54,}
- ,
- {7, 0, 6, 0, 52,}
- ,
- {7, 0, 5, 0, 61,}
- ,
- {7, 0, 5, 0, 59,}
- ,
- {7, 0, 5, 0, 57,}
- ,
- {7, 0, 5, 0, 56,}
- ,
- {7, 0, 5, 0, 54,}
- ,
- {7, 0, 5, 0, 53,}
- ,
- {7, 0, 5, 0, 51,}
- ,
- {7, 0, 4, 0, 62,}
- ,
- {7, 0, 4, 0, 60,}
- ,
- {7, 0, 4, 0, 58,}
- ,
- {7, 0, 4, 0, 57,}
- ,
- {7, 0, 4, 0, 55,}
- ,
- {7, 0, 4, 0, 54,}
- ,
- {7, 0, 4, 0, 52,}
- ,
- {7, 0, 4, 0, 51,}
- ,
- {7, 0, 4, 0, 49,}
- ,
- {7, 0, 4, 0, 48,}
- ,
- {7, 0, 4, 0, 46,}
- ,
- {7, 0, 3, 0, 60,}
- ,
- {7, 0, 3, 0, 58,}
- ,
- {7, 0, 3, 0, 57,}
- ,
- {7, 0, 3, 0, 55,}
- ,
- {7, 0, 3, 0, 54,}
- ,
- {7, 0, 3, 0, 52,}
- ,
- {7, 0, 3, 0, 51,}
- ,
- {7, 0, 3, 0, 49,}
- ,
- {7, 0, 3, 0, 48,}
- ,
- {7, 0, 3, 0, 46,}
- ,
- {7, 0, 3, 0, 45,}
- ,
- {7, 0, 3, 0, 44,}
- ,
- {7, 0, 3, 0, 43,}
- ,
- {7, 0, 3, 0, 41,}
- ,
- {7, 0, 2, 0, 61,}
- ,
- {7, 0, 2, 0, 59,}
- ,
- {7, 0, 2, 0, 57,}
- ,
- {7, 0, 2, 0, 56,}
- ,
- {7, 0, 2, 0, 54,}
- ,
- {7, 0, 2, 0, 53,}
- ,
- {7, 0, 2, 0, 51,}
- ,
- {7, 0, 2, 0, 50,}
- ,
- {7, 0, 2, 0, 48,}
- ,
- {7, 0, 2, 0, 47,}
- ,
- {7, 0, 2, 0, 46,}
- ,
- {7, 0, 2, 0, 44,}
- ,
- {7, 0, 2, 0, 43,}
- ,
- {7, 0, 2, 0, 42,}
- ,
- {7, 0, 2, 0, 41,}
- ,
- {7, 0, 2, 0, 39,}
- ,
- {7, 0, 2, 0, 38,}
- ,
- {7, 0, 2, 0, 37,}
- ,
- {7, 0, 2, 0, 36,}
- ,
- {7, 0, 2, 0, 35,}
- ,
- {7, 0, 2, 0, 34,}
- ,
- {7, 0, 2, 0, 33,}
- ,
- {7, 0, 2, 0, 32,}
- ,
- {7, 0, 1, 0, 63,}
- ,
- {7, 0, 1, 0, 61,}
- ,
- {7, 0, 1, 0, 59,}
- ,
- {7, 0, 1, 0, 57,}
- ,
+ {7, 0, 31, 0, 72},
+ {7, 0, 31, 0, 70},
+ {7, 0, 31, 0, 68},
+ {7, 0, 30, 0, 67},
+ {7, 0, 29, 0, 68},
+ {7, 0, 28, 0, 68},
+ {7, 0, 27, 0, 69},
+ {7, 0, 26, 0, 70},
+ {7, 0, 25, 0, 70},
+ {7, 0, 24, 0, 71},
+ {7, 0, 23, 0, 72},
+ {7, 0, 23, 0, 70},
+ {7, 0, 22, 0, 71},
+ {7, 0, 21, 0, 72},
+ {7, 0, 21, 0, 70},
+ {7, 0, 21, 0, 68},
+ {7, 0, 21, 0, 66},
+ {7, 0, 21, 0, 64},
+ {7, 0, 21, 0, 63},
+ {7, 0, 20, 0, 64},
+ {7, 0, 19, 0, 65},
+ {7, 0, 19, 0, 64},
+ {7, 0, 18, 0, 65},
+ {7, 0, 18, 0, 64},
+ {7, 0, 17, 0, 65},
+ {7, 0, 17, 0, 64},
+ {7, 0, 16, 0, 65},
+ {7, 0, 16, 0, 64},
+ {7, 0, 16, 0, 62},
+ {7, 0, 16, 0, 60},
+ {7, 0, 16, 0, 58},
+ {7, 0, 15, 0, 61},
+ {7, 0, 15, 0, 59},
+ {7, 0, 14, 0, 61},
+ {7, 0, 14, 0, 60},
+ {7, 0, 14, 0, 58},
+ {7, 0, 13, 0, 60},
+ {7, 0, 13, 0, 59},
+ {7, 0, 12, 0, 62},
+ {7, 0, 12, 0, 60},
+ {7, 0, 12, 0, 58},
+ {7, 0, 11, 0, 62},
+ {7, 0, 11, 0, 60},
+ {7, 0, 11, 0, 59},
+ {7, 0, 11, 0, 57},
+ {7, 0, 10, 0, 61},
+ {7, 0, 10, 0, 59},
+ {7, 0, 10, 0, 57},
+ {7, 0, 9, 0, 62},
+ {7, 0, 9, 0, 60},
+ {7, 0, 9, 0, 58},
+ {7, 0, 9, 0, 57},
+ {7, 0, 8, 0, 62},
+ {7, 0, 8, 0, 60},
+ {7, 0, 8, 0, 58},
+ {7, 0, 8, 0, 57},
+ {7, 0, 8, 0, 55},
+ {7, 0, 7, 0, 61},
+ {7, 0, 7, 0, 60},
+ {7, 0, 7, 0, 58},
+ {7, 0, 7, 0, 56},
+ {7, 0, 7, 0, 55},
+ {7, 0, 6, 0, 62},
+ {7, 0, 6, 0, 60},
+ {7, 0, 6, 0, 58},
+ {7, 0, 6, 0, 57},
+ {7, 0, 6, 0, 55},
+ {7, 0, 6, 0, 54},
+ {7, 0, 6, 0, 52},
+ {7, 0, 5, 0, 61},
+ {7, 0, 5, 0, 59},
+ {7, 0, 5, 0, 57},
+ {7, 0, 5, 0, 56},
+ {7, 0, 5, 0, 54},
+ {7, 0, 5, 0, 53},
+ {7, 0, 5, 0, 51},
+ {7, 0, 4, 0, 62},
+ {7, 0, 4, 0, 60},
+ {7, 0, 4, 0, 58},
+ {7, 0, 4, 0, 57},
+ {7, 0, 4, 0, 55},
+ {7, 0, 4, 0, 54},
+ {7, 0, 4, 0, 52},
+ {7, 0, 4, 0, 51},
+ {7, 0, 4, 0, 49},
+ {7, 0, 4, 0, 48},
+ {7, 0, 4, 0, 46},
+ {7, 0, 3, 0, 60},
+ {7, 0, 3, 0, 58},
+ {7, 0, 3, 0, 57},
+ {7, 0, 3, 0, 55},
+ {7, 0, 3, 0, 54},
+ {7, 0, 3, 0, 52},
+ {7, 0, 3, 0, 51},
+ {7, 0, 3, 0, 49},
+ {7, 0, 3, 0, 48},
+ {7, 0, 3, 0, 46},
+ {7, 0, 3, 0, 45},
+ {7, 0, 3, 0, 44},
+ {7, 0, 3, 0, 43},
+ {7, 0, 3, 0, 41},
+ {7, 0, 2, 0, 61},
+ {7, 0, 2, 0, 59},
+ {7, 0, 2, 0, 57},
+ {7, 0, 2, 0, 56},
+ {7, 0, 2, 0, 54},
+ {7, 0, 2, 0, 53},
+ {7, 0, 2, 0, 51},
+ {7, 0, 2, 0, 50},
+ {7, 0, 2, 0, 48},
+ {7, 0, 2, 0, 47},
+ {7, 0, 2, 0, 46},
+ {7, 0, 2, 0, 44},
+ {7, 0, 2, 0, 43},
+ {7, 0, 2, 0, 42},
+ {7, 0, 2, 0, 41},
+ {7, 0, 2, 0, 39},
+ {7, 0, 2, 0, 38},
+ {7, 0, 2, 0, 37},
+ {7, 0, 2, 0, 36},
+ {7, 0, 2, 0, 35},
+ {7, 0, 2, 0, 34},
+ {7, 0, 2, 0, 33},
+ {7, 0, 2, 0, 32},
+ {7, 0, 1, 0, 63},
+ {7, 0, 1, 0, 61},
+ {7, 0, 1, 0, 59},
+ {7, 0, 1, 0, 57},
};
const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = {
- {255, 255, 0xf0, 0, 152,}
- ,
- {255, 255, 0xf0, 0, 147,}
- ,
- {255, 255, 0xf0, 0, 143,}
- ,
- {255, 255, 0xf0, 0, 139,}
- ,
- {255, 255, 0xf0, 0, 135,}
- ,
- {255, 255, 0xf0, 0, 131,}
- ,
- {255, 255, 0xf0, 0, 128,}
- ,
- {255, 255, 0xf0, 0, 124,}
- ,
- {255, 255, 0xf0, 0, 121,}
- ,
- {255, 255, 0xf0, 0, 117,}
- ,
- {255, 255, 0xf0, 0, 114,}
- ,
- {255, 255, 0xf0, 0, 111,}
- ,
- {255, 255, 0xf0, 0, 107,}
- ,
- {255, 255, 0xf0, 0, 104,}
- ,
- {255, 255, 0xf0, 0, 101,}
- ,
- {255, 255, 0xf0, 0, 99,}
- ,
- {255, 255, 0xf0, 0, 96,}
- ,
- {255, 255, 0xf0, 0, 93,}
- ,
- {255, 255, 0xf0, 0, 90,}
- ,
- {255, 255, 0xf0, 0, 88,}
- ,
- {255, 255, 0xf0, 0, 85,}
- ,
- {255, 255, 0xf0, 0, 83,}
- ,
- {255, 255, 0xf0, 0, 81,}
- ,
- {255, 255, 0xf0, 0, 78,}
- ,
- {255, 255, 0xf0, 0, 76,}
- ,
- {255, 255, 0xf0, 0, 74,}
- ,
- {255, 255, 0xf0, 0, 72,}
- ,
- {255, 255, 0xf0, 0, 70,}
- ,
- {255, 255, 0xf0, 0, 68,}
- ,
- {255, 255, 0xf0, 0, 66,}
- ,
- {255, 255, 0xf0, 0, 64,}
- ,
- {255, 248, 0xf0, 0, 64,}
- ,
- {255, 241, 0xf0, 0, 64,}
- ,
- {255, 251, 0xe0, 0, 64,}
- ,
- {255, 244, 0xe0, 0, 64,}
- ,
- {255, 254, 0xd0, 0, 64,}
- ,
- {255, 246, 0xd0, 0, 64,}
- ,
- {255, 239, 0xd0, 0, 64,}
- ,
- {255, 249, 0xc0, 0, 64,}
- ,
- {255, 242, 0xc0, 0, 64,}
- ,
- {255, 255, 0xb0, 0, 64,}
- ,
- {255, 248, 0xb0, 0, 64,}
- ,
- {255, 241, 0xb0, 0, 64,}
- ,
- {255, 254, 0xa0, 0, 64,}
- ,
- {255, 246, 0xa0, 0, 64,}
- ,
- {255, 239, 0xa0, 0, 64,}
- ,
- {255, 255, 0x90, 0, 64,}
- ,
- {255, 248, 0x90, 0, 64,}
- ,
- {255, 241, 0x90, 0, 64,}
- ,
- {255, 234, 0x90, 0, 64,}
- ,
- {255, 255, 0x80, 0, 64,}
- ,
- {255, 248, 0x80, 0, 64,}
- ,
- {255, 241, 0x80, 0, 64,}
- ,
- {255, 234, 0x80, 0, 64,}
- ,
- {255, 255, 0x70, 0, 64,}
- ,
- {255, 248, 0x70, 0, 64,}
- ,
- {255, 241, 0x70, 0, 64,}
- ,
- {255, 234, 0x70, 0, 64,}
- ,
- {255, 227, 0x70, 0, 64,}
- ,
- {255, 221, 0x70, 0, 64,}
- ,
- {255, 215, 0x70, 0, 64,}
- ,
- {255, 208, 0x70, 0, 64,}
- ,
- {255, 203, 0x70, 0, 64,}
- ,
- {255, 197, 0x70, 0, 64,}
- ,
- {255, 255, 0x60, 0, 64,}
- ,
- {255, 248, 0x60, 0, 64,}
- ,
- {255, 241, 0x60, 0, 64,}
- ,
- {255, 234, 0x60, 0, 64,}
- ,
- {255, 227, 0x60, 0, 64,}
- ,
- {255, 221, 0x60, 0, 64,}
- ,
- {255, 255, 0x50, 0, 64,}
- ,
- {255, 248, 0x50, 0, 64,}
- ,
- {255, 241, 0x50, 0, 64,}
- ,
- {255, 234, 0x50, 0, 64,}
- ,
- {255, 227, 0x50, 0, 64,}
- ,
- {255, 221, 0x50, 0, 64,}
- ,
- {255, 215, 0x50, 0, 64,}
- ,
- {255, 208, 0x50, 0, 64,}
- ,
- {255, 255, 0x40, 0, 64,}
- ,
- {255, 248, 0x40, 0, 64,}
- ,
- {255, 241, 0x40, 0, 64,}
- ,
- {255, 234, 0x40, 0, 64,}
- ,
- {255, 227, 0x40, 0, 64,}
- ,
- {255, 221, 0x40, 0, 64,}
- ,
- {255, 215, 0x40, 0, 64,}
- ,
- {255, 208, 0x40, 0, 64,}
- ,
- {255, 203, 0x40, 0, 64,}
- ,
- {255, 197, 0x40, 0, 64,}
- ,
- {255, 255, 0x30, 0, 64,}
- ,
- {255, 248, 0x30, 0, 64,}
- ,
- {255, 241, 0x30, 0, 64,}
- ,
- {255, 234, 0x30, 0, 64,}
- ,
- {255, 227, 0x30, 0, 64,}
- ,
- {255, 221, 0x30, 0, 64,}
- ,
- {255, 215, 0x30, 0, 64,}
- ,
- {255, 208, 0x30, 0, 64,}
- ,
- {255, 203, 0x30, 0, 64,}
- ,
- {255, 197, 0x30, 0, 64,}
- ,
- {255, 191, 0x30, 0, 64,}
- ,
- {255, 186, 0x30, 0, 64,}
- ,
- {255, 181, 0x30, 0, 64,}
- ,
- {255, 175, 0x30, 0, 64,}
- ,
- {255, 255, 0x20, 0, 64,}
- ,
- {255, 248, 0x20, 0, 64,}
- ,
- {255, 241, 0x20, 0, 64,}
- ,
- {255, 234, 0x20, 0, 64,}
- ,
- {255, 227, 0x20, 0, 64,}
- ,
- {255, 221, 0x20, 0, 64,}
- ,
- {255, 215, 0x20, 0, 64,}
- ,
- {255, 208, 0x20, 0, 64,}
- ,
- {255, 203, 0x20, 0, 64,}
- ,
- {255, 197, 0x20, 0, 64,}
- ,
- {255, 191, 0x20, 0, 64,}
- ,
- {255, 186, 0x20, 0, 64,}
- ,
- {255, 181, 0x20, 0, 64,}
- ,
- {255, 175, 0x20, 0, 64,}
- ,
- {255, 170, 0x20, 0, 64,}
- ,
- {255, 166, 0x20, 0, 64,}
- ,
- {255, 161, 0x20, 0, 64,}
- ,
- {255, 156, 0x20, 0, 64,}
- ,
- {255, 152, 0x20, 0, 64,}
- ,
- {255, 148, 0x20, 0, 64,}
- ,
- {255, 143, 0x20, 0, 64,}
- ,
- {255, 139, 0x20, 0, 64,}
- ,
- {255, 135, 0x20, 0, 64,}
- ,
- {255, 132, 0x20, 0, 64,}
- ,
- {255, 255, 0x10, 0, 64,}
- ,
- {255, 248, 0x10, 0, 64,}
- ,
+ {255, 255, 0xf0, 0, 152},
+ {255, 255, 0xf0, 0, 147},
+ {255, 255, 0xf0, 0, 143},
+ {255, 255, 0xf0, 0, 139},
+ {255, 255, 0xf0, 0, 135},
+ {255, 255, 0xf0, 0, 131},
+ {255, 255, 0xf0, 0, 128},
+ {255, 255, 0xf0, 0, 124},
+ {255, 255, 0xf0, 0, 121},
+ {255, 255, 0xf0, 0, 117},
+ {255, 255, 0xf0, 0, 114},
+ {255, 255, 0xf0, 0, 111},
+ {255, 255, 0xf0, 0, 107},
+ {255, 255, 0xf0, 0, 104},
+ {255, 255, 0xf0, 0, 101},
+ {255, 255, 0xf0, 0, 99},
+ {255, 255, 0xf0, 0, 96},
+ {255, 255, 0xf0, 0, 93},
+ {255, 255, 0xf0, 0, 90},
+ {255, 255, 0xf0, 0, 88},
+ {255, 255, 0xf0, 0, 85},
+ {255, 255, 0xf0, 0, 83},
+ {255, 255, 0xf0, 0, 81},
+ {255, 255, 0xf0, 0, 78},
+ {255, 255, 0xf0, 0, 76},
+ {255, 255, 0xf0, 0, 74},
+ {255, 255, 0xf0, 0, 72},
+ {255, 255, 0xf0, 0, 70},
+ {255, 255, 0xf0, 0, 68},
+ {255, 255, 0xf0, 0, 66},
+ {255, 255, 0xf0, 0, 64},
+ {255, 248, 0xf0, 0, 64},
+ {255, 241, 0xf0, 0, 64},
+ {255, 251, 0xe0, 0, 64},
+ {255, 244, 0xe0, 0, 64},
+ {255, 254, 0xd0, 0, 64},
+ {255, 246, 0xd0, 0, 64},
+ {255, 239, 0xd0, 0, 64},
+ {255, 249, 0xc0, 0, 64},
+ {255, 242, 0xc0, 0, 64},
+ {255, 255, 0xb0, 0, 64},
+ {255, 248, 0xb0, 0, 64},
+ {255, 241, 0xb0, 0, 64},
+ {255, 254, 0xa0, 0, 64},
+ {255, 246, 0xa0, 0, 64},
+ {255, 239, 0xa0, 0, 64},
+ {255, 255, 0x90, 0, 64},
+ {255, 248, 0x90, 0, 64},
+ {255, 241, 0x90, 0, 64},
+ {255, 234, 0x90, 0, 64},
+ {255, 255, 0x80, 0, 64},
+ {255, 248, 0x80, 0, 64},
+ {255, 241, 0x80, 0, 64},
+ {255, 234, 0x80, 0, 64},
+ {255, 255, 0x70, 0, 64},
+ {255, 248, 0x70, 0, 64},
+ {255, 241, 0x70, 0, 64},
+ {255, 234, 0x70, 0, 64},
+ {255, 227, 0x70, 0, 64},
+ {255, 221, 0x70, 0, 64},
+ {255, 215, 0x70, 0, 64},
+ {255, 208, 0x70, 0, 64},
+ {255, 203, 0x70, 0, 64},
+ {255, 197, 0x70, 0, 64},
+ {255, 255, 0x60, 0, 64},
+ {255, 248, 0x60, 0, 64},
+ {255, 241, 0x60, 0, 64},
+ {255, 234, 0x60, 0, 64},
+ {255, 227, 0x60, 0, 64},
+ {255, 221, 0x60, 0, 64},
+ {255, 255, 0x50, 0, 64},
+ {255, 248, 0x50, 0, 64},
+ {255, 241, 0x50, 0, 64},
+ {255, 234, 0x50, 0, 64},
+ {255, 227, 0x50, 0, 64},
+ {255, 221, 0x50, 0, 64},
+ {255, 215, 0x50, 0, 64},
+ {255, 208, 0x50, 0, 64},
+ {255, 255, 0x40, 0, 64},
+ {255, 248, 0x40, 0, 64},
+ {255, 241, 0x40, 0, 64},
+ {255, 234, 0x40, 0, 64},
+ {255, 227, 0x40, 0, 64},
+ {255, 221, 0x40, 0, 64},
+ {255, 215, 0x40, 0, 64},
+ {255, 208, 0x40, 0, 64},
+ {255, 203, 0x40, 0, 64},
+ {255, 197, 0x40, 0, 64},
+ {255, 255, 0x30, 0, 64},
+ {255, 248, 0x30, 0, 64},
+ {255, 241, 0x30, 0, 64},
+ {255, 234, 0x30, 0, 64},
+ {255, 227, 0x30, 0, 64},
+ {255, 221, 0x30, 0, 64},
+ {255, 215, 0x30, 0, 64},
+ {255, 208, 0x30, 0, 64},
+ {255, 203, 0x30, 0, 64},
+ {255, 197, 0x30, 0, 64},
+ {255, 191, 0x30, 0, 64},
+ {255, 186, 0x30, 0, 64},
+ {255, 181, 0x30, 0, 64},
+ {255, 175, 0x30, 0, 64},
+ {255, 255, 0x20, 0, 64},
+ {255, 248, 0x20, 0, 64},
+ {255, 241, 0x20, 0, 64},
+ {255, 234, 0x20, 0, 64},
+ {255, 227, 0x20, 0, 64},
+ {255, 221, 0x20, 0, 64},
+ {255, 215, 0x20, 0, 64},
+ {255, 208, 0x20, 0, 64},
+ {255, 203, 0x20, 0, 64},
+ {255, 197, 0x20, 0, 64},
+ {255, 191, 0x20, 0, 64},
+ {255, 186, 0x20, 0, 64},
+ {255, 181, 0x20, 0, 64},
+ {255, 175, 0x20, 0, 64},
+ {255, 170, 0x20, 0, 64},
+ {255, 166, 0x20, 0, 64},
+ {255, 161, 0x20, 0, 64},
+ {255, 156, 0x20, 0, 64},
+ {255, 152, 0x20, 0, 64},
+ {255, 148, 0x20, 0, 64},
+ {255, 143, 0x20, 0, 64},
+ {255, 139, 0x20, 0, 64},
+ {255, 135, 0x20, 0, 64},
+ {255, 132, 0x20, 0, 64},
+ {255, 255, 0x10, 0, 64},
+ {255, 248, 0x10, 0, 64},
};
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c
index 7f741f4868a6..dbf50ef6cd75 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c
@@ -17,7 +17,7 @@
#include <types.h>
#include "phytbl_n.h"
-const u32 frame_struct_rev0[] = {
+static const u32 frame_struct_rev0[] = {
0x08004a04,
0x00100000,
0x01000a05,
@@ -852,7 +852,7 @@ const u32 frame_struct_rev0[] = {
0x00000000,
};
-const u8 frame_lut_rev0[] = {
+static const u8 frame_lut_rev0[] = {
0x02,
0x04,
0x14,
@@ -887,7 +887,7 @@ const u8 frame_lut_rev0[] = {
0x2a,
};
-const u32 tmap_tbl_rev0[] = {
+static const u32 tmap_tbl_rev0[] = {
0x8a88aa80,
0x8aaaaa8a,
0x8a8a8aa8,
@@ -1338,7 +1338,7 @@ const u32 tmap_tbl_rev0[] = {
0x00000000,
};
-const u32 tdtrn_tbl_rev0[] = {
+static const u32 tdtrn_tbl_rev0[] = {
0x061c061c,
0x0050ee68,
0xf592fe36,
@@ -2045,7 +2045,7 @@ const u32 tdtrn_tbl_rev0[] = {
0x00f006be,
};
-const u32 intlv_tbl_rev0[] = {
+static const u32 intlv_tbl_rev0[] = {
0x00802070,
0x0671188d,
0x0a60192c,
@@ -2055,7 +2055,7 @@ const u32 intlv_tbl_rev0[] = {
0x00000070,
};
-const u16 pilot_tbl_rev0[] = {
+static const u16 pilot_tbl_rev0[] = {
0xff08,
0xff08,
0xff08,
@@ -2146,7 +2146,7 @@ const u16 pilot_tbl_rev0[] = {
0xffff,
};
-const u32 pltlut_tbl_rev0[] = {
+static const u32 pltlut_tbl_rev0[] = {
0x76540123,
0x62407351,
0x76543201,
@@ -2155,7 +2155,7 @@ const u32 pltlut_tbl_rev0[] = {
0x76430521,
};
-const u32 tdi_tbl20_ant0_rev0[] = {
+static const u32 tdi_tbl20_ant0_rev0[] = {
0x00091226,
0x000a1429,
0x000b56ad,
@@ -2213,7 +2213,7 @@ const u32 tdi_tbl20_ant0_rev0[] = {
0x00000000,
};
-const u32 tdi_tbl20_ant1_rev0[] = {
+static const u32 tdi_tbl20_ant1_rev0[] = {
0x00014b26,
0x00028d29,
0x000393ad,
@@ -2271,7 +2271,7 @@ const u32 tdi_tbl20_ant1_rev0[] = {
0x00000000,
};
-const u32 tdi_tbl40_ant0_rev0[] = {
+static const u32 tdi_tbl40_ant0_rev0[] = {
0x0011a346,
0x00136ccf,
0x0014f5d9,
@@ -2384,7 +2384,7 @@ const u32 tdi_tbl40_ant0_rev0[] = {
0x00000000,
};
-const u32 tdi_tbl40_ant1_rev0[] = {
+static const u32 tdi_tbl40_ant1_rev0[] = {
0x001edb36,
0x000129ca,
0x0002b353,
@@ -2497,7 +2497,7 @@ const u32 tdi_tbl40_ant1_rev0[] = {
0x00000000,
};
-const u16 bdi_tbl_rev0[] = {
+static const u16 bdi_tbl_rev0[] = {
0x0070,
0x0126,
0x012c,
@@ -2506,7 +2506,7 @@ const u16 bdi_tbl_rev0[] = {
0x04d2,
};
-const u32 chanest_tbl_rev0[] = {
+static const u32 chanest_tbl_rev0[] = {
0x44444444,
0x44444444,
0x44444444,
@@ -2605,7 +2605,7 @@ const u32 chanest_tbl_rev0[] = {
0x10101010,
};
-const u8 mcs_tbl_rev0[] = {
+static const u8 mcs_tbl_rev0[] = {
0x00,
0x08,
0x0a,
@@ -2736,7 +2736,7 @@ const u8 mcs_tbl_rev0[] = {
0x00,
};
-const u32 noise_var_tbl0_rev0[] = {
+static const u32 noise_var_tbl0_rev0[] = {
0x020c020c,
0x0000014d,
0x020c020c,
@@ -2995,7 +2995,7 @@ const u32 noise_var_tbl0_rev0[] = {
0x0000014d,
};
-const u32 noise_var_tbl1_rev0[] = {
+static const u32 noise_var_tbl1_rev0[] = {
0x020c020c,
0x0000014d,
0x020c020c,
@@ -3254,7 +3254,7 @@ const u32 noise_var_tbl1_rev0[] = {
0x0000014d,
};
-const u8 est_pwr_lut_core0_rev0[] = {
+static const u8 est_pwr_lut_core0_rev0[] = {
0x50,
0x4f,
0x4e,
@@ -3321,7 +3321,7 @@ const u8 est_pwr_lut_core0_rev0[] = {
0x11,
};
-const u8 est_pwr_lut_core1_rev0[] = {
+static const u8 est_pwr_lut_core1_rev0[] = {
0x50,
0x4f,
0x4e,
@@ -3388,7 +3388,7 @@ const u8 est_pwr_lut_core1_rev0[] = {
0x11,
};
-const u8 adj_pwr_lut_core0_rev0[] = {
+static const u8 adj_pwr_lut_core0_rev0[] = {
0x00,
0x00,
0x00,
@@ -3519,7 +3519,7 @@ const u8 adj_pwr_lut_core0_rev0[] = {
0x00,
};
-const u8 adj_pwr_lut_core1_rev0[] = {
+static const u8 adj_pwr_lut_core1_rev0[] = {
0x00,
0x00,
0x00,
@@ -3650,7 +3650,7 @@ const u8 adj_pwr_lut_core1_rev0[] = {
0x00,
};
-const u32 gainctrl_lut_core0_rev0[] = {
+static const u32 gainctrl_lut_core0_rev0[] = {
0x03cc2b44,
0x03cc2b42,
0x03cc2b40,
@@ -3781,7 +3781,7 @@ const u32 gainctrl_lut_core0_rev0[] = {
0x00002b00,
};
-const u32 gainctrl_lut_core1_rev0[] = {
+static const u32 gainctrl_lut_core1_rev0[] = {
0x03cc2b44,
0x03cc2b42,
0x03cc2b40,
@@ -3912,7 +3912,7 @@ const u32 gainctrl_lut_core1_rev0[] = {
0x00002b00,
};
-const u32 iq_lut_core0_rev0[] = {
+static const u32 iq_lut_core0_rev0[] = {
0x0000007f,
0x0000007f,
0x0000007f,
@@ -4043,7 +4043,7 @@ const u32 iq_lut_core0_rev0[] = {
0x0000007f,
};
-const u32 iq_lut_core1_rev0[] = {
+static const u32 iq_lut_core1_rev0[] = {
0x0000007f,
0x0000007f,
0x0000007f,
@@ -4174,7 +4174,7 @@ const u32 iq_lut_core1_rev0[] = {
0x0000007f,
};
-const u16 loft_lut_core0_rev0[] = {
+static const u16 loft_lut_core0_rev0[] = {
0x0000,
0x0101,
0x0002,
@@ -4305,7 +4305,7 @@ const u16 loft_lut_core0_rev0[] = {
0x0103,
};
-const u16 loft_lut_core1_rev0[] = {
+static const u16 loft_lut_core1_rev0[] = {
0x0000,
0x0101,
0x0002,
@@ -4522,7 +4522,8 @@ const struct phytbl_info mimophytbl_info_rev0[] = {
{&chanest_tbl_rev0,
sizeof(chanest_tbl_rev0) / sizeof(chanest_tbl_rev0[0]), 22, 0, 32}
,
- {&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0, 8}
+ {&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0,
+ 8}
,
{&noise_var_tbl0_rev0,
sizeof(noise_var_tbl0_rev0) / sizeof(noise_var_tbl0_rev0[0]), 16, 0,
@@ -4540,7 +4541,7 @@ const u32 mimophytbl_info_sz_rev0_volatile =
sizeof(mimophytbl_info_rev0_volatile) /
sizeof(mimophytbl_info_rev0_volatile[0]);
-const u16 ant_swctrl_tbl_rev3[] = {
+static const u16 ant_swctrl_tbl_rev3[] = {
0x0082,
0x0082,
0x0211,
@@ -4575,7 +4576,7 @@ const u16 ant_swctrl_tbl_rev3[] = {
0x0000,
};
-const u16 ant_swctrl_tbl_rev3_1[] = {
+static const u16 ant_swctrl_tbl_rev3_1[] = {
0x0022,
0x0022,
0x0011,
@@ -4610,7 +4611,7 @@ const u16 ant_swctrl_tbl_rev3_1[] = {
0x0000,
};
-const u16 ant_swctrl_tbl_rev3_2[] = {
+static const u16 ant_swctrl_tbl_rev3_2[] = {
0x0088,
0x0088,
0x0044,
@@ -4645,7 +4646,7 @@ const u16 ant_swctrl_tbl_rev3_2[] = {
0x0000,
};
-const u16 ant_swctrl_tbl_rev3_3[] = {
+static const u16 ant_swctrl_tbl_rev3_3[] = {
0x022,
0x022,
0x011,
@@ -4680,7 +4681,7 @@ const u16 ant_swctrl_tbl_rev3_3[] = {
0x3cc
};
-const u32 frame_struct_rev3[] = {
+static const u32 frame_struct_rev3[] = {
0x08004a04,
0x00100000,
0x01000a05,
@@ -5515,7 +5516,7 @@ const u32 frame_struct_rev3[] = {
0x00000000,
};
-const u16 pilot_tbl_rev3[] = {
+static const u16 pilot_tbl_rev3[] = {
0xff08,
0xff08,
0xff08,
@@ -5606,7 +5607,7 @@ const u16 pilot_tbl_rev3[] = {
0xffff,
};
-const u32 tmap_tbl_rev3[] = {
+static const u32 tmap_tbl_rev3[] = {
0x8a88aa80,
0x8aaaaa8a,
0x8a8a8aa8,
@@ -6057,7 +6058,7 @@ const u32 tmap_tbl_rev3[] = {
0x00000000,
};
-const u32 intlv_tbl_rev3[] = {
+static const u32 intlv_tbl_rev3[] = {
0x00802070,
0x0671188d,
0x0a60192c,
@@ -6067,7 +6068,7 @@ const u32 intlv_tbl_rev3[] = {
0x00000070,
};
-const u32 tdtrn_tbl_rev3[] = {
+static const u32 tdtrn_tbl_rev3[] = {
0x061c061c,
0x0050ee68,
0xf592fe36,
@@ -7033,7 +7034,7 @@ const u32 noise_var_tbl_rev3[] = {
0x0000014d,
};
-const u16 mcs_tbl_rev3[] = {
+static const u16 mcs_tbl_rev3[] = {
0x0000,
0x0008,
0x000a,
@@ -7164,7 +7165,7 @@ const u16 mcs_tbl_rev3[] = {
0x0007,
};
-const u32 tdi_tbl20_ant0_rev3[] = {
+static const u32 tdi_tbl20_ant0_rev3[] = {
0x00091226,
0x000a1429,
0x000b56ad,
@@ -7222,7 +7223,7 @@ const u32 tdi_tbl20_ant0_rev3[] = {
0x00000000,
};
-const u32 tdi_tbl20_ant1_rev3[] = {
+static const u32 tdi_tbl20_ant1_rev3[] = {
0x00014b26,
0x00028d29,
0x000393ad,
@@ -7280,7 +7281,7 @@ const u32 tdi_tbl20_ant1_rev3[] = {
0x00000000,
};
-const u32 tdi_tbl40_ant0_rev3[] = {
+static const u32 tdi_tbl40_ant0_rev3[] = {
0x0011a346,
0x00136ccf,
0x0014f5d9,
@@ -7393,7 +7394,7 @@ const u32 tdi_tbl40_ant0_rev3[] = {
0x00000000,
};
-const u32 tdi_tbl40_ant1_rev3[] = {
+static const u32 tdi_tbl40_ant1_rev3[] = {
0x001edb36,
0x000129ca,
0x0002b353,
@@ -7506,7 +7507,7 @@ const u32 tdi_tbl40_ant1_rev3[] = {
0x00000000,
};
-const u32 pltlut_tbl_rev3[] = {
+static const u32 pltlut_tbl_rev3[] = {
0x76540213,
0x62407351,
0x76543210,
@@ -7515,7 +7516,7 @@ const u32 pltlut_tbl_rev3[] = {
0x76430521,
};
-const u32 chanest_tbl_rev3[] = {
+static const u32 chanest_tbl_rev3[] = {
0x44444444,
0x44444444,
0x44444444,
@@ -7614,7 +7615,7 @@ const u32 chanest_tbl_rev3[] = {
0x10101010,
};
-const u8 frame_lut_rev3[] = {
+static const u8 frame_lut_rev3[] = {
0x02,
0x04,
0x14,
@@ -7649,7 +7650,7 @@ const u8 frame_lut_rev3[] = {
0x2a,
};
-const u8 est_pwr_lut_core0_rev3[] = {
+static const u8 est_pwr_lut_core0_rev3[] = {
0x55,
0x54,
0x54,
@@ -7716,7 +7717,7 @@ const u8 est_pwr_lut_core0_rev3[] = {
0xfd,
};
-const u8 est_pwr_lut_core1_rev3[] = {
+static const u8 est_pwr_lut_core1_rev3[] = {
0x55,
0x54,
0x54,
@@ -7783,7 +7784,7 @@ const u8 est_pwr_lut_core1_rev3[] = {
0xfd,
};
-const u8 adj_pwr_lut_core0_rev3[] = {
+static const u8 adj_pwr_lut_core0_rev3[] = {
0x00,
0x00,
0x00,
@@ -7914,7 +7915,7 @@ const u8 adj_pwr_lut_core0_rev3[] = {
0x00,
};
-const u8 adj_pwr_lut_core1_rev3[] = {
+static const u8 adj_pwr_lut_core1_rev3[] = {
0x00,
0x00,
0x00,
@@ -8045,7 +8046,7 @@ const u8 adj_pwr_lut_core1_rev3[] = {
0x00,
};
-const u32 gainctrl_lut_core0_rev3[] = {
+static const u32 gainctrl_lut_core0_rev3[] = {
0x5bf70044,
0x5bf70042,
0x5bf70040,
@@ -8176,7 +8177,7 @@ const u32 gainctrl_lut_core0_rev3[] = {
0x5b07001c,
};
-const u32 gainctrl_lut_core1_rev3[] = {
+static const u32 gainctrl_lut_core1_rev3[] = {
0x5bf70044,
0x5bf70042,
0x5bf70040,
@@ -8307,7 +8308,7 @@ const u32 gainctrl_lut_core1_rev3[] = {
0x5b07001c,
};
-const u32 iq_lut_core0_rev3[] = {
+static const u32 iq_lut_core0_rev3[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -8438,7 +8439,7 @@ const u32 iq_lut_core0_rev3[] = {
0x00000000,
};
-const u32 iq_lut_core1_rev3[] = {
+static const u32 iq_lut_core1_rev3[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -8569,7 +8570,7 @@ const u32 iq_lut_core1_rev3[] = {
0x00000000,
};
-const u16 loft_lut_core0_rev3[] = {
+static const u16 loft_lut_core0_rev3[] = {
0x0000,
0x0000,
0x0000,
@@ -8700,7 +8701,7 @@ const u16 loft_lut_core0_rev3[] = {
0x0000,
};
-const u16 loft_lut_core1_rev3[] = {
+static const u16 loft_lut_core1_rev3[] = {
0x0000,
0x0000,
0x0000,
@@ -8831,7 +8832,7 @@ const u16 loft_lut_core1_rev3[] = {
0x0000,
};
-const u16 papd_comp_rfpwr_tbl_core0_rev3[] = {
+static const u16 papd_comp_rfpwr_tbl_core0_rev3[] = {
0x0036,
0x0036,
0x0036,
@@ -8962,7 +8963,7 @@ const u16 papd_comp_rfpwr_tbl_core0_rev3[] = {
0x01d6,
};
-const u16 papd_comp_rfpwr_tbl_core1_rev3[] = {
+static const u16 papd_comp_rfpwr_tbl_core1_rev3[] = {
0x0036,
0x0036,
0x0036,
@@ -9093,7 +9094,7 @@ const u16 papd_comp_rfpwr_tbl_core1_rev3[] = {
0x01d6,
};
-const u32 papd_comp_epsilon_tbl_core0_rev3[] = {
+static const u32 papd_comp_epsilon_tbl_core0_rev3[] = {
0x00000000,
0x00001fa0,
0x00019f78,
@@ -9160,7 +9161,7 @@ const u32 papd_comp_epsilon_tbl_core0_rev3[] = {
0x03e38ffe,
};
-const u32 papd_cal_scalars_tbl_core0_rev3[] = {
+static const u32 papd_cal_scalars_tbl_core0_rev3[] = {
0x05af005a,
0x0571005e,
0x05040066,
@@ -9227,7 +9228,7 @@ const u32 papd_cal_scalars_tbl_core0_rev3[] = {
0x002606a4,
};
-const u32 papd_comp_epsilon_tbl_core1_rev3[] = {
+static const u32 papd_comp_epsilon_tbl_core1_rev3[] = {
0x00000000,
0x00001fa0,
0x00019f78,
@@ -9294,7 +9295,7 @@ const u32 papd_comp_epsilon_tbl_core1_rev3[] = {
0x03e38ffe,
};
-const u32 papd_cal_scalars_tbl_core1_rev3[] = {
+static const u32 papd_cal_scalars_tbl_core1_rev3[] = {
0x05af005a,
0x0571005e,
0x05040066,
@@ -9489,7 +9490,7 @@ const u32 mimophytbl_info_sz_rev3_volatile3 =
sizeof(mimophytbl_info_rev3_volatile3) /
sizeof(mimophytbl_info_rev3_volatile3[0]);
-const u32 tmap_tbl_rev7[] = {
+static const u32 tmap_tbl_rev7[] = {
0x8a88aa80,
0x8aaaaa8a,
0x8a8a8aa8,
@@ -10199,7 +10200,7 @@ const u32 noise_var_tbl_rev7[] = {
0x0000014d,
};
-const u32 papd_comp_epsilon_tbl_core0_rev7[] = {
+static const u32 papd_comp_epsilon_tbl_core0_rev7[] = {
0x00000000,
0x00000000,
0x00016023,
@@ -10266,7 +10267,7 @@ const u32 papd_comp_epsilon_tbl_core0_rev7[] = {
0x0156cfff,
};
-const u32 papd_cal_scalars_tbl_core0_rev7[] = {
+static const u32 papd_cal_scalars_tbl_core0_rev7[] = {
0x0b5e002d,
0x0ae2002f,
0x0a3b0032,
@@ -10333,7 +10334,7 @@ const u32 papd_cal_scalars_tbl_core0_rev7[] = {
0x004e068c,
};
-const u32 papd_comp_epsilon_tbl_core1_rev7[] = {
+static const u32 papd_comp_epsilon_tbl_core1_rev7[] = {
0x00000000,
0x00000000,
0x00016023,
@@ -10400,7 +10401,7 @@ const u32 papd_comp_epsilon_tbl_core1_rev7[] = {
0x0156cfff,
};
-const u32 papd_cal_scalars_tbl_core1_rev7[] = {
+static const u32 papd_cal_scalars_tbl_core1_rev7[] = {
0x0b5e002d,
0x0ae2002f,
0x0a3b0032,
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h
index c5266cf23725..dc8a84e85117 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h
@@ -20,21 +20,31 @@
#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;
+ 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;
+ 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;
diff --git a/drivers/staging/brcm80211/brcmsmac/phy_shim.c b/drivers/staging/brcm80211/brcmsmac/phy_shim.c
index 82ecdcda271f..5926854f62e2 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy_shim.c
+++ b/drivers/staging/brcm80211/brcmsmac/phy_shim.c
@@ -15,15 +15,15 @@
*/
/*
- * This is "two-way" interface, acting as the SHIM layer between WL and PHY layer.
- * WL driver can optinally call this translation layer to do some preprocessing, then reach PHY.
- * On the PHY->WL driver direction, all calls go through this layer since PHY doesn't have the
- * access to wlc_hw pointer.
+ * 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 "bmac.h"
#include "main.h"
#include "mac80211_if.h"
#include "phy_shim.h"
@@ -31,21 +31,19 @@
/* PHY SHIM module specific state */
struct phy_shim_info {
struct brcms_hardware *wlc_hw; /* pointer to main wlc_hw structure */
- void *wlc; /* pointer to main wlc structure */
- void *wl; /* pointer to os-specific private state */
+ 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,
- void *wl, void *wlc) {
+ 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) {
- wiphy_err(wlc_hw->wlc->wiphy,
- "wl%d: wlc_phy_shim_attach: out of mem\n",
- wlc_hw->unit);
+ if (!physhim)
return NULL;
- }
+
physhim->wlc_hw = wlc_hw;
physhim->wlc = wlc;
physhim->wl = wl;
@@ -59,28 +57,28 @@ void wlc_phy_shim_detach(struct phy_shim_info *physhim)
}
struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
- void (*fn) (void *arg), void *arg,
- const char *name)
+ void (*fn)(struct brcms_phy *pi),
+ void *arg, const char *name)
{
return (struct wlapi_timer *)
- brcms_init_timer(physhim->wl, fn, arg, name);
+ brcms_init_timer(physhim->wl, (void (*)(void *))fn,
+ arg, name);
}
-void wlapi_free_timer(struct phy_shim_info *physhim, struct wlapi_timer *t)
+void wlapi_free_timer(struct wlapi_timer *t)
{
- brcms_free_timer(physhim->wl, (struct brcms_timer *)t);
+ brcms_free_timer((struct brcms_timer *)t);
}
void
-wlapi_add_timer(struct phy_shim_info *physhim, struct wlapi_timer *t, uint ms,
- int periodic)
+wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic)
{
- brcms_add_timer(physhim->wl, (struct brcms_timer *)t, ms, periodic);
+ brcms_add_timer((struct brcms_timer *)t, ms, periodic);
}
-bool wlapi_del_timer(struct phy_shim_info *physhim, struct wlapi_timer *t)
+bool wlapi_del_timer(struct wlapi_timer *t)
{
- return brcms_del_timer(physhim->wl, (struct brcms_timer *)t);
+ return brcms_del_timer((struct brcms_timer *)t);
}
void wlapi_intrson(struct phy_shim_info *physhim)
@@ -216,3 +214,12 @@ wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf,
{
brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel);
}
+
+char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id)
+{
+ return getvar(physhim->wlc_hw->sih, id);
+}
+int wlapi_getintvar(struct phy_shim_info *physhim, enum brcms_srom_id id)
+{
+ return getintvar(physhim->wlc_hw->sih, id);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy_shim.h b/drivers/staging/brcm80211/brcmsmac/phy_shim.h
index 2d12bb4400f1..9168c459b185 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy_shim.h
+++ b/drivers/staging/brcm80211/brcmsmac/phy_shim.h
@@ -45,17 +45,17 @@
#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 */
+#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 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 */
@@ -77,26 +77,40 @@
#define WL_TX_POWER_RATES 101
#define WL_TX_POWER_CCK_FIRST 0
#define WL_TX_POWER_CCK_NUM 4
-#define WL_TX_POWER_OFDM_FIRST 4 /* Index for first 20MHz OFDM SISO rate */
-#define WL_TX_POWER_OFDM20_CDD_FIRST 12 /* Index for first 20MHz OFDM CDD rate */
-#define WL_TX_POWER_OFDM40_SISO_FIRST 52 /* Index for first 40MHz OFDM SISO rate */
-#define WL_TX_POWER_OFDM40_CDD_FIRST 60 /* Index for first 40MHz OFDM CDD rate */
+/* 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
-#define WL_TX_POWER_MCS20_SISO_FIRST 20 /* Index for first 20MHz MCS SISO rate */
-#define WL_TX_POWER_MCS20_CDD_FIRST 28 /* Index for first 20MHz MCS CDD rate */
-#define WL_TX_POWER_MCS20_STBC_FIRST 36 /* Index for first 20MHz MCS STBC rate */
-#define WL_TX_POWER_MCS20_SDM_FIRST 44 /* Index for first 20MHz MCS SDM rate */
-#define WL_TX_POWER_MCS40_SISO_FIRST 68 /* Index for first 40MHz MCS SISO rate */
-#define WL_TX_POWER_MCS40_CDD_FIRST 76 /* Index for first 40MHz MCS CDD rate */
-#define WL_TX_POWER_MCS40_STBC_FIRST 84 /* Index for first 40MHz MCS STBC rate */
-#define WL_TX_POWER_MCS40_SDM_FIRST 92 /* Index for first 40MHz MCS SDM rate */
+/* 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
-#define WL_TX_POWER_MCS_32 100 /* Index for 40MHz rate MCS 32 */
+/* Index for 40MHz rate MCS 32 */
+#define WL_TX_POWER_MCS_32 100
#define WL_TX_POWER_MCS_32_NUM 1
/* sslpnphy specifics */
-#define WL_TX_POWER_MCS20_SISO_FIRST_SSN 12 /* Index for first 20MHz MCS SISO rate */
+/* 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
@@ -108,20 +122,20 @@
#define BRCMS_N_TXRX_CHAIN0 0
#define BRCMS_N_TXRX_CHAIN1 1
+struct brcms_phy;
+
extern struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
- void *wl, void *wlc);
+ struct brcms_info *wl,
+ struct brcms_c_info *wlc);
extern void wlc_phy_shim_detach(struct phy_shim_info *physhim);
/* PHY to WL utility functions */
extern struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
- void (*fn) (void *arg), void *arg,
- const char *name);
-extern void wlapi_free_timer(struct phy_shim_info *physhim,
- struct wlapi_timer *t);
-extern void wlapi_add_timer(struct phy_shim_info *physhim,
- struct wlapi_timer *t, uint ms, int periodic);
-extern bool wlapi_del_timer(struct phy_shim_info *physhim,
- struct wlapi_timer *t);
+ void (*fn) (struct brcms_phy *pi),
+ void *arg, const char *name);
+extern void wlapi_free_timer(struct wlapi_timer *t);
+extern void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic);
+extern bool wlapi_del_timer(struct wlapi_timer *t);
extern void wlapi_intrson(struct phy_shim_info *physhim);
extern u32 wlapi_intrsoff(struct phy_shim_info *physhim);
extern void wlapi_intrsrestore(struct phy_shim_info *physhim,
@@ -161,4 +175,8 @@ extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint,
extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim,
u32 phy_mode);
extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim);
+extern char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id);
+extern int wlapi_getintvar(struct phy_shim_info *physhim,
+ enum brcms_srom_id id);
+
#endif /* _BRCM_PHY_SHIM_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/pmu.c b/drivers/staging/brcm80211/brcmsmac/pmu.c
index e8b2b81d2d04..3b36e3acfd74 100644
--- a/drivers/staging/brcm80211/brcmsmac/pmu.c
+++ b/drivers/staging/brcm80211/brcmsmac/pmu.c
@@ -70,11 +70,13 @@
#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<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.
+ */
+/* pllcontrol registers:
+ * ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>,
+ * p1div, p2div, _bypass_sdmod
*/
-/* pllcontrol registers */
-/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
#define PMU1_PLL0_PLLCTL0 0
#define PMU1_PLL0_PLLCTL1 1
#define PMU1_PLL0_PLLCTL2 2
@@ -137,7 +139,8 @@ static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax)
}
static void
-si_pmu_spuravoid_pllupdate(struct si_pub *sih, chipcregs_t *cc, u8 spuravoid)
+si_pmu_spuravoid_pllupdate(struct si_pub *sih, struct chipcregs __iomem *cc,
+ u8 spuravoid)
{
u32 tmp = 0;
@@ -199,28 +202,6 @@ si_pmu_spuravoid_pllupdate(struct si_pub *sih, chipcregs_t *cc, u8 spuravoid)
W_REG(&cc->pmucontrol, tmp);
}
-u32 si_pmu_ilp_clock(struct si_pub *sih)
-{
- static u32 ilpcycles_per_sec;
-
- if (!PMUCTL_ENAB(sih))
- return ILP_CLOCK;
-
- if (ilpcycles_per_sec == 0) {
- u32 start, end, delta;
- u32 origidx = ai_coreidx(sih);
- chipcregs_t *cc = ai_setcoreidx(sih, SI_CC_IDX);
- start = R_REG(&cc->pmutimer);
- mdelay(ILP_CALC_DUR);
- end = R_REG(&cc->pmutimer);
- delta = end - start;
- ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
- ai_setcoreidx(sih, origidx);
- }
-
- return ilpcycles_per_sec;
-}
-
u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
{
uint delay = PMU_MAX_TRANSITION_DLY;
@@ -240,7 +221,7 @@ u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
void si_pmu_sprom_enable(struct si_pub *sih, bool enable)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
/* Remember original core before switch to chipc */
@@ -254,34 +235,37 @@ void si_pmu_sprom_enable(struct si_pub *sih, bool enable)
/* Read/write a chipcontrol reg */
u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
- ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol_addr), ~0,
- reg);
+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol_addr),
+ ~0, reg);
return ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data), mask, val);
+ offsetof(struct chipcregs, chipcontrol_data), mask,
+ val);
}
/* Read/write a regcontrol reg */
u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
- ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, regcontrol_addr), ~0,
- reg);
+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, regcontrol_addr),
+ ~0, reg);
return ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, regcontrol_data), mask, val);
+ offsetof(struct chipcregs, regcontrol_data), mask,
+ val);
}
/* Read/write a pllcontrol reg */
u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
- ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pllcontrol_addr), ~0,
- reg);
+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pllcontrol_addr),
+ ~0, reg);
return ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, pllcontrol_data), mask, val);
+ offsetof(struct chipcregs, pllcontrol_data), mask,
+ val);
}
/* PMU PLL update */
void si_pmu_pllupd(struct si_pub *sih)
{
- ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pmucontrol),
+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pmucontrol),
PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
}
@@ -291,7 +275,7 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
u32 clock = ALP_CLOCK;
/* bail out with default */
- if (!PMUCTL_ENAB(sih))
+ if (!(sih->cccaps & CC_CAP_PMU))
return clock;
switch (sih->chip) {
@@ -310,12 +294,12 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx, intr_val;
/* Remember original core before switch to chipc */
- cc = (chipcregs_t *) ai_switch_core(sih, CC_CORE_ID, &origidx,
- &intr_val);
+ cc = (struct chipcregs __iomem *)
+ ai_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
/* update the pll changes */
si_pmu_spuravoid_pllupdate(sih, cc, spuravoid);
@@ -327,7 +311,7 @@ void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid)
/* initialize PMU */
void si_pmu_init(struct si_pub *sih)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
/* Remember original core before switch to chipc */
@@ -366,7 +350,7 @@ void si_pmu_swreg_init(struct si_pub *sih)
/* initialize PLL */
void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
/* Remember original core before switch to chipc */
@@ -390,7 +374,7 @@ void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq)
/* initialize PMU resources */
void si_pmu_res_init(struct si_pub *sih)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
u32 min_mask = 0, max_mask = 0;
@@ -422,7 +406,7 @@ void si_pmu_res_init(struct si_pub *sih)
u32 si_pmu_measure_alpclk(struct si_pub *sih)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
u32 alp_khz;
diff --git a/drivers/staging/brcm80211/brcmsmac/pmu.h b/drivers/staging/brcm80211/brcmsmac/pmu.h
index 0c7e48c4bcd8..3a08c620640e 100644
--- a/drivers/staging/brcm80211/brcmsmac/pmu.h
+++ b/drivers/staging/brcm80211/brcmsmac/pmu.h
@@ -19,25 +19,11 @@
#define _BRCM_PMU_H_
#include "types.h"
-/*
- * LDO selections used in si_pmu_set_ldo_voltage
- */
-#define SET_LDO_VOLTAGE_LDO1 1
-#define SET_LDO_VOLTAGE_LDO2 2
-#define SET_LDO_VOLTAGE_LDO3 3
-#define SET_LDO_VOLTAGE_PAREF 4
-#define SET_LDO_VOLTAGE_CLDO_PWM 5
-#define SET_LDO_VOLTAGE_CLDO_BURST 6
-#define SET_LDO_VOLTAGE_CBUCK_PWM 7
-#define SET_LDO_VOLTAGE_CBUCK_BURST 8
-#define SET_LDO_VOLTAGE_LNLDO1 9
-#define SET_LDO_VOLTAGE_LNLDO2_SEL 10
extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih);
extern void si_pmu_sprom_enable(struct si_pub *sih, bool enable);
extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
-extern u32 si_pmu_ilp_clock(struct si_pub *sih);
extern u32 si_pmu_alp_clock(struct si_pub *sih);
extern void si_pmu_pllupd(struct si_pub *sih);
extern void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid);
diff --git a/drivers/staging/brcm80211/brcmsmac/pub.h b/drivers/staging/brcm80211/brcmsmac/pub.h
index 01d74609560f..37bb2dcc113f 100644
--- a/drivers/staging/brcm80211/brcmsmac/pub.h
+++ b/drivers/staging/brcm80211/brcmsmac/pub.h
@@ -21,8 +21,265 @@
#include "types.h"
#include "defs.h"
+enum brcms_srom_id {
+ BRCMS_SROM_NULL,
+ BRCMS_SROM_CONT,
+ BRCMS_SROM_AA2G,
+ BRCMS_SROM_AA5G,
+ BRCMS_SROM_AG0,
+ BRCMS_SROM_AG1,
+ BRCMS_SROM_AG2,
+ BRCMS_SROM_AG3,
+ BRCMS_SROM_ANTSWCTL2G,
+ BRCMS_SROM_ANTSWCTL5G,
+ BRCMS_SROM_ANTSWITCH,
+ BRCMS_SROM_BOARDFLAGS2,
+ BRCMS_SROM_BOARDFLAGS,
+ BRCMS_SROM_BOARDNUM,
+ BRCMS_SROM_BOARDREV,
+ BRCMS_SROM_BOARDTYPE,
+ BRCMS_SROM_BW40PO,
+ BRCMS_SROM_BWDUPPO,
+ BRCMS_SROM_BXA2G,
+ BRCMS_SROM_BXA5G,
+ BRCMS_SROM_CC,
+ BRCMS_SROM_CCK2GPO,
+ BRCMS_SROM_CCKBW202GPO,
+ BRCMS_SROM_CCKBW20UL2GPO,
+ BRCMS_SROM_CCODE,
+ BRCMS_SROM_CDDPO,
+ BRCMS_SROM_DEVID,
+ BRCMS_SROM_ET1MACADDR,
+ BRCMS_SROM_EXTPAGAIN2G,
+ BRCMS_SROM_EXTPAGAIN5G,
+ BRCMS_SROM_FREQOFFSET_CORR,
+ BRCMS_SROM_HW_IQCAL_EN,
+ BRCMS_SROM_IL0MACADDR,
+ BRCMS_SROM_IQCAL_SWP_DIS,
+ BRCMS_SROM_LEDBH0,
+ BRCMS_SROM_LEDBH1,
+ BRCMS_SROM_LEDBH2,
+ BRCMS_SROM_LEDBH3,
+ BRCMS_SROM_LEDDC,
+ BRCMS_SROM_LEGOFDM40DUPPO,
+ BRCMS_SROM_LEGOFDMBW202GPO,
+ BRCMS_SROM_LEGOFDMBW205GHPO,
+ BRCMS_SROM_LEGOFDMBW205GLPO,
+ BRCMS_SROM_LEGOFDMBW205GMPO,
+ BRCMS_SROM_LEGOFDMBW20UL2GPO,
+ BRCMS_SROM_LEGOFDMBW20UL5GHPO,
+ BRCMS_SROM_LEGOFDMBW20UL5GLPO,
+ BRCMS_SROM_LEGOFDMBW20UL5GMPO,
+ BRCMS_SROM_MACADDR,
+ BRCMS_SROM_MCS2GPO0,
+ BRCMS_SROM_MCS2GPO1,
+ BRCMS_SROM_MCS2GPO2,
+ BRCMS_SROM_MCS2GPO3,
+ BRCMS_SROM_MCS2GPO4,
+ BRCMS_SROM_MCS2GPO5,
+ BRCMS_SROM_MCS2GPO6,
+ BRCMS_SROM_MCS2GPO7,
+ BRCMS_SROM_MCS32PO,
+ BRCMS_SROM_MCS5GHPO0,
+ BRCMS_SROM_MCS5GHPO1,
+ BRCMS_SROM_MCS5GHPO2,
+ BRCMS_SROM_MCS5GHPO3,
+ BRCMS_SROM_MCS5GHPO4,
+ BRCMS_SROM_MCS5GHPO5,
+ BRCMS_SROM_MCS5GHPO6,
+ BRCMS_SROM_MCS5GHPO7,
+ BRCMS_SROM_MCS5GLPO0,
+ BRCMS_SROM_MCS5GLPO1,
+ BRCMS_SROM_MCS5GLPO2,
+ BRCMS_SROM_MCS5GLPO3,
+ BRCMS_SROM_MCS5GLPO4,
+ BRCMS_SROM_MCS5GLPO5,
+ BRCMS_SROM_MCS5GLPO6,
+ BRCMS_SROM_MCS5GLPO7,
+ BRCMS_SROM_MCS5GPO0,
+ BRCMS_SROM_MCS5GPO1,
+ BRCMS_SROM_MCS5GPO2,
+ BRCMS_SROM_MCS5GPO3,
+ BRCMS_SROM_MCS5GPO4,
+ BRCMS_SROM_MCS5GPO5,
+ BRCMS_SROM_MCS5GPO6,
+ BRCMS_SROM_MCS5GPO7,
+ BRCMS_SROM_MCSBW202GPO,
+ BRCMS_SROM_MCSBW205GHPO,
+ BRCMS_SROM_MCSBW205GLPO,
+ BRCMS_SROM_MCSBW205GMPO,
+ BRCMS_SROM_MCSBW20UL2GPO,
+ BRCMS_SROM_MCSBW20UL5GHPO,
+ BRCMS_SROM_MCSBW20UL5GLPO,
+ BRCMS_SROM_MCSBW20UL5GMPO,
+ BRCMS_SROM_MCSBW402GPO,
+ BRCMS_SROM_MCSBW405GHPO,
+ BRCMS_SROM_MCSBW405GLPO,
+ BRCMS_SROM_MCSBW405GMPO,
+ BRCMS_SROM_MEASPOWER,
+ BRCMS_SROM_OFDM2GPO,
+ BRCMS_SROM_OFDM5GHPO,
+ BRCMS_SROM_OFDM5GLPO,
+ BRCMS_SROM_OFDM5GPO,
+ BRCMS_SROM_OPO,
+ BRCMS_SROM_PA0B0,
+ BRCMS_SROM_PA0B1,
+ BRCMS_SROM_PA0B2,
+ BRCMS_SROM_PA0ITSSIT,
+ BRCMS_SROM_PA0MAXPWR,
+ BRCMS_SROM_PA1B0,
+ BRCMS_SROM_PA1B1,
+ BRCMS_SROM_PA1B2,
+ BRCMS_SROM_PA1HIB0,
+ BRCMS_SROM_PA1HIB1,
+ BRCMS_SROM_PA1HIB2,
+ BRCMS_SROM_PA1HIMAXPWR,
+ BRCMS_SROM_PA1ITSSIT,
+ BRCMS_SROM_PA1LOB0,
+ BRCMS_SROM_PA1LOB1,
+ BRCMS_SROM_PA1LOB2,
+ BRCMS_SROM_PA1LOMAXPWR,
+ BRCMS_SROM_PA1MAXPWR,
+ BRCMS_SROM_PDETRANGE2G,
+ BRCMS_SROM_PDETRANGE5G,
+ BRCMS_SROM_PHYCAL_TEMPDELTA,
+ BRCMS_SROM_RAWTEMPSENSE,
+ BRCMS_SROM_REGREV,
+ BRCMS_SROM_REV,
+ BRCMS_SROM_RSSISAV2G,
+ BRCMS_SROM_RSSISAV5G,
+ BRCMS_SROM_RSSISMC2G,
+ BRCMS_SROM_RSSISMC5G,
+ BRCMS_SROM_RSSISMF2G,
+ BRCMS_SROM_RSSISMF5G,
+ BRCMS_SROM_RXCHAIN,
+ BRCMS_SROM_RXPO2G,
+ BRCMS_SROM_RXPO5G,
+ BRCMS_SROM_STBCPO,
+ BRCMS_SROM_TEMPCORRX,
+ BRCMS_SROM_TEMPOFFSET,
+ BRCMS_SROM_TEMPSENSE_OPTION,
+ BRCMS_SROM_TEMPSENSE_SLOPE,
+ BRCMS_SROM_TEMPTHRESH,
+ BRCMS_SROM_TRI2G,
+ BRCMS_SROM_TRI5GH,
+ BRCMS_SROM_TRI5GL,
+ BRCMS_SROM_TRI5G,
+ BRCMS_SROM_TRISO2G,
+ BRCMS_SROM_TRISO5G,
+ BRCMS_SROM_TSSIPOS2G,
+ BRCMS_SROM_TSSIPOS5G,
+ BRCMS_SROM_TXCHAIN,
+ BRCMS_SROM_TXPID2GA0,
+ BRCMS_SROM_TXPID2GA1,
+ BRCMS_SROM_TXPID2GA2,
+ BRCMS_SROM_TXPID2GA3,
+ BRCMS_SROM_TXPID5GA0,
+ BRCMS_SROM_TXPID5GA1,
+ BRCMS_SROM_TXPID5GA2,
+ BRCMS_SROM_TXPID5GA3,
+ BRCMS_SROM_TXPID5GHA0,
+ BRCMS_SROM_TXPID5GHA1,
+ BRCMS_SROM_TXPID5GHA2,
+ BRCMS_SROM_TXPID5GHA3,
+ BRCMS_SROM_TXPID5GLA0,
+ BRCMS_SROM_TXPID5GLA1,
+ BRCMS_SROM_TXPID5GLA2,
+ BRCMS_SROM_TXPID5GLA3,
+ /*
+ * per-path identifiers (see srom.c)
+ */
+ BRCMS_SROM_ITT2GA0,
+ BRCMS_SROM_ITT2GA1,
+ BRCMS_SROM_ITT2GA2,
+ BRCMS_SROM_ITT2GA3,
+ BRCMS_SROM_ITT5GA0,
+ BRCMS_SROM_ITT5GA1,
+ BRCMS_SROM_ITT5GA2,
+ BRCMS_SROM_ITT5GA3,
+ BRCMS_SROM_MAXP2GA0,
+ BRCMS_SROM_MAXP2GA1,
+ BRCMS_SROM_MAXP2GA2,
+ BRCMS_SROM_MAXP2GA3,
+ BRCMS_SROM_MAXP5GA0,
+ BRCMS_SROM_MAXP5GA1,
+ BRCMS_SROM_MAXP5GA2,
+ BRCMS_SROM_MAXP5GA3,
+ BRCMS_SROM_MAXP5GHA0,
+ BRCMS_SROM_MAXP5GHA1,
+ BRCMS_SROM_MAXP5GHA2,
+ BRCMS_SROM_MAXP5GHA3,
+ BRCMS_SROM_MAXP5GLA0,
+ BRCMS_SROM_MAXP5GLA1,
+ BRCMS_SROM_MAXP5GLA2,
+ BRCMS_SROM_MAXP5GLA3,
+ BRCMS_SROM_PA2GW0A0,
+ BRCMS_SROM_PA2GW0A1,
+ BRCMS_SROM_PA2GW0A2,
+ BRCMS_SROM_PA2GW0A3,
+ BRCMS_SROM_PA2GW1A0,
+ BRCMS_SROM_PA2GW1A1,
+ BRCMS_SROM_PA2GW1A2,
+ BRCMS_SROM_PA2GW1A3,
+ BRCMS_SROM_PA2GW2A0,
+ BRCMS_SROM_PA2GW2A1,
+ BRCMS_SROM_PA2GW2A2,
+ BRCMS_SROM_PA2GW2A3,
+ BRCMS_SROM_PA2GW3A0,
+ BRCMS_SROM_PA2GW3A1,
+ BRCMS_SROM_PA2GW3A2,
+ BRCMS_SROM_PA2GW3A3,
+ BRCMS_SROM_PA5GHW0A0,
+ BRCMS_SROM_PA5GHW0A1,
+ BRCMS_SROM_PA5GHW0A2,
+ BRCMS_SROM_PA5GHW0A3,
+ BRCMS_SROM_PA5GHW1A0,
+ BRCMS_SROM_PA5GHW1A1,
+ BRCMS_SROM_PA5GHW1A2,
+ BRCMS_SROM_PA5GHW1A3,
+ BRCMS_SROM_PA5GHW2A0,
+ BRCMS_SROM_PA5GHW2A1,
+ BRCMS_SROM_PA5GHW2A2,
+ BRCMS_SROM_PA5GHW2A3,
+ BRCMS_SROM_PA5GHW3A0,
+ BRCMS_SROM_PA5GHW3A1,
+ BRCMS_SROM_PA5GHW3A2,
+ BRCMS_SROM_PA5GHW3A3,
+ BRCMS_SROM_PA5GLW0A0,
+ BRCMS_SROM_PA5GLW0A1,
+ BRCMS_SROM_PA5GLW0A2,
+ BRCMS_SROM_PA5GLW0A3,
+ BRCMS_SROM_PA5GLW1A0,
+ BRCMS_SROM_PA5GLW1A1,
+ BRCMS_SROM_PA5GLW1A2,
+ BRCMS_SROM_PA5GLW1A3,
+ BRCMS_SROM_PA5GLW2A0,
+ BRCMS_SROM_PA5GLW2A1,
+ BRCMS_SROM_PA5GLW2A2,
+ BRCMS_SROM_PA5GLW2A3,
+ BRCMS_SROM_PA5GLW3A0,
+ BRCMS_SROM_PA5GLW3A1,
+ BRCMS_SROM_PA5GLW3A2,
+ BRCMS_SROM_PA5GLW3A3,
+ BRCMS_SROM_PA5GW0A0,
+ BRCMS_SROM_PA5GW0A1,
+ BRCMS_SROM_PA5GW0A2,
+ BRCMS_SROM_PA5GW0A3,
+ BRCMS_SROM_PA5GW1A0,
+ BRCMS_SROM_PA5GW1A1,
+ BRCMS_SROM_PA5GW1A2,
+ BRCMS_SROM_PA5GW1A3,
+ BRCMS_SROM_PA5GW2A0,
+ BRCMS_SROM_PA5GW2A1,
+ BRCMS_SROM_PA5GW2A2,
+ BRCMS_SROM_PA5GW2A3,
+ BRCMS_SROM_PA5GW3A0,
+ BRCMS_SROM_PA5GW3A1,
+ BRCMS_SROM_PA5GW3A2,
+ BRCMS_SROM_PA5GW3A3,
+};
+
#define BRCMS_NUMRATES 16 /* max # of rates in a rateset */
-#define MAXMULTILIST 32 /* max # multicast addresses */
#define D11_PHY_HDR_LEN 6 /* Phy header length - 6 bytes */
/* phy types */
@@ -40,10 +297,6 @@
#define BRCMS_20_MHZ 20 /* 20Mhz nphy channel bandwidth */
#define BRCMS_40_MHZ 40 /* 40Mhz nphy channel bandwidth */
-#define CHSPEC_WLC_BW(chanspec) (CHSPEC_IS40(chanspec) ? BRCMS_40_MHZ : \
- CHSPEC_IS20(chanspec) ? BRCMS_20_MHZ : \
- BRCMS_10_MHZ)
-
#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 */
@@ -52,13 +305,6 @@
#define BRCMS_RSSI_VERY_GOOD -58 /* Very good quality cutoffs */
#define BRCMS_RSSI_EXCELLENT -57 /* Excellent quality cutoffs */
-/* macro to perform PHY -> D11 PHY TYPE, currently 1:1 */
-#define BRCMS_PHYTYPE(_x) (_x)
-
-#define MA_WINDOW_SZ 8 /* moving average window size */
-
-#define BRCMS_SNR_INVALID 0 /* invalid SNR value */
-
/* 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
*/
@@ -69,63 +315,58 @@
#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 */
-#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */
+#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 */
-#define ANT_TX_FORCE_0 0 /* Tx on antenna 0, "legacy term Main" */
-#define ANT_TX_FORCE_1 1 /* Tx on antenna 1, "legacy term Aux" */
-#define ANT_TX_LAST_RX 3 /* Tx on phy's last good Rx antenna */
-#define ANT_TX_DEF 3 /* driver's default tx antenna setting */
-
-#define TXCORE_POLICY_ALL 0x1 /* use all available core for transmit */
+/* 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 */
-#define TXCHAIN_DEF 0x1 /* def bitmap of txchain */
-#define TXCHAIN_DEF_NPHY 0x3 /* default bitmap of tx chains for nphy */
-#define TXCHAIN_DEF_HTPHY 0x7 /* default bitmap of tx chains for nphy */
-#define RXCHAIN_DEF 0x1 /* def bitmap of rxchain */
-#define RXCHAIN_DEF_NPHY 0x3 /* default bitmap of rx chains for nphy */
-#define RXCHAIN_DEF_HTPHY 0x7 /* default bitmap of rx chains for nphy */
-#define ANTSWITCH_NONE 0 /* no antenna switch */
-#define ANTSWITCH_TYPE_1 1 /* antenna switch on 4321CB2, 2of3 */
-#define ANTSWITCH_TYPE_2 2 /* antenna switch on 4321MPCI, 2of3 */
-#define ANTSWITCH_TYPE_3 3 /* antenna switch on 4322, 2of3 */
+/* 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
-#ifndef AIDMAPSZ
-#define AIDMAPSZ (roundup(MAXSCB, NBBY)/NBBY) /* aid bitmap size in bytes */
-#endif /* AIDMAPSZ */
#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */
-#define WL_SPURAVOID_OFF 0
-#define WL_SPURAVOID_ON1 1
-#define WL_SPURAVOID_ON2 2
-
-struct brcms_tunables {
- int ntxd; /* size of tx descriptor table */
- int nrxd; /* size of rx descriptor table */
- int rxbufsz; /* size of rx buffers to post */
- int nrxbufpost; /* # of rx buffers to post */
- int maxscb; /* # of SCBs supported */
- int ampdunummpdu; /* max number of mpdu in an ampdu */
- int maxpktcb; /* max # of packet callbacks */
- int maxucodebss; /* max # of BSS handled in ucode bcn/prb */
- int maxucodebss4; /* max # of BSS handled in sw bcn/prb */
- int maxbss; /* max # of bss info elements in scan list */
- int datahiwat; /* data msg txq hiwat mark */
- int ampdudatahiwat; /* AMPDU msg txq hiwat mark */
- int rxbnd; /* max # of rx bufs to process before deferring to dpc */
- int txsbnd; /* max # tx status to process in wlc_txstatus() */
- int memreserved; /* memory reserved for BMAC's USB dma rx */
+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_rateset {
+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];
@@ -133,34 +374,11 @@ struct brcms_rateset {
u8 mcs[MCSSET_LEN]; /* supported mcs index bit map */
};
-struct rsn_parms {
- u8 flags; /* misc booleans (e.g., supported) */
- u8 multicast; /* multicast cipher */
- u8 ucount; /* count of unicast ciphers */
- u8 unicast[4]; /* unicast ciphers */
- u8 acount; /* count of auth modes */
- u8 auth[4]; /* Authentication modes */
- u8 PAD[4]; /* padding for future growth */
-};
-
-/*
- * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
- */
-#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1)
-
-#define RSN_FLAGS_SUPPORTED 0x1 /* Flag for rsn_params */
-#define RSN_FLAGS_PREAUTH 0x2 /* Flag for WPA2 rsn_params */
-
/* 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) */
-/* defaults for the HT (MIMO) bss */
-#define HT_CAP (IEEE80211_HT_CAP_SM_PS |\
- IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_GRN_FLD |\
- IEEE80211_HT_CAP_MAX_AMSDU | IEEE80211_HT_CAP_DSSSCCK40)
-
/* wlc internal bss_info */
struct brcms_bss_info {
u8 BSSID[ETH_ALEN]; /* network BSSID */
@@ -170,200 +388,55 @@ struct brcms_bss_info {
s16 RSSI; /* receive signal strength (in dBm) */
s16 SNR; /* receive signal SNR in dB */
u16 beacon_period; /* units are Kusec */
- u16 atim_window; /* units are Kusec */
- chanspec_t chanspec; /* Channel num, bw, ctrl_sb and band */
- s8 infra; /* 0=IBSS, 1=infrastructure, 2=unknown */
- wlc_rateset_t rateset; /* supported rates */
- u8 dtim_period; /* DTIM period */
- s8 phy_noise; /* noise right after tx (in dBm) */
- u16 capability; /* Capability information */
- u8 wme_qosinfo; /* QoS Info from WME IE; valid if BSS_WME flag set */
- struct rsn_parms wpa;
- struct rsn_parms wpa2;
- u16 qbss_load_aac; /* qbss load available admission capacity */
- /* qbss_load_chan_free <- (0xff - channel_utilization of qbss_load_ie_t) */
- u8 qbss_load_chan_free; /* indicates how free the channel is */
- u8 mcipher; /* multicast cipher */
- u8 wpacfg; /* wpa config index */
+ u16 chanspec; /* Channel num, bw, ctrl_sb and band */
+ struct brcms_c_rateset rateset; /* supported rates */
};
-/* IOVar flags for common error checks */
-#define IOVF_MFG (1<<3) /* flag for mfgtest iovars */
-#define IOVF_WHL (1<<4) /* value must be whole (0-max) */
-#define IOVF_NTRL (1<<5) /* value must be natural (1-max) */
-
-#define IOVF_SET_UP (1<<6) /* set requires driver be up */
-#define IOVF_SET_DOWN (1<<7) /* set requires driver be down */
-#define IOVF_SET_CLK (1<<8) /* set requires core clock */
-#define IOVF_SET_BAND (1<<9) /* set requires fixed band */
-
-#define IOVF_GET_UP (1<<10) /* get requires driver be up */
-#define IOVF_GET_DOWN (1<<11) /* get requires driver be down */
-#define IOVF_GET_CLK (1<<12) /* get requires core clock */
-#define IOVF_GET_BAND (1<<13) /* get requires fixed band */
-#define IOVF_OPEN_ALLOW (1<<14) /* set allowed iovar for opensrc */
-
-/* watchdog down and dump callback function proto's */
-typedef int (*watchdog_fn_t) (void *handle);
-typedef int (*down_fn_t) (void *handle);
-typedef int (*dump_fn_t) (void *handle, struct brcmu_strbuf *b);
-
-/* IOVar handler
- *
- * handle - a pointer value registered with the function
- * vi - iovar_info that was looked up
- * actionid - action ID, calculated by IOV_GVAL() and IOV_SVAL() based on varid.
- * name - the actual iovar name
- * params/plen - parameters and length for a get, input only.
- * arg/len - buffer and length for value to be set or retrieved, input or output.
- * vsize - value size, valid for integer type only.
- * wlcif - interface context (brcms_c_if pointer)
- *
- * All pointers may point into the same buffer.
- */
-typedef int (*iovar_fn_t) (void *handle, const struct brcmu_iovar *vi,
- u32 actionid, const char *name, void *params,
- uint plen, void *arg, int alen, int vsize,
- struct brcms_c_if *wlcif);
-
#define MAC80211_PROMISC_BCNS (1 << 0)
#define MAC80211_SCAN (1 << 1)
/*
- * Public portion of "common" os-independent state structure.
+ * Public portion of common driver state structure.
* The wlc handle points at this.
*/
struct brcms_pub {
- void *wlc;
-
+ struct brcms_c_info *wlc;
struct ieee80211_hw *ieee_hw;
- struct scb *global_scb;
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) */
- char *vars; /* "environment" name=value */
bool up; /* interface up and running */
bool hw_off; /* HW is off */
- /* tunables: ntxd, nrxd, maxscb, etc. */
- struct brcms_tunables *tunables;
- bool hw_up; /* one time hw up/down(from boot or hibernation) */
- bool _piomode; /* true if pio mode *//* BMAC_NOTE: NEED In both */
+ bool hw_up; /* one time hw up/down */
+ bool _piomode; /* true if pio mode */
uint _nbands; /* # bands supported */
uint now; /* # elapsed seconds */
bool promisc; /* promiscuous destination address */
bool delayed_down; /* down delayed */
- bool _ap; /* AP mode enabled */
- bool _apsta; /* simultaneous AP/STA mode enabled */
- bool _assoc_recreate; /* association recreation on up transitions */
- int _wme; /* WME QoS mode */
- u8 _mbss; /* MBSS mode on */
- bool allmulti; /* enable all multicasts */
bool associated; /* true:part of [I]BSS, false: not */
/* (union of stas_associated, aps_associated) */
- bool phytest_on; /* whether a PHY test is running */
- bool bf_preempt_4306; /* True to enable 'darwin' mode */
bool _ampdu; /* ampdu enabled or not */
- bool _cac; /* 802.11e CAC enabled */
u8 _n_enab; /* bitmap of 11N + HT support */
- bool _n_reqd; /* N support required for clients */
-
- s8 _coex; /* 20/40 MHz BSS Management AUTO, ENAB, DISABLE */
- bool _priofc; /* Priority-based flowcontrol */
u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */
- u8 *multicast; /* ptr to list of multicast addresses */
- uint nmulticast; /* # enabled multicast addresses */
-
- u32 wlfeatureflag; /* Flags to control sw features from registry */
- int psq_pkts_total; /* total num of ps pkts */
-
- u16 txmaxpkts; /* max number of large pkts allowed to be pending */
-
- /* s/w decryption counters */
- u32 swdecrypt; /* s/w decrypt attempts */
-
int bcmerror; /* last bcm error */
- mbool radio_disabled; /* bit vector for radio disabled reasons */
- bool radio_active; /* radio on/off state */
- u16 roam_time_thresh; /* Max. # secs. of not hearing beacons
- * before roaming.
- */
- bool align_wd_tbtt; /* Align watchdog with tbtt indication
- * handling. This flag is cleared by default
- * and is set by per port code explicitly and
- * you need to make sure the OSL_SYSUPTIME()
- * is implemented properly in osl of that port
- * when it enables this Power Save feature.
- */
+ 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 tempsense_disable; /* disable periodic tempsense check */
bool phy_11ncapable; /* the PHY/HW is capable of 802.11N */
- bool _ampdumac; /* mac assist ampdu enabled or not */
struct wl_cnt *_cnt; /* low-level counters in driver */
};
-/* wl_monitor rx status per packet */
-struct wl_rxsts {
- uint pkterror; /* error flags per pkt */
- uint phytype; /* 802.11 A/B/G ... */
- uint channel; /* channel */
- uint datarate; /* rate in 500kbps */
- uint antenna; /* antenna pkts received on */
- uint pktlength; /* pkt length minus bcm phy hdr */
- u32 mactime; /* time stamp from mac, count per 1us */
- uint sq; /* signal quality */
- s32 signal; /* in dbm */
- s32 noise; /* in dbm */
- uint preamble; /* Unknown, short, long */
- uint encoding; /* Unknown, CCK, PBCC, OFDM */
- uint nfrmtype; /* special 802.11n frames(AMPDU, AMSDU) */
- struct brcms_if *wlif; /* wl interface */
-};
-
-/* status per error RX pkt */
-#define WL_RXS_CRC_ERROR 0x00000001 /* CRC Error in packet */
-#define WL_RXS_RUNT_ERROR 0x00000002 /* Runt packet */
-#define WL_RXS_ALIGN_ERROR 0x00000004 /* Misaligned packet */
-#define WL_RXS_OVERSIZE_ERROR 0x00000008 /* packet bigger than RX_LENGTH (usually 1518) */
-#define WL_RXS_WEP_ICV_ERROR 0x00000010 /* Integrity Check Value error */
-#define WL_RXS_WEP_ENCRYPTED 0x00000020 /* Encrypted with WEP */
-#define WL_RXS_PLCP_SHORT 0x00000040 /* Short PLCP error */
-#define WL_RXS_DECRYPT_ERR 0x00000080 /* Decryption error */
-#define WL_RXS_OTHER_ERR 0x80000000 /* Other errors */
-
-/* phy type */
-#define WL_RXS_PHY_A 0x00000000 /* A phy type */
-#define WL_RXS_PHY_B 0x00000001 /* B phy type */
-#define WL_RXS_PHY_G 0x00000002 /* G phy type */
-#define WL_RXS_PHY_N 0x00000004 /* N phy type */
-
-/* encoding */
-#define WL_RXS_ENCODING_CCK 0x00000000 /* CCK encoding */
-#define WL_RXS_ENCODING_OFDM 0x00000001 /* OFDM encoding */
-
-/* preamble */
-#define WL_RXS_UNUSED_STUB 0x0 /* stub to match with wlc_ethereal.h */
-#define WL_RXS_PREAMBLE_SHORT 0x00000001 /* Short preamble */
-#define WL_RXS_PREAMBLE_LONG 0x00000002 /* Long preamble */
-#define WL_RXS_PREAMBLE_MIMO_MM 0x00000003 /* MIMO mixed mode preamble */
-#define WL_RXS_PREAMBLE_MIMO_GF 0x00000004 /* MIMO green field preamble */
-
-#define WL_RXS_NFRM_AMPDU_FIRST 0x00000001 /* first MPDU in A-MPDU */
-#define WL_RXS_NFRM_AMPDU_SUB 0x00000002 /* subsequent MPDU(s) in A-MPDU */
-#define WL_RXS_NFRM_AMSDU_FIRST 0x00000004 /* first MSDU in A-MSDU */
-#define WL_RXS_NFRM_AMSDU_SUB 0x00000008 /* subsequent MSDU(s) in A-MSDU */
-
enum wlc_par_id {
IOV_MPC = 1,
IOV_RTSTHRESH,
@@ -376,49 +449,15 @@ enum wlc_par_id {
* *********************************************
*/
-/* AP Support (versus STA) */
-#define AP_ENAB(pub) (0)
-
-/* Macro to check if APSTA mode enabled */
-#define APSTA_ENAB(pub) (0)
-
-/* Some useful combinations */
-#define STA_ONLY(pub) (!AP_ENAB(pub))
-#define AP_ONLY(pub) (AP_ENAB(pub) && !APSTA_ENAB(pub))
-
#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 */
-#if ((defined(NCONF) && (NCONF != 0)) || (defined(LCNCONF) && (LCNCONF != 0)) || \
- (defined(HTCONF) && (HTCONF != 0)) || (defined(SSLPNCONF) && (SSLPNCONF != 0)))
-#define N_ENAB(pub) ((pub)->_n_enab & SUPPORT_11N)
-#define N_REQD(pub) ((pub)->_n_reqd)
-#else
-#define N_ENAB(pub) 0
-#define N_REQD(pub) 0
-#endif
-
-#if (defined(HTCONF) && (HTCONF != 0))
-#define HT_ENAB(pub) (((pub)->_n_enab & SUPPORT_HT) == SUPPORT_HT)
-#else
-#define HT_ENAB(pub) 0
-#endif
+/* WL11N Support */
#define AMPDU_AGG_HOST 1
-#define AMPDU_ENAB(pub) ((pub)->_ampdu)
-
-#define EDCF_ENAB(pub) (WME_ENAB(pub))
-#define QOS_ENAB(pub) (WME_ENAB(pub) || N_ENAB(pub))
-
-#define MONITOR_ENAB(wlc) ((wlc)->monitor)
-
-#define PROMISC_ENAB(wlc) ((wlc)->promisc)
-
-#define BRCMS_PREC_COUNT 16 /* Max precedence level implemented */
/* pri is priority encoded in the packet. This maps the Packet priority to
* enqueue precedence as defined in wlc_prec_map
@@ -426,18 +465,19 @@ enum wlc_par_id {
extern const u8 wlc_prio2prec_map[];
#define BRCMS_PRIO_TO_PREC(pri) wlc_prio2prec_map[(pri) & 7]
-/* This maps priority to one precedence higher - Used by PS-Poll response packets to
- * simulate enqueue-at-head operation, but still maintain the order on the queue
- */
-#define BRCMS_PRIO_TO_HI_PREC(pri) min(BRCMS_PRIO_TO_PREC(pri) + 1,\
- BRCMS_PREC_COUNT - 1)
-
-extern const u8 wme_fifo2ac[];
-#define WME_PRIO2AC(prio) wme_fifo2ac[prio2fifo[(prio)]]
+#define BRCMS_PREC_COUNT 16 /* Max precedence level implemented */
/* Mask to describe all precedence levels */
#define BRCMS_PREC_BMP_ALL MAXBITVAL(BRCMS_PREC_COUNT)
+/*
+ * This maps priority to one precedence higher - Used by PS-Poll response
+ * packets to simulate enqueue-at-head operation, but still maintain the
+ * order on the queue
+ */
+#define BRCMS_PRIO_TO_HI_PREC(pri) min(BRCMS_PRIO_TO_PREC(pri) + 1,\
+ BRCMS_PREC_COUNT - 1)
+
/* Define a bitmap of precedences comprised by each AC */
#define BRCMS_PREC_BMP_AC_BE (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BE)) | \
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BE)) | \
@@ -456,14 +496,6 @@ extern const u8 wme_fifo2ac[];
NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NC)) | \
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NC)))
-/* WME Support */
-#define WME_ENAB(pub) ((pub)->_wme != OFF)
-#define WME_AUTO(wlc) ((wlc)->pub->_wme == AUTO)
-
-/* invalid core flags, use the saved coreflags */
-#define BRCMS_USE_COREFLAGS 0xffffffff
-
-
/* network protection config */
#define BRCMS_PROT_G_SPEC 1 /* SPEC g protection */
#define BRCMS_PROT_G_OVR 2 /* SPEC g prot override */
@@ -480,28 +512,34 @@ extern const u8 wme_fifo2ac[];
/*
* 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
+ * 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
@@ -511,58 +549,13 @@ extern const u8 wme_fifo2ac[];
#define GMODE_LRS 5
#define GMODE_MAX 6
-/* values for PLCPHdr_override */
-#define BRCMS_PLCP_AUTO -1
-#define BRCMS_PLCP_SHORT 0
-#define BRCMS_PLCP_LONG 1
-
-/* values for g_protection_override and n_protection_override */
-#define BRCMS_PROTECTION_AUTO -1
-#define BRCMS_PROTECTION_OFF 0
-#define BRCMS_PROTECTION_ON 1
-#define BRCMS_PROTECTION_MMHDR_ONLY 2
-#define BRCMS_PROTECTION_CTS_ONLY 3
-
-/* values for g_protection_control and n_protection_control */
-#define BRCMS_PROTECTION_CTL_OFF 0
-#define BRCMS_PROTECTION_CTL_LOCAL 1
-#define BRCMS_PROTECTION_CTL_OVERLAP 2
-
-/* values for n_protection */
-#define BRCMS_N_PROTECTION_OFF 0
-#define BRCMS_N_PROTECTION_OPTIONAL 1
-#define BRCMS_N_PROTECTION_20IN40 2
-#define BRCMS_N_PROTECTION_MIXEDMODE 3
-
-/* values for band specific 40MHz capabilities */
-#define BRCMS_N_BW_20ALL 0
-#define BRCMS_N_BW_40ALL 1
-#define BRCMS_N_BW_20IN2G_40IN5G 2
-
-/* bitflags for SGI support (sgi_rx iovar) */
-#define BRCMS_N_SGI_20 0x01
-#define BRCMS_N_SGI_40 0x02
-
-/* defines used by the nrate iovar */
-#define NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */
-#define NRATE_RATE_MASK 0x0000007f /* rate/mcs value */
-#define NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */
-#define NRATE_STF_SHIFT 8 /* stf mode shift */
-#define NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */
-#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */
-#define NRATE_SGI_MASK 0x00800000 /* sgi mode */
-#define NRATE_SGI_SHIFT 23 /* sgi mode */
-#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */
-#define NRATE_LDPC_SHIFT 22 /* ldpc shift */
-
-#define NRATE_STF_SISO 0 /* stf mode SISO */
-#define NRATE_STF_CDD 1 /* stf mode CDD */
-#define NRATE_STF_STBC 2 /* stf mode STBC */
-#define NRATE_STF_SDM 3 /* stf mode SDM */
-
-#define ANT_SELCFG_MAX 4 /* max number of antenna configurations */
-
-#define HIGHEST_SINGLE_STREAM_MCS 7 /* MCS values greater than this enable multiple streams */
+/* 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 */
@@ -570,15 +563,14 @@ struct brcms_antselcfg {
};
/* common functions for every port */
-extern void *brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device,
- uint unit, bool piomode, void *regsva, uint bustype,
- void *btparam, uint *perr);
+extern struct brcms_c_info *
+brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
+ bool piomode, void __iomem *regsva, struct pci_dev *btparam,
+ uint *perr);
extern uint brcms_c_detach(struct brcms_c_info *wlc);
extern int brcms_c_up(struct brcms_c_info *wlc);
extern uint brcms_c_down(struct brcms_c_info *wlc);
-extern int brcms_c_set(struct brcms_c_info *wlc, int cmd, int arg);
-extern int brcms_c_get(struct brcms_c_info *wlc, int cmd, int *arg);
extern bool brcms_c_chipmatch(u16 vendor, u16 device);
extern void brcms_c_init(struct brcms_c_info *wlc);
extern void brcms_c_reset(struct brcms_c_info *wlc);
@@ -589,55 +581,31 @@ extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask);
extern bool brcms_c_intrsupd(struct brcms_c_info *wlc);
extern bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc);
extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded);
-extern bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc,
+extern void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc,
struct sk_buff *sdu,
struct ieee80211_hw *hw);
-extern int brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
- struct brcms_c_if *wlcif);
extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid);
-
-/* helper functions */
-extern void brcms_c_statsupd(struct brcms_c_info *wlc);
extern void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx,
int val);
extern int brcms_c_get_header_len(void);
-extern void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc,
- bool promisc);
extern void brcms_c_set_addrmatch(struct brcms_c_info *wlc,
int match_reg_offset,
const u8 *addr);
extern void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
const struct ieee80211_tx_queue_params *arg,
bool suspend);
-extern struct brcms_pub *brcms_c_pub(void *wlc);
-
-/* common functions for every port */
-extern void brcms_c_mhf(struct brcms_c_info *wlc, u8 idx, u16 mask, u16 val,
- int bands);
-extern void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
- wlc_rateset_t *rateset);
-extern void brcms_default_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs);
-
+extern struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc);
extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
struct ieee80211_sta *sta, u16 tid);
extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
u8 ba_wsize, uint max_rx_ampdu_bytes);
-extern int brcms_c_set_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
- int val);
-extern int brcms_c_get_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
- int *ret_int_ptr);
-extern char *getvar(char *vars, const char *name);
-extern int getintvar(char *vars, const char *name);
-
-/* wlc_phy.c helper functions */
-extern void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc);
-extern void brcms_c_mctrl(struct brcms_c_info *wlc, u32 mask, u32 val);
-
+extern char *getvar(struct si_pub *sih, enum brcms_srom_id id);
+extern int getintvar(struct si_pub *sih, enum brcms_srom_id id);
extern int brcms_c_module_register(struct brcms_pub *pub,
- const char *name, void *hdl,
- watchdog_fn_t watchdog_fn, down_fn_t down_fn);
+ const char *name, struct brcms_info *hdl,
+ int (*down_fn)(void *handle));
extern int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
- void *hdl);
+ struct brcms_info *hdl);
extern void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc);
extern void brcms_c_enable_mac(struct brcms_c_info *wlc);
extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);
@@ -646,20 +614,21 @@ extern void brcms_c_scan_stop(struct brcms_c_info *wlc);
extern int brcms_c_get_curband(struct brcms_c_info *wlc);
extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc,
bool drop);
-
-/* helper functions */
+extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);
+extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);
+extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
+ struct brcm_rateset *currs);
+extern int brcms_c_set_rateset(struct brcms_c_info *wlc,
+ struct brcm_rateset *rs);
+extern int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period);
+extern u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx);
+extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc,
+ s8 sslot_override);
+extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
+ u8 interval);
+extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
+extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
+extern void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc);
extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
-extern bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc);
-
-#define MAXBANDS 2 /* Maximum #of bands */
-/* bandstate array indices */
-#define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */
-#define BAND_5G_INDEX 1 /* wlc->bandstate[x] index */
-
-#define BAND_2G_NAME "2.4G"
-#define BAND_5G_NAME "5G"
-
-/* BMAC RPC: 7 u32 params: pkttotlen, fifo, commit, fid, txpktpend, pktflag, rpc_id */
-#define BRCMS_RPCTX_PARAMS 32
#endif /* _BRCM_PUB_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/rate.c b/drivers/staging/brcm80211/brcmsmac/rate.c
index f0e4b99c2566..0a0c0ad4f96f 100644
--- a/drivers/staging/brcm80211/brcmsmac/rate.c
+++ b/drivers/staging/brcm80211/brcmsmac/rate.c
@@ -21,7 +21,10 @@
#include "pub.h"
#include "rate.h"
-/* Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate value */
+/*
+ * 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,
@@ -139,20 +142,25 @@ const struct brcms_mcs_info mcs_table[MCS_TABLE_SIZE] = {
{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
+/*
+ * 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 */
- u8 tx_phy_ctl3; /* phy ctl byte 3, code rate, modulation type, # of streams */
+ /* phy ctl byte 3, code rate, modulation type, # of streams */
+ u8 tx_phy_ctl3;
};
-#define LEGACY_PHYCFG_TABLE_SIZE 12 /* Number of legacy_rate_cfg entries in the table */
+/* 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 */
+/*
+ * 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 */
@@ -179,86 +187,89 @@ legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
/* Hardware rates (also encodes default basic rates) */
-const wlc_rateset_t cck_ofdm_mimo_rates = {
+const struct brcms_c_rateset cck_ofdm_mimo_rates = {
12,
- { /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */
- 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
- 0x6c},
+ /* 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}
+ { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t ofdm_mimo_rates = {
+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},
+ /* 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}
+ { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
/* Default ratesets that include MCS32 for 40BW channels */
-const wlc_rateset_t cck_ofdm_40bw_mimo_rates = {
+static const struct brcms_c_rateset cck_ofdm_40bw_mimo_rates = {
12,
- { /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */
- 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
- 0x6c},
+ /* 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}
+ { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t ofdm_40bw_mimo_rates = {
+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},
+ /* 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}
+ { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t cck_ofdm_rates = {
+const struct brcms_c_rateset cck_ofdm_rates = {
12,
- { /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */
- 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
- 0x6c},
+ /* 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}
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t gphy_legacy_rates = {
+const struct brcms_c_rateset gphy_legacy_rates = {
4,
- { /* 1b, 2b, 5.5b, 11b Mbps */
- 0x82, 0x84, 0x8b, 0x96},
+ /* 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}
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t ofdm_rates = {
+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},
+ /* 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}
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t cck_rates = {
+const struct brcms_c_rateset cck_rates = {
4,
- { /* 1b, 2b, 5.5, 11 Mbps */
- 0x82, 0x84, 0x0b, 0x16},
+ /* 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}
+ { 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(wlc_rateset_t *rs, bool check_brate)
+static bool brcms_c_rateset_valid(struct brcms_c_rateset *rs, bool check_brate)
{
uint idx;
@@ -276,19 +287,20 @@ static bool brcms_c_rateset_valid(wlc_rateset_t *rs, bool check_brate)
return false;
}
-void brcms_c_rateset_mcs_upd(wlc_rateset_t *rs, u8 txstreams)
+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.
+/*
+ * 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(wlc_rateset_t *rs,
- const wlc_rateset_t *hw_rs,
+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];
@@ -328,10 +340,10 @@ brcms_c_rate_hwrs_filter_sort_validate(wlc_rateset_t *rs,
}
/* calculate the rate of a rx'd frame and return it as a ratespec */
-ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
+u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
{
int phy_type;
- ratespec_t rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
+ u32 rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
phy_type =
((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT);
@@ -341,12 +353,12 @@ ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) {
case PRXS0_CCK:
rspec =
- CCK_PHY2MAC_RATE(
+ cck_phy2mac_rate(
((struct cck_phy_hdr *) plcp)->signal);
break;
case PRXS0_OFDM:
rspec =
- OFDM_PHY2MAC_RATE(
+ ofdm_phy2mac_rate(
((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
break;
case PRXS0_PREN:
@@ -363,23 +375,24 @@ ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
/* not supported, error condition */
break;
}
- if (PLCP3_ISSGI(plcp[3]))
+ 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(
+ rspec = ofdm_phy2mac_rate(
((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
else
- rspec = CCK_PHY2MAC_RATE(
+ 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 wlc_rateset_t *src, wlc_rateset_t *dst)
+void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
+ struct brcms_c_rateset *dst)
{
- memcpy(dst, src, sizeof(wlc_rateset_t));
+ memcpy(dst, src, sizeof(struct brcms_c_rateset));
}
/*
@@ -392,8 +405,8 @@ void brcms_c_rateset_copy(const wlc_rateset_t *src, wlc_rateset_t *dst)
* 'xmask' is the copy mask (typically 0x7f or 0xff).
*/
void
-brcms_c_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
- u8 rates, uint xmask, bool mcsallow)
+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;
@@ -404,9 +417,11 @@ brcms_c_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
r = src->rates[i];
if (basic_only && !(r & BRCMS_RATE_FLAG))
continue;
- if (rates == BRCMS_RATES_CCK && IS_OFDM((r & BRCMS_RATE_MASK)))
+ if (rates == BRCMS_RATES_CCK &&
+ is_ofdm_rate((r & BRCMS_RATE_MASK)))
continue;
- if (rates == BRCMS_RATES_OFDM && IS_CCK((r & BRCMS_RATE_MASK)))
+ if (rates == BRCMS_RATES_OFDM &&
+ is_cck_rate((r & BRCMS_RATE_MASK)))
continue;
dst->rates[count++] = r & xmask;
}
@@ -423,26 +438,27 @@ brcms_c_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
* and fill rs_tgt with result
*/
void
-brcms_c_rateset_default(wlc_rateset_t *rs_tgt, const wlc_rateset_t *rs_hw,
- uint phy_type, int bandtype, bool cck_only, uint rate_mask,
- bool mcsallow, u8 bw, u8 txstreams)
+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 wlc_rateset_t *rs_dflt;
- wlc_rateset_t rs_sel;
+ 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 (BAND_5G(bandtype)) {
+ if (bandtype == BRCM_BAND_5G)
rs_dflt = (bw == BRCMS_20_MHZ ?
&ofdm_mimo_rates : &ofdm_40bw_mimo_rates);
- } else {
+ 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 = (BAND_5G(bandtype)) ? &ofdm_rates : &cck_ofdm_rates;
+ 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)) {
@@ -475,21 +491,21 @@ s16 brcms_c_rate_legacy_phyctl(uint rate)
return -1;
}
-void brcms_c_rateset_mcs_clear(wlc_rateset_t *rateset)
+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(wlc_rateset_t *rateset, u8 txstreams)
+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(wlc_rateset_t *rateset, u8 bw)
+void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw)
{
if (bw == BRCMS_40_MHZ)
setbit(rateset->mcs, 32);
diff --git a/drivers/staging/brcm80211/brcmsmac/rate.h b/drivers/staging/brcm80211/brcmsmac/rate.h
index dbfd3e5816d4..e7b9dc2f2731 100644
--- a/drivers/staging/brcm80211/brcmsmac/rate.h
+++ b/drivers/staging/brcm80211/brcmsmac/rate.h
@@ -18,156 +18,233 @@
#define _BRCM_RATE_H_
#include "types.h"
+#include "d11.h"
extern const u8 rate_info[];
-extern const struct brcms_rateset cck_ofdm_mimo_rates;
-extern const struct brcms_rateset ofdm_mimo_rates;
-extern const struct brcms_rateset cck_ofdm_rates;
-extern const struct brcms_rateset ofdm_rates;
-extern const struct brcms_rateset cck_rates;
-extern const struct brcms_rateset gphy_legacy_rates;
-extern const struct brcms_rateset wlc_lrs_rates;
-extern const struct brcms_rateset rate_limit_1_2;
+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 {
- u32 phy_rate_20; /* phy rate in kbps [20Mhz] */
- u32 phy_rate_40; /* phy rate in kbps [40Mhz] */
- u32 phy_rate_20_sgi; /* phy rate in kbps [20Mhz] with SGI */
- u32 phy_rate_40_sgi; /* phy rate in kbps [40Mhz] with SGI */
- u8 tx_phy_ctl3; /* phy ctl byte 3, code rate, modulation type, # of streams */
- u8 leg_ofdm; /* matching legacy ofdm rate in 500bkps */
+ /* 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_INVALID 0xFF
-#define MCS_CR_MASK 0x07 /* Code Rate bit mask */
-#define MCS_MOD_MASK 0x38 /* Modulation bit shift */
-#define MCS_MOD_SHIFT 3 /* MOdulation bit shift */
#define MCS_TXS_MASK 0xc0 /* num tx streams - 1 bit mask */
#define MCS_TXS_SHIFT 6 /* num tx streams - 1 bit shift */
-#define MCS_CR(_mcs) (mcs_table[_mcs].tx_phy_ctl3 & MCS_CR_MASK)
-#define MCS_MOD(_mcs) ((mcs_table[_mcs].tx_phy_ctl3 & MCS_MOD_MASK) >> MCS_MOD_SHIFT)
-#define MCS_TXS(_mcs) ((mcs_table[_mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT)
-#define MCS_RATE(_mcs, _is40, _sgi) (_sgi ? \
- (_is40 ? mcs_table[_mcs].phy_rate_40_sgi : mcs_table[_mcs].phy_rate_20_sgi) : \
- (_is40 ? mcs_table[_mcs].phy_rate_40 : mcs_table[_mcs].phy_rate_20))
-#define VALID_MCS(_mcs) ((_mcs < MCS_TABLE_SIZE))
+
+/* 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 */
-/* convert 500kbps to bps */
-#define BRCMS_RATE_500K_TO_BPS(rate) ((rate) * 500000)
-
-/* 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 : 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 */
-#define RSPEC_RATE_MASK 0x0000007F /* Either 500Kbps units or MIMO MCS idx */
-#define RSPEC_MIMORATE 0x08000000 /* mimo MCS is stored in RSPEC_RATE_MASK */
-#define RSPEC_BW_MASK 0x00000700 /* mimo bw mask */
-#define RSPEC_BW_SHIFT 8 /* mimo bw shift */
-#define RSPEC_STF_MASK 0x00003800 /* mimo Space/Time/Frequency mode mask */
-#define RSPEC_STF_SHIFT 11 /* mimo Space/Time/Frequency mode shift */
-#define RSPEC_CT_MASK 0x0000C000 /* mimo coding type mask */
-#define RSPEC_CT_SHIFT 14 /* mimo coding type shift */
-#define RSPEC_STC_MASK 0x00300000 /* mimo num STC streams per PLCP defn. */
-#define RSPEC_STC_SHIFT 20 /* mimo num STC streams per PLCP defn. */
-#define RSPEC_LDPC_CODING 0x00400000 /* mimo bit indicates adv coding in use */
-#define RSPEC_SHORT_GI 0x00800000 /* mimo bit indicates short GI in use */
-#define RSPEC_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */
-#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicates override rate only */
-
-#define BRCMS_HTPHY 127 /* HT PHY Membership */
-
-#define RSPEC_ACTIVE(rspec) (rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE))
-#define RSPEC2RATE(rspec) ((rspec & RSPEC_MIMORATE) ? \
- MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec)) : \
- (rspec & RSPEC_RATE_MASK))
-/* return rate in unit of 500Kbps -- for internal use in wlc_rate_sel.c */
-#define RSPEC2RATE500K(rspec) ((rspec & RSPEC_MIMORATE) ? \
- MCS_RATE((rspec & RSPEC_RATE_MASK), state->is40bw, RSPEC_ISSGI(rspec))/500 : \
- (rspec & RSPEC_RATE_MASK))
-#define CRSPEC2RATE500K(rspec) ((rspec & RSPEC_MIMORATE) ? \
- MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec))/500 :\
- (rspec & RSPEC_RATE_MASK))
-
-#define RSPEC2KBPS(rspec) (IS_MCS(rspec) ? RSPEC2RATE(rspec) : RSPEC2RATE(rspec)*500)
-#define RSPEC_PHYTXBYTE2(rspec) ((rspec & 0xff00) >> 8)
-#define RSPEC_GET_BW(rspec) ((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT)
-#define RSPEC_IS40MHZ(rspec) ((((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT) == \
- PHY_TXC1_BW_40MHZ) || (((rspec & RSPEC_BW_MASK) >> \
- RSPEC_BW_SHIFT) == PHY_TXC1_BW_40MHZ_DUP))
-#define RSPEC_ISSGI(rspec) ((rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI)
-#define RSPEC_MIMOPLCP3(rspec) ((rspec & 0xf00000) >> 16)
-#define PLCP3_ISSGI(plcp) (plcp & (RSPEC_SHORT_GI >> 16))
-#define RSPEC_STC(rspec) ((rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT)
-#define RSPEC_STF(rspec) ((rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT)
-#define PLCP3_ISSTBC(plcp) ((plcp & (RSPEC_STC_MASK) >> 16) == 0x10)
-#define PLCP3_STC_MASK 0x30
-#define PLCP3_STC_SHIFT 4
-
-/* Rate info table; takes a legacy rate or ratespec_t */
-#define IS_MCS(r) (r & RSPEC_MIMORATE)
-#define IS_OFDM(r) (!IS_MCS(r) && (rate_info[(r) & RSPEC_RATE_MASK] & \
- BRCMS_RATE_FLAG))
-#define IS_CCK(r) (!IS_MCS(r) && ( \
- ((r) & BRCMS_RATE_MASK) == BRCM_RATE_1M || \
- ((r) & BRCMS_RATE_MASK) == BRCM_RATE_2M || \
- ((r) & BRCMS_RATE_MASK) == BRCM_RATE_5M5 || \
- ((r) & BRCMS_RATE_MASK) == BRCM_RATE_11M))
-#define IS_SINGLE_STREAM(mcs) (((mcs) <= HIGHEST_SINGLE_STREAM_MCS) || ((mcs) == 32))
-#define CCK_RSPEC(cck) ((cck) & RSPEC_RATE_MASK)
-#define OFDM_RSPEC(ofdm) (((ofdm) & RSPEC_RATE_MASK) |\
- (PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT))
-#define LEGACY_RSPEC(rate) (IS_CCK(rate) ? CCK_RSPEC(rate) : OFDM_RSPEC(rate))
-
-#define MCS_RSPEC(mcs) (((mcs) & RSPEC_RATE_MASK) | RSPEC_MIMORATE | \
- (IS_SINGLE_STREAM(mcs) ? (PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT) : \
- (PHY_TXC1_MODE_SDM << RSPEC_STF_SHIFT)))
-
-/* Convert encoded rate value in plcp header to numerical rates in 500 KHz increments */
+
+/* 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 */
extern const u8 ofdm_rate_lookup[];
-#define OFDM_PHY2MAC_RATE(rlpt) (ofdm_rate_lookup[rlpt & 0x7])
-#define CCK_PHY2MAC_RATE(signal) (signal/5)
+
+static inline u8 ofdm_phy2mac_rate(u8 rlpt)
+{
+ return 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 */
+/* sanitize, and sort a rateset with the basic bit(s) preserved, validate
+ * rateset */
extern bool
-brcms_c_rate_hwrs_filter_sort_validate(struct brcms_rateset *rs,
- const struct brcms_rateset *hw_rs,
+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) */
-extern void brcms_c_rateset_copy(const struct brcms_rateset *src,
- struct brcms_rateset *dst);
+extern void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
+ struct brcms_c_rateset *dst);
/* would be nice to have these documented ... */
-extern ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp);
+extern u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp);
-extern void brcms_c_rateset_filter(struct brcms_rateset *src,
- struct brcms_rateset *dst, bool basic_only, u8 rates, uint xmask,
+extern void brcms_c_rateset_filter(struct brcms_c_rateset *src,
+ struct brcms_c_rateset *dst, bool basic_only, u8 rates, uint xmask,
bool mcsallow);
extern void
-brcms_c_rateset_default(struct brcms_rateset *rs_tgt,
- const struct brcms_rateset *rs_hw, uint phy_type,
+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);
extern s16 brcms_c_rate_legacy_phyctl(uint rate);
-extern void brcms_c_rateset_mcs_upd(struct brcms_rateset *rs, u8 txstreams);
-extern void brcms_c_rateset_mcs_clear(struct brcms_rateset *rateset);
-extern void brcms_c_rateset_mcs_build(struct brcms_rateset *rateset,
+extern void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams);
+extern void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset);
+extern void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset,
u8 txstreams);
-extern void brcms_c_rateset_bw_mcs_filter(struct brcms_rateset *rateset, u8 bw);
+extern void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset,
+ u8 bw);
#endif /* _BRCM_RATE_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/scb.h b/drivers/staging/brcm80211/brcmsmac/scb.h
index d6c8328554d0..51c79c7239b7 100644
--- a/drivers/staging/brcm80211/brcmsmac/scb.h
+++ b/drivers/staging/brcm80211/brcmsmac/scb.h
@@ -23,17 +23,27 @@
#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 tx_in_transit; /* number of pending mpdus in transit in driver */
- u8 tid; /* initiator tid for easy lookup */
- u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; /* tx retry count; indexed by seq modulo */
- struct scb *scb; /* backptr for easy lookup */
- u8 ba_wsize; /* negotiated ba window size (in pdu) */
+ u8 tx_in_transit; /* number of pending mpdus in transit in driver */
+ 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) */
};
-#define AMPDU_MAX_SCB_TID NUMPRIO
-
struct scb_ampdu {
struct scb *scb; /* back pointer for easy reference */
u8 mpdu_density; /* mpdu density */
@@ -41,45 +51,32 @@ struct scb_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 */
- struct pktq txq; /* sdu transmit queue pending aggregation */
- /* 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.
+ /*
+ * 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];
};
-#define SCB_MAGIC 0xbeefcafe
-
/* 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 */
+ 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 */
- void *fragbuf[NUMPRIO]; /* defragmentation buffer per prio */
- uint fragresid[NUMPRIO]; /* #bytes unused in frag buffer per prio */
+ uint fragresid[NUMPRIO];/* #bytes unused in frag buffer per prio */
u16 seqctl[NUMPRIO]; /* seqctl of last received frame (for dups) */
- u16 seqctl_nonqos; /* seqctl of last received frame (for dups) for
- * non-QoS data and management
- */
- u16 seqnum[NUMPRIO]; /* WME: driver maintained sw seqnum per priority */
+ /* 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 */
};
-/* scb flags */
-#define SCB_WMECAP 0x0040 /* may ONLY be set if WME_ENAB(wlc) */
-#define SCB_HTCAP 0x10000 /* HT (MIMO) capable device */
-#define SCB_IS40 0x80000 /* 40MHz capable */
-#define SCB_STBCCAP 0x40000000 /* STBC Capable */
-#define SCB_WME(a) ((a)->flags & SCB_WMECAP)/* implies WME_ENAB */
-#define SCB_SEQNUM(scb, prio) ((scb)->seqnum[(prio)])
-#define SCB_PS(a) NULL
-#define SCB_STBC_CAP(a) ((a)->flags & SCB_STBCCAP)
-#define SCB_AMPDU(a) true
#endif /* _BRCM_SCB_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/srom.c b/drivers/staging/brcm80211/brcmsmac/srom.c
index f39442ed4ce7..99f791048e84 100644
--- a/drivers/staging/brcm80211/brcmsmac/srom.c
+++ b/drivers/staging/brcm80211/brcmsmac/srom.c
@@ -18,24 +18,23 @@
#include <linux/string.h>
#include <linux/io.h>
#include <linux/etherdevice.h>
+#include <linux/crc8.h>
#include <stdarg.h>
#include <chipcommon.h>
#include <brcmu_utils.h>
+#include "pub.h"
#include "nicpci.h"
#include "aiutils.h"
#include "otp.h"
#include "srom.h"
-#define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
- (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
- ((u8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
- ((u8 *)curmap + PCI_BAR0_SPROM_OFFSET))
-
-#if defined(BCMDBG)
-#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
-#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
-#endif
+/*
+ * SROM CRC8 polynomial value:
+ *
+ * x^8 + x^7 +x^6 + x^4 + x^2 + 1
+ */
+#define SROM_CRC8_POLY 0xAB
/* Maximum srom: 6 Kilobits == 768 bytes */
#define SROM_MAX 768
@@ -260,7 +259,8 @@
/* Temp sense related entries */
#define SROM8_MPWR_RAWTS 90
#define SROM8_TS_SLP_OPT_CORRX 91
-/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
+/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable,
+ * IQSWP: IQ CAL swap disable */
#define SROM8_FOC_HWIQ_IQSWP 92
/* Temperature delta for PHY calibration */
@@ -349,20 +349,53 @@
#define SROM9_PO_LOFDM40DUP 203
/* SROM flags (see sromvar_t) */
-#define SRFL_MORE 1 /* value continues as described by the next entry */
+
+/* value continues as described by the next entry */
+#define SRFL_MORE 1
#define SRFL_NOFFS 2 /* value bits can't be all one's */
#define SRFL_PRHEX 4 /* value is in hexdecimal format */
#define SRFL_PRSIGN 8 /* value is in signed decimal format */
#define SRFL_CCODE 0x10 /* value is in country code format */
#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */
#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */
-#define SRFL_NOVAR 0x80 /* do not generate a nvram param, entry is for mfgc */
+/* do not generate a nvram param, entry is for mfgc */
+#define SRFL_NOVAR 0x80
/* Max. nvram variable table size */
#define MAXSZ_NVRAM_VARS 4096
+/*
+ * indicates type of value.
+ */
+enum brcms_srom_var_type {
+ BRCMS_SROM_STRING,
+ BRCMS_SROM_SNUMBER,
+ BRCMS_SROM_UNUMBER
+};
+
+/*
+ * storage type for srom variable.
+ *
+ * var_list: for linked list operations.
+ * varid: identifier of the variable.
+ * var_type: type of variable.
+ * buf: variable value when var_type == BRCMS_SROM_STRING.
+ * uval: unsigned variable value when var_type == BRCMS_SROM_UNUMBER.
+ * sval: signed variable value when var_type == BRCMS_SROM_SNUMBER.
+ */
+struct brcms_srom_list_head {
+ struct list_head var_list;
+ enum brcms_srom_id varid;
+ enum brcms_srom_var_type var_type;
+ union {
+ char buf[0];
+ u32 uval;
+ s32 sval;
+ };
+};
+
struct brcms_sromvar {
- const char *name;
+ enum brcms_srom_id varid;
u32 revmask;
u32 flags;
u16 off;
@@ -375,615 +408,476 @@ struct brcms_varbuf {
unsigned int size; /* current (residual) size in bytes */
};
-/* Assumptions:
- * - Ethernet address spans across 3 consective words
+/*
+ * Assumptions:
+ * - Ethernet address spans across 3 consecutive words
*
* Table rules:
- * - Add multiple entries next to each other if a value spans across multiple words
- * (even multiple fields in the same word) with each entry except the last having
- * it's SRFL_MORE bit set.
- * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
- * bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
- * - The last entry's name field must be NULL to indicate the end of the table. Other
- * entries must have non-NULL name.
+ * - Add multiple entries next to each other if a value spans across multiple
+ * words (even multiple fields in the same word) with each entry except the
+ * last having it's SRFL_MORE bit set.
+ * - Ethernet address entry does not follow above rule and must not have
+ * SRFL_MORE bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
+ * - The last entry's name field must be NULL to indicate the end of the table.
+ * Other entries must have non-NULL name.
*/
static const struct brcms_sromvar pci_sromvars[] = {
- {"devid", 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, 0xffff},
- {"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK},
- {"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
- {"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
- {"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
- {"boardflags", 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
- {"", 0, 0, SROM_BFL2, 0xffff},
- {"boardflags", 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
- {"", 0, 0, SROM3_BFL2, 0xffff},
- {"boardflags", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, 0xffff},
- {"", 0, 0, SROM4_BFL1, 0xffff},
- {"boardflags", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, 0xffff},
- {"", 0, 0, SROM5_BFL1, 0xffff},
- {"boardflags", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, 0xffff},
- {"", 0, 0, SROM8_BFL1, 0xffff},
- {"boardflags2", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, 0xffff},
- {"", 0, 0, SROM4_BFL3, 0xffff},
- {"boardflags2", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, 0xffff},
- {"", 0, 0, SROM5_BFL3, 0xffff},
- {"boardflags2", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, 0xffff},
- {"", 0, 0, SROM8_BFL3, 0xffff},
- {"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
- {"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
- {"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff},
- {"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff},
- {"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff},
- {"boardnum", 0xffffff00, 0, SROM8_MACLO, 0xffff},
- {"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
- {"regrev", 0x00000008, 0, SROM_OPO, 0xff00},
- {"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff},
- {"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff},
- {"regrev", 0xffffff00, 0, SROM8_REGREV, 0x00ff},
- {"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
- {"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
- {"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
- {"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
- {"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
- {"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
- {"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
- {"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
- {"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
- {"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
- {"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
- {"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
- {"ledbh0", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
- {"ledbh1", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
- {"ledbh2", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
- {"ledbh3", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
- {"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
- {"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
- {"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
- {"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff},
- {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
- {"pa0b0", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
- {"pa0b1", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
- {"pa0b2", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
- {"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
- {"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
- {"opo", 0x0000000c, 0, SROM_OPO, 0x00ff},
- {"opo", 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
- {"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
- {"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff},
- {"aa2g", 0xffffff00, 0, SROM8_AA, 0x00ff},
- {"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
- {"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00},
- {"aa5g", 0xffffff00, 0, SROM8_AA, 0xff00},
- {"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff},
- {"ag1", 0x0000000e, 0, SROM_AG10, 0xff00},
- {"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff},
- {"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00},
- {"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff},
- {"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00},
- {"ag0", 0xffffff00, 0, SROM8_AG10, 0x00ff},
- {"ag1", 0xffffff00, 0, SROM8_AG10, 0xff00},
- {"ag2", 0xffffff00, 0, SROM8_AG32, 0x00ff},
- {"ag3", 0xffffff00, 0, SROM8_AG32, 0xff00},
- {"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
- {"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
- {"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
- {"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
- {"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
- {"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
- {"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
- {"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
- {"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
- {"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00},
- {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
- {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
- {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
- {"pa1b0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
- {"pa1b1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
- {"pa1b2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
- {"pa1lob0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
- {"pa1lob1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
- {"pa1lob2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
- {"pa1hib0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
- {"pa1hib1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
- {"pa1hib2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
- {"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
- {"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
- {"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
- {"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
- {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
- {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
- {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
- {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
- {"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
- {"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
- {"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
- {"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
- {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
- {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
- {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
- {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
- {"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
- {"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
- {"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
- {"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
- {"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff},
- {"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00},
- {"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
- {"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00},
- {"tri2g", 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
- {"tri5g", 0xffffff00, 0, SROM8_TRI52G, 0xff00},
- {"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
- {"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
- {"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
- {"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
- {"rxpo2g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
- {"rxpo5g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
- {"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK},
- {"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK},
- {"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK},
- {"txchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK},
- {"rxchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK},
- {"antswitch", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK},
- {"tssipos2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK},
- {"extpagain2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK},
- {"pdetrange2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK},
- {"triso2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
- {"antswctl2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK},
- {"tssipos5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK},
- {"extpagain5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK},
- {"pdetrange5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK},
- {"triso5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
- {"antswctl5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK},
- {"tempthresh", 0xffffff00, 0, SROM8_THERMAL, 0xff00},
- {"tempoffset", 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
- {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
- {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
- {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
- {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
- {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
- {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
- {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
- {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
- {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
- {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
- {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
- {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
- {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
- {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
- {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
- {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
-
- {"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
- {"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
- {"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
- {"ccode", 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
- {"macaddr", 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
- {"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
- {"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
- {"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
- {"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff},
- {"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff},
- {"leddc", 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, 0xffff},
- {"leddc", 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, 0xffff},
- {"leddc", 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, 0xffff},
- {"leddc", 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, 0xffff},
- {"rawtempsense", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff},
- {"measpower", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00},
- {"tempsense_slope", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
+ {BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID,
+ 0xffff},
+ {BRCMS_SROM_BOARDREV, 0x0000000e, SRFL_PRHEX, SROM_AABREV,
+ SROM_BR_MASK},
+ {BRCMS_SROM_BOARDREV, 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
+ {BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM_BFL2, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM3_BFL2, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_BFL1, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM5_BFL1, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS2, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_BFL3, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS2, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM5_BFL3, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff},
+ {BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
+ {BRCMS_SROM_BOARDNUM, 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
+ {BRCMS_SROM_BOARDNUM, 0x00000008, 0, SROM3_MACLO, 0xffff},
+ {BRCMS_SROM_BOARDNUM, 0x00000010, 0, SROM4_MACLO, 0xffff},
+ {BRCMS_SROM_BOARDNUM, 0x000000e0, 0, SROM5_MACLO, 0xffff},
+ {BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff},
+ {BRCMS_SROM_CC, 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
+ {BRCMS_SROM_REGREV, 0x00000008, 0, SROM_OPO, 0xff00},
+ {BRCMS_SROM_REGREV, 0x00000010, 0, SROM4_REGREV, 0x00ff},
+ {BRCMS_SROM_REGREV, 0x000000e0, 0, SROM5_REGREV, 0x00ff},
+ {BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff},
+ {BRCMS_SROM_LEDBH0, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
+ {BRCMS_SROM_LEDBH1, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
+ {BRCMS_SROM_LEDBH2, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
+ {BRCMS_SROM_LEDBH3, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
+ {BRCMS_SROM_LEDBH0, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
+ {BRCMS_SROM_LEDBH1, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
+ {BRCMS_SROM_LEDBH2, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
+ {BRCMS_SROM_LEDBH3, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
+ {BRCMS_SROM_LEDBH0, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
+ {BRCMS_SROM_LEDBH1, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
+ {BRCMS_SROM_LEDBH2, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
+ {BRCMS_SROM_LEDBH3, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
+ {BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
+ {BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
+ {BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
+ {BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
+ {BRCMS_SROM_PA0B0, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
+ {BRCMS_SROM_PA0B1, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
+ {BRCMS_SROM_PA0B2, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
+ {BRCMS_SROM_PA0ITSSIT, 0x0000000e, 0, SROM_ITT, 0x00ff},
+ {BRCMS_SROM_PA0MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
+ {BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
+ {BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
+ {BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
+ {BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
+ {BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
+ {BRCMS_SROM_OPO, 0x0000000c, 0, SROM_OPO, 0x00ff},
+ {BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
+ {BRCMS_SROM_AA2G, 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
+ {BRCMS_SROM_AA2G, 0x000000f0, 0, SROM4_AA, 0x00ff},
+ {BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff},
+ {BRCMS_SROM_AA5G, 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
+ {BRCMS_SROM_AA5G, 0x000000f0, 0, SROM4_AA, 0xff00},
+ {BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00},
+ {BRCMS_SROM_AG0, 0x0000000e, 0, SROM_AG10, 0x00ff},
+ {BRCMS_SROM_AG1, 0x0000000e, 0, SROM_AG10, 0xff00},
+ {BRCMS_SROM_AG0, 0x000000f0, 0, SROM4_AG10, 0x00ff},
+ {BRCMS_SROM_AG1, 0x000000f0, 0, SROM4_AG10, 0xff00},
+ {BRCMS_SROM_AG2, 0x000000f0, 0, SROM4_AG32, 0x00ff},
+ {BRCMS_SROM_AG3, 0x000000f0, 0, SROM4_AG32, 0xff00},
+ {BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff},
+ {BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00},
+ {BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff},
+ {BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00},
+ {BRCMS_SROM_PA1B0, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
+ {BRCMS_SROM_PA1B1, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
+ {BRCMS_SROM_PA1B2, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
+ {BRCMS_SROM_PA1LOB0, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
+ {BRCMS_SROM_PA1LOB1, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
+ {BRCMS_SROM_PA1LOB2, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
+ {BRCMS_SROM_PA1HIB0, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
+ {BRCMS_SROM_PA1HIB1, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
+ {BRCMS_SROM_PA1HIB2, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
+ {BRCMS_SROM_PA1ITSSIT, 0x0000000e, 0, SROM_ITT, 0xff00},
+ {BRCMS_SROM_PA1MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
+ {BRCMS_SROM_PA1LOMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
+ {BRCMS_SROM_PA1HIMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
+ {BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
+ {BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
+ {BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
+ {BRCMS_SROM_PA1LOB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
+ {BRCMS_SROM_PA1LOB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
+ {BRCMS_SROM_PA1LOB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
+ {BRCMS_SROM_PA1HIB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
+ {BRCMS_SROM_PA1HIB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
+ {BRCMS_SROM_PA1HIB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
+ {BRCMS_SROM_PA1ITSSIT, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
+ {BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
+ {BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
+ {BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
+ {BRCMS_SROM_BXA2G, 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
+ {BRCMS_SROM_RSSISAV2G, 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
+ {BRCMS_SROM_RSSISMC2G, 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
+ {BRCMS_SROM_RSSISMF2G, 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
+ {BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
+ {BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
+ {BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
+ {BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
+ {BRCMS_SROM_BXA5G, 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
+ {BRCMS_SROM_RSSISAV5G, 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
+ {BRCMS_SROM_RSSISMC5G, 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
+ {BRCMS_SROM_RSSISMF5G, 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
+ {BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
+ {BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
+ {BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
+ {BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
+ {BRCMS_SROM_TRI2G, 0x00000008, 0, SROM_TRI52G, 0x00ff},
+ {BRCMS_SROM_TRI5G, 0x00000008, 0, SROM_TRI52G, 0xff00},
+ {BRCMS_SROM_TRI5GL, 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
+ {BRCMS_SROM_TRI5GH, 0x00000008, 0, SROM_TRI5GHL, 0xff00},
+ {BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
+ {BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00},
+ {BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
+ {BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
+ {BRCMS_SROM_RXPO2G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
+ {BRCMS_SROM_RXPO5G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
+ {BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
+ {BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
+ {BRCMS_SROM_TXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
+ SROM4_TXCHAIN_MASK},
+ {BRCMS_SROM_RXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
+ SROM4_RXCHAIN_MASK},
+ {BRCMS_SROM_ANTSWITCH, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
+ SROM4_SWITCH_MASK},
+ {BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
+ SROM4_TXCHAIN_MASK},
+ {BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
+ SROM4_RXCHAIN_MASK},
+ {BRCMS_SROM_ANTSWITCH, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
+ SROM4_SWITCH_MASK},
+ {BRCMS_SROM_TSSIPOS2G, 0xffffff00, 0, SROM8_FEM2G,
+ SROM8_FEM_TSSIPOS_MASK},
+ {BRCMS_SROM_EXTPAGAIN2G, 0xffffff00, 0, SROM8_FEM2G,
+ SROM8_FEM_EXTPA_GAIN_MASK},
+ {BRCMS_SROM_PDETRANGE2G, 0xffffff00, 0, SROM8_FEM2G,
+ SROM8_FEM_PDET_RANGE_MASK},
+ {BRCMS_SROM_TRISO2G, 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
+ {BRCMS_SROM_ANTSWCTL2G, 0xffffff00, 0, SROM8_FEM2G,
+ SROM8_FEM_ANTSWLUT_MASK},
+ {BRCMS_SROM_TSSIPOS5G, 0xffffff00, 0, SROM8_FEM5G,
+ SROM8_FEM_TSSIPOS_MASK},
+ {BRCMS_SROM_EXTPAGAIN5G, 0xffffff00, 0, SROM8_FEM5G,
+ SROM8_FEM_EXTPA_GAIN_MASK},
+ {BRCMS_SROM_PDETRANGE5G, 0xffffff00, 0, SROM8_FEM5G,
+ SROM8_FEM_PDET_RANGE_MASK},
+ {BRCMS_SROM_TRISO5G, 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
+ {BRCMS_SROM_ANTSWCTL5G, 0xffffff00, 0, SROM8_FEM5G,
+ SROM8_FEM_ANTSWLUT_MASK},
+ {BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00},
+ {BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
+ {BRCMS_SROM_TXPID2GA0, 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
+ {BRCMS_SROM_TXPID2GA1, 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
+ {BRCMS_SROM_TXPID2GA2, 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
+ {BRCMS_SROM_TXPID2GA3, 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
+ {BRCMS_SROM_TXPID5GA0, 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
+ {BRCMS_SROM_TXPID5GA1, 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
+ {BRCMS_SROM_TXPID5GA2, 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
+ {BRCMS_SROM_TXPID5GA3, 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
+ {BRCMS_SROM_TXPID5GLA0, 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
+ {BRCMS_SROM_TXPID5GLA1, 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
+ {BRCMS_SROM_TXPID5GLA2, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
+ {BRCMS_SROM_TXPID5GLA3, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
+ {BRCMS_SROM_TXPID5GHA0, 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
+ {BRCMS_SROM_TXPID5GHA1, 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
+ {BRCMS_SROM_TXPID5GHA2, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
+ {BRCMS_SROM_TXPID5GHA3, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
+
+ {BRCMS_SROM_CCODE, 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
+ {BRCMS_SROM_CCODE, 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
+ {BRCMS_SROM_CCODE, 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
+ {BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
+ {BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
+ {BRCMS_SROM_MACADDR, 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
+ {BRCMS_SROM_MACADDR, 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
+ {BRCMS_SROM_MACADDR, 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
+ {BRCMS_SROM_IL0MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0,
+ 0xffff},
+ {BRCMS_SROM_ET1MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1,
+ 0xffff},
+ {BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC,
+ 0xffff},
+ {BRCMS_SROM_LEDDC, 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC,
+ 0xffff},
+ {BRCMS_SROM_LEDDC, 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC,
+ 0xffff},
+ {BRCMS_SROM_LEDDC, 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC,
+ 0xffff},
+ {BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
+ 0x01ff},
+ {BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
+ 0xfe00},
+ {BRCMS_SROM_TEMPSENSE_SLOPE, 0xffffff00, SRFL_PRHEX,
+ SROM8_TS_SLP_OPT_CORRX, 0x00ff},
+ {BRCMS_SROM_TEMPCORRX, 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
+ 0xfc00},
+ {BRCMS_SROM_TEMPSENSE_OPTION, 0xffffff00, SRFL_PRHEX,
+ SROM8_TS_SLP_OPT_CORRX, 0x0300},
+ {BRCMS_SROM_FREQOFFSET_CORR, 0xffffff00, SRFL_PRHEX,
+ SROM8_FOC_HWIQ_IQSWP, 0x000f},
+ {BRCMS_SROM_IQCAL_SWP_DIS, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
+ 0x0010},
+ {BRCMS_SROM_HW_IQCAL_EN, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
+ 0x0020},
+ {BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA,
0x00ff},
- {"tempcorrx", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00},
- {"tempsense_option", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
- 0x0300},
- {"freqoffset_corr", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
- 0x000f},
- {"iqcal_swp_dis", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010},
- {"hw_iqcal_en", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020},
- {"phycal_tempdelta", 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff},
-
- {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
- {"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
- {"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
- {"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
- {"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
- {"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
- {"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
- {"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
- {"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
- {"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
- {"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
- {"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
- {"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
- {"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
- {"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
- {"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
- {"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
- {"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
- {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
- {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
- {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
- {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
- {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
- {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
- {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
- {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
- {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
- {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
- {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
- {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
- {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
- {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
- {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
- {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
- {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
- {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
- {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
- {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
- {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
- {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
- {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
- {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
- {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
- {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
- {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
- {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
- {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
- {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
- {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
- {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
- {"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
- {"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
- {"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
- {"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
- {"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
- {"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
- {"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
- {"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
- {"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
- {"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
- {"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
- {"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
- {"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
- {"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
- {"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
- {"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
- {"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
- {"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
- {"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
- {"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
- {"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
- {"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
- {"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
- {"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
- {"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
- {"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
- {"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
- {"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
- {"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
- {"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
- {"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
- {"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
- {"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff},
- {"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff},
- {"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff},
- {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
- {"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff},
- {"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff},
- {"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff},
- {"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
+
+ {BRCMS_SROM_CCK2GPO, 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
+ {BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
+ {BRCMS_SROM_OFDM2GPO, 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GPO, 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GLPO, 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GHPO, 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GLPO, 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_MCS2GPO0, 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS2GPO1, 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS2GPO2, 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS2GPO3, 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS2GPO4, 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS2GPO5, 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS2GPO6, 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS2GPO7, 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GPO0, 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GPO1, 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GPO2, 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GPO3, 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GPO4, 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GPO5, 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GPO6, 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GPO7, 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GLPO0, 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GLPO1, 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GLPO2, 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GLPO3, 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GLPO4, 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GLPO5, 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GLPO6, 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GLPO7, 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GHPO0, 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GHPO1, 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GHPO2, 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GHPO3, 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GHPO4, 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GHPO5, 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GHPO6, 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GHPO7, 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS2GPO3, 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS2GPO4, 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS2GPO5, 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS2GPO6, 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS2GPO7, 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GPO0, 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GPO1, 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GPO2, 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GPO3, 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GPO4, 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GPO5, 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GPO6, 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GPO7, 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GLPO0, 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GLPO1, 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GLPO2, 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GLPO3, 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GLPO4, 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GLPO5, 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GLPO6, 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GLPO7, 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GHPO0, 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GHPO1, 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GHPO2, 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GHPO3, 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GHPO4, 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_CDDPO, 0x000000f0, 0, SROM4_CDDPO, 0xffff},
+ {BRCMS_SROM_STBCPO, 0x000000f0, 0, SROM4_STBCPO, 0xffff},
+ {BRCMS_SROM_BW40PO, 0x000000f0, 0, SROM4_BW40PO, 0xffff},
+ {BRCMS_SROM_BWDUPPO, 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
+ {BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff},
+ {BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff},
+ {BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff},
+ {BRCMS_SROM_BWDUPPO, 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
/* power per rate from sromrev 9 */
- {"cckbw202gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
- {"cckbw20ul2gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
- {"legofdmbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20,
+ {BRCMS_SROM_CCKBW202GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
+ {BRCMS_SROM_CCKBW20UL2GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW202GPO, 0xfffffe00, SRFL_MORE,
+ SROM9_2GPO_LOFDMBW20, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW20UL2GPO, 0xfffffe00, SRFL_MORE,
+ SROM9_2GPO_LOFDMBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW205GLPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GLPO_LOFDMBW20, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW20UL5GLPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GLPO_LOFDMBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW205GMPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GMPO_LOFDMBW20, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW20UL5GMPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GMPO_LOFDMBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW205GHPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GHPO_LOFDMBW20, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW20UL5GHPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GHPO_LOFDMBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
+ {BRCMS_SROM_MCSBW202GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20,
0xffff},
- {"", 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
- {"legofdmbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20UL,
+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW20UL2GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL,
0xffff},
- {"", 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
- {"legofdmbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20,
+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
+ {BRCMS_SROM_MCSBW402GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40,
0xffff},
- {"", 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
- {"legofdmbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,
+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW205GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20,
0xffff},
- {"", 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
- {"legofdmbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20,
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW20UL5GLPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GLPO_MCSBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
+ {BRCMS_SROM_MCSBW405GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40,
0xffff},
- {"", 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
- {"legofdmbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW205GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20,
0xffff},
- {"", 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
- {"legofdmbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20,
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW20UL5GMPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GMPO_MCSBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
+ {BRCMS_SROM_MCSBW405GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40,
0xffff},
- {"", 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
- {"legofdmbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW205GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20,
0xffff},
- {"", 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
- {"mcsbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff},
- {"", 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
- {"mcsbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff},
- {"", 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
- {"mcsbw402gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff},
- {"", 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
- {"mcsbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff},
- {"", 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
- {"mcsbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20UL,
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW20UL5GHPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GHPO_MCSBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
+ {BRCMS_SROM_MCSBW405GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40,
0xffff},
- {"", 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
- {"mcsbw405glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff},
- {"", 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
- {"mcsbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff},
- {"", 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
- {"mcsbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20UL,
- 0xffff},
- {"", 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
- {"mcsbw405gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff},
- {"", 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
- {"mcsbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff},
- {"", 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
- {"mcsbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20UL,
- 0xffff},
- {"", 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
- {"mcsbw405ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff},
- {"", 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
- {"mcs32po", 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
- {"legofdm40duppo", 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
+ {BRCMS_SROM_MCS32PO, 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
+ {BRCMS_SROM_LEGOFDM40DUPPO, 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
- {NULL, 0, 0, 0, 0}
+ {BRCMS_SROM_NULL, 0, 0, 0, 0}
};
static const struct brcms_sromvar perpath_pci_sromvars[] = {
- {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
- {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
- {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
- {"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
- {"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
- {"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
- {"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
- {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
- {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
- {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
- {"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
- {"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
- {"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
- {"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
- {"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
- {"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff},
- {"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff},
- {"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff},
- {"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
- {"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff},
- {"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff},
- {"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff},
- {"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
- {"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
- {"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
- {"pa2gw0a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
- {"pa2gw1a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
- {"pa2gw2a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
- {"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
- {"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
- {"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
- {"pa5gw0a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
- {"pa5gw1a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
- {"pa5gw2a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
- {"pa5glw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
- {"pa5glw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff},
- {"pa5glw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff},
- {"pa5ghw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
- {"pa5ghw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff},
- {"pa5ghw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff},
- {NULL, 0, 0, 0, 0}
+ {BRCMS_SROM_MAXP2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
+ {BRCMS_SROM_ITT2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
+ {BRCMS_SROM_ITT5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
+ {BRCMS_SROM_PA2GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
+ {BRCMS_SROM_PA2GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
+ {BRCMS_SROM_PA2GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
+ {BRCMS_SROM_PA2GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
+ {BRCMS_SROM_MAXP5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
+ {BRCMS_SROM_MAXP5GHA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
+ {BRCMS_SROM_MAXP5GLA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
+ {BRCMS_SROM_PA5GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
+ {BRCMS_SROM_PA5GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
+ {BRCMS_SROM_PA5GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
+ {BRCMS_SROM_PA5GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
+ {BRCMS_SROM_PA5GLW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
+ {BRCMS_SROM_PA5GLW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1,
+ 0xffff},
+ {BRCMS_SROM_PA5GLW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2,
+ 0xffff},
+ {BRCMS_SROM_PA5GLW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3,
+ 0xffff},
+ {BRCMS_SROM_PA5GHW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
+ {BRCMS_SROM_PA5GHW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1,
+ 0xffff},
+ {BRCMS_SROM_PA5GHW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2,
+ 0xffff},
+ {BRCMS_SROM_PA5GHW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3,
+ 0xffff},
+ {BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
+ {BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
+ {BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
+ {BRCMS_SROM_PA2GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
+ {BRCMS_SROM_PA2GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
+ {BRCMS_SROM_PA2GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
+ {BRCMS_SROM_MAXP5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
+ {BRCMS_SROM_MAXP5GHA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
+ {BRCMS_SROM_MAXP5GLA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
+ {BRCMS_SROM_PA5GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
+ {BRCMS_SROM_PA5GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
+ {BRCMS_SROM_PA5GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
+ {BRCMS_SROM_PA5GLW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
+ {BRCMS_SROM_PA5GLW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1,
+ 0xffff},
+ {BRCMS_SROM_PA5GLW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2,
+ 0xffff},
+ {BRCMS_SROM_PA5GHW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
+ {BRCMS_SROM_PA5GHW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1,
+ 0xffff},
+ {BRCMS_SROM_PA5GHW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2,
+ 0xffff},
+ {BRCMS_SROM_NULL, 0, 0, 0, 0}
};
-static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off,
- struct brcms_varbuf *b);
-static int initvars_srom_pci(struct si_pub *sih, void *curmap, char **vars,
- uint *count);
-static int sprom_read_pci(struct si_pub *sih, u16 *sprom,
- uint wordoff, u16 *buf, uint nwords, bool check_crc);
-#if defined(BCMNVRAMR)
-static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz);
-#endif
-
-static int initvars_table(char *start, char *end,
- char **vars, uint *count);
-
-/* Initialization of varbuf structure */
-static void varbuf_init(struct brcms_varbuf *b, char *buf, uint size)
-{
- b->size = size;
- b->base = b->buf = buf;
-}
-
-/* append a null terminated var=value string */
-static int varbuf_append(struct brcms_varbuf *b, const char *fmt, ...)
-{
- va_list ap;
- int r;
- size_t len;
- char *s;
-
- if (b->size < 2)
- return 0;
-
- va_start(ap, fmt);
- r = vsnprintf(b->buf, b->size, fmt, ap);
- va_end(ap);
-
- /* C99 snprintf behavior returns r >= size on overflow,
- * others return -1 on overflow.
- * All return -1 on format error.
- * We need to leave room for 2 null terminations, one for the current var
- * string, and one for final null of the var table. So check that the
- * strlen written, r, leaves room for 2 chars.
- */
- if ((r == -1) || (r > (int)(b->size - 2))) {
- b->size = 0;
- return 0;
- }
-
- /* Remove any earlier occurrence of the same variable */
- s = strchr(b->buf, '=');
- if (s != NULL) {
- len = (size_t) (s - b->buf);
- for (s = b->base; s < b->buf;) {
- if ((memcmp(s, b->buf, len) == 0) && s[len] == '=') {
- len = strlen(s) + 1;
- memmove(s, (s + len),
- ((b->buf + r + 1) - (s + len)));
- b->buf -= len;
- b->size += (unsigned int)len;
- break;
- }
-
- while (*s++)
- ;
- }
- }
-
- /* skip over this string's null termination */
- r++;
- b->size -= r;
- b->buf += r;
-
- return r;
-}
-
-/*
- * Initialize local vars from the right source for this platform.
- * Return 0 on success, nonzero on error.
- */
-int srom_var_init(struct si_pub *sih, uint bustype, void *curmap,
- char **vars, uint *count)
-{
- uint len;
-
- len = 0;
-
- if (vars == NULL || count == NULL)
- return 0;
-
- *vars = NULL;
- *count = 0;
-
- if (curmap != NULL && bustype == PCI_BUS)
- return initvars_srom_pci(sih, curmap, vars, count);
-
- return -EINVAL;
-}
-
-static inline void ltoh16_buf(u16 *buf, unsigned int size)
-{
- for (size /= 2; size; size--)
- *(buf + size) = le16_to_cpu(*(buf + size));
-}
-
-static inline void htol16_buf(u16 *buf, unsigned int size)
-{
- for (size /= 2; size; size--)
- *(buf + size) = cpu_to_le16(*(buf + size));
-}
-
-/*
- * Read in and validate sprom.
- * Return 0 on success, nonzero on error.
- */
-static int
-sprom_read_pci(struct si_pub *sih, u16 *sprom, uint wordoff,
- u16 *buf, uint nwords, bool check_crc)
-{
- int err = 0;
- uint i;
-
- /* read the sprom */
- for (i = 0; i < nwords; i++)
- buf[i] = R_REG(&sprom[wordoff + i]);
-
- if (check_crc) {
-
- if (buf[0] == 0xffff) {
- /* The hardware thinks that an srom that starts with 0xffff
- * is blank, regardless of the rest of the content, so declare
- * it bad.
- */
- return -ENODATA;
- }
-
- /* fixup the endianness so crc8 will pass */
- htol16_buf(buf, nwords * 2);
- if (brcmu_crc8((u8 *) buf, nwords * 2, CRC8_INIT_VALUE) !=
- CRC8_GOOD_VALUE) {
- /* DBG only pci always read srom4 first, then srom8/9 */
- err = -EIO;
- }
- /* now correct the endianness of the byte array */
- ltoh16_buf(buf, nwords * 2);
- }
- return err;
-}
-
-#if defined(BCMNVRAMR)
-static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
-{
- u8 *otp;
- uint sz = OTP_SZ_MAX / 2; /* size in words */
- int err = 0;
-
- otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
- if (otp == NULL) {
- return -ENOMEM;
- }
-
- err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
-
- memcpy(buf, otp, bufsz);
-
- kfree(otp);
-
- /* Check CRC */
- if (buf[0] == 0xffff) {
- /* The hardware thinks that an srom that starts with 0xffff
- * is blank, regardless of the rest of the content, so declare
- * it bad.
- */
- return -ENODATA;
- }
-
- /* fixup the endianness so crc8 will pass */
- htol16_buf(buf, bufsz);
- if (brcmu_crc8((u8 *) buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) !=
- CRC8_GOOD_VALUE) {
- err = -EIO;
- }
- /* now correct the endianness of the byte array */
- ltoh16_buf(buf, bufsz);
+/* crc table has the same contents for every device instance, so it can be
+ * shared between devices. */
+static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE];
- return err;
-}
-#endif /* defined(BCMNVRAMR) */
-/*
-* Create variable table from memory.
-* Return 0 on success, nonzero on error.
-*/
-static int initvars_table(char *start, char *end,
- char **vars, uint *count)
+static u16 __iomem *
+srom_window_address(struct si_pub *sih, u8 __iomem *curmap)
{
- int c = (int)(end - start);
-
- /* do it only when there is more than just the null string */
- if (c > 1) {
- char *vp = kmalloc(c, GFP_ATOMIC);
- if (!vp)
- return -ENOMEM;
- memcpy(vp, start, c);
- *vars = vp;
- *count = c;
- } else {
- *vars = NULL;
- *count = 0;
- }
+ if (sih->ccrev < 32)
+ return (u16 __iomem *)(curmap + PCI_BAR0_SPROM_OFFSET);
+ if (sih->cccaps & CC_CAP_SROM)
+ return (u16 __iomem *)
+ (curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP);
- return 0;
+ return NULL;
}
/* Parse SROM and create name=value pairs. 'srom' points to
@@ -1012,9 +906,28 @@ static uint mask_width(u16 mask)
return 0;
}
+static inline void ltoh16_buf(u16 *buf, unsigned int size)
+{
+ size /= 2;
+ while (size--)
+ *(buf + size) = le16_to_cpu(*(__le16 *)(buf + size));
+}
+
+static inline void htol16_buf(u16 *buf, unsigned int size)
+{
+ size /= 2;
+ while (size--)
+ *(__le16 *)(buf + size) = cpu_to_le16(*(buf + size));
+}
+
+/*
+ * convert binary srom data into linked list of srom variable items.
+ */
static void
-_initvars_srom_pci(u8 sromrev, u16 *srom, uint off, struct brcms_varbuf *b)
+_initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
{
+ struct brcms_srom_list_head *entry;
+ enum brcms_srom_id id;
u16 w;
u32 val;
const struct brcms_sromvar *srv;
@@ -1022,46 +935,52 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, struct brcms_varbuf *b)
uint flags;
u32 sr = (1 << sromrev);
- varbuf_append(b, "sromrev=%d", sromrev);
+ /* first store the srom revision */
+ entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL);
+ entry->varid = BRCMS_SROM_REV;
+ entry->var_type = BRCMS_SROM_UNUMBER;
+ entry->uval = sromrev;
+ list_add(&entry->var_list, var_list);
- for (srv = pci_sromvars; srv->name != NULL; srv++) {
- const char *name;
+ for (srv = pci_sromvars; srv->varid != BRCMS_SROM_NULL; srv++) {
+ enum brcms_srom_var_type type;
+ u8 ea[ETH_ALEN];
+ u8 extra_space = 0;
if ((srv->revmask & sr) == 0)
continue;
- if (srv->off < off)
- continue;
-
flags = srv->flags;
- name = srv->name;
+ id = srv->varid;
/* This entry is for mfgc only. Don't generate param for it, */
if (flags & SRFL_NOVAR)
continue;
if (flags & SRFL_ETHADDR) {
- u8 ea[ETH_ALEN];
-
- ea[0] = (srom[srv->off - off] >> 8) & 0xff;
- ea[1] = srom[srv->off - off] & 0xff;
- ea[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
- ea[3] = srom[srv->off + 1 - off] & 0xff;
- ea[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
- ea[5] = srom[srv->off + 2 - off] & 0xff;
-
- varbuf_append(b, "%s=%pM", name, ea);
+ /*
+ * stored in string format XX:XX:XX:XX:XX:XX (17 chars)
+ */
+ ea[0] = (srom[srv->off] >> 8) & 0xff;
+ ea[1] = srom[srv->off] & 0xff;
+ ea[2] = (srom[srv->off + 1] >> 8) & 0xff;
+ ea[3] = srom[srv->off + 1] & 0xff;
+ ea[4] = (srom[srv->off + 2] >> 8) & 0xff;
+ ea[5] = srom[srv->off + 2] & 0xff;
+ /* 17 characters + string terminator - union size */
+ extra_space = 18 - sizeof(s32);
+ type = BRCMS_SROM_STRING;
} else {
- w = srom[srv->off - off];
+ w = srom[srv->off];
val = (w & srv->mask) >> mask_shift(srv->mask);
width = mask_width(srv->mask);
while (srv->flags & SRFL_MORE) {
srv++;
- if (srv->off == 0 || srv->off < off)
+ if (srv->off == 0)
continue;
- w = srom[srv->off - off];
+ w = srom[srv->off];
val +=
((w & srv->mask) >> mask_shift(srv->
mask)) <<
@@ -1074,28 +993,42 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, struct brcms_varbuf *b)
continue;
if (flags & SRFL_CCODE) {
- if (val == 0)
- varbuf_append(b, "ccode=");
- else
- varbuf_append(b, "ccode=%c%c",
- (val >> 8), (val & 0xff));
- }
- /* LED Powersave duty cycle has to be scaled:
- *(oncount >> 24) (offcount >> 8)
- */
- else if (flags & SRFL_LEDDC) {
- u32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */
- (((val & 0xff)) << 8); /* offcount */
- varbuf_append(b, "leddc=%d", w32);
- } else if (flags & SRFL_PRHEX)
- varbuf_append(b, "%s=0x%x", name, val);
- else if ((flags & SRFL_PRSIGN)
- && (val & (1 << (width - 1))))
- varbuf_append(b, "%s=%d", name,
- (int)(val | (~0 << width)));
+ type = BRCMS_SROM_STRING;
+ } else if (flags & SRFL_LEDDC) {
+ /* LED Powersave duty cycle has to be scaled:
+ *(oncount >> 24) (offcount >> 8)
+ */
+ u32 w32 = /* oncount */
+ (((val >> 8) & 0xff) << 24) |
+ /* offcount */
+ (((val & 0xff)) << 8);
+ type = BRCMS_SROM_UNUMBER;
+ val = w32;
+ } else if ((flags & SRFL_PRSIGN)
+ && (val & (1 << (width - 1)))) {
+ type = BRCMS_SROM_SNUMBER;
+ val |= ~0 << width;
+ } else
+ type = BRCMS_SROM_UNUMBER;
+ }
+
+ entry = kzalloc(sizeof(struct brcms_srom_list_head) +
+ extra_space, GFP_KERNEL);
+ entry->varid = id;
+ entry->var_type = type;
+ if (flags & SRFL_ETHADDR) {
+ snprintf(entry->buf, 18, "%pM", ea);
+ } else if (flags & SRFL_CCODE) {
+ if (val == 0)
+ entry->buf[0] = '\0';
else
- varbuf_append(b, "%s=%u", name, val);
+ snprintf(entry->buf, 3, "%c%c",
+ (val >> 8), (val & 0xff));
+ } else {
+ entry->uval = val;
}
+
+ list_add(&entry->var_list, var_list);
}
if (sromrev >= 4) {
@@ -1111,34 +1044,31 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, struct brcms_varbuf *b)
}
for (p = 0; p < MAX_PATH_SROM; p++) {
- for (srv = perpath_pci_sromvars; srv->name != NULL;
- srv++) {
+ for (srv = perpath_pci_sromvars;
+ srv->varid != BRCMS_SROM_NULL; srv++) {
if ((srv->revmask & sr) == 0)
continue;
- if (pb + srv->off < off)
- continue;
-
- /* This entry is for mfgc only. Don't generate param for it, */
if (srv->flags & SRFL_NOVAR)
continue;
- w = srom[pb + srv->off - off];
+ w = srom[pb + srv->off];
val = (w & srv->mask) >> mask_shift(srv->mask);
width = mask_width(srv->mask);
- /* Cheating: no per-path var is more than 1 word */
-
+ /* Cheating: no per-path var is more than
+ * 1 word */
if ((srv->flags & SRFL_NOFFS)
&& ((int)val == (1 << width) - 1))
continue;
- if (srv->flags & SRFL_PRHEX)
- varbuf_append(b, "%s%d=0x%x", srv->name,
- p, val);
- else
- varbuf_append(b, "%s%d=%d", srv->name,
- p, val);
+ entry =
+ kzalloc(sizeof(struct brcms_srom_list_head),
+ GFP_KERNEL);
+ entry->varid = srv->varid+p;
+ entry->var_type = BRCMS_SROM_UNUMBER;
+ entry->uval = val;
+ list_add(&entry->var_list, var_list);
}
pb += psz;
}
@@ -1146,17 +1076,90 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, struct brcms_varbuf *b)
}
/*
+ * Read in and validate sprom.
+ * Return 0 on success, nonzero on error.
+ */
+static int
+sprom_read_pci(struct si_pub *sih, u16 __iomem *sprom, uint wordoff,
+ u16 *buf, uint nwords, bool check_crc)
+{
+ int err = 0;
+ uint i;
+
+ /* read the sprom */
+ for (i = 0; i < nwords; i++)
+ buf[i] = R_REG(&sprom[wordoff + i]);
+
+ if (check_crc) {
+
+ if (buf[0] == 0xffff)
+ /*
+ * The hardware thinks that an srom that starts with
+ * 0xffff is blank, regardless of the rest of the
+ * content, so declare it bad.
+ */
+ return -ENODATA;
+
+ /* fixup the endianness so crc8 will pass */
+ htol16_buf(buf, nwords * 2);
+ if (crc8(brcms_srom_crc8_table, (u8 *) buf, nwords * 2,
+ CRC8_INIT_VALUE) !=
+ CRC8_GOOD_VALUE(brcms_srom_crc8_table))
+ /* DBG only pci always read srom4 first, then srom8/9 */
+ err = -EIO;
+
+ /* now correct the endianness of the byte array */
+ ltoh16_buf(buf, nwords * 2);
+ }
+ return err;
+}
+
+static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
+{
+ u8 *otp;
+ uint sz = OTP_SZ_MAX / 2; /* size in words */
+ int err = 0;
+
+ otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
+ if (otp == NULL)
+ return -ENOMEM;
+
+ err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
+
+ memcpy(buf, otp, bufsz);
+
+ kfree(otp);
+
+ /* Check CRC */
+ if (buf[0] == 0xffff)
+ /* The hardware thinks that an srom that starts with 0xffff
+ * is blank, regardless of the rest of the content, so declare
+ * it bad.
+ */
+ return -ENODATA;
+
+ /* fixup the endianness so crc8 will pass */
+ htol16_buf(buf, bufsz);
+ if (crc8(brcms_srom_crc8_table, (u8 *) buf, SROM4_WORDS * 2,
+ CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table))
+ err = -EIO;
+
+ /* now correct the endianness of the byte array */
+ ltoh16_buf(buf, bufsz);
+
+ return err;
+}
+
+/*
* Initialize nonvolatile variable table from sprom.
* Return 0 on success, nonzero on error.
*/
-static int initvars_srom_pci(struct si_pub *sih, void *curmap, char **vars,
- uint *count)
+static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
{
- u16 *srom, *sromwindow;
+ u16 *srom;
+ u16 __iomem *sromwindow;
u8 sromrev = 0;
u32 sr;
- struct brcms_varbuf b;
- char *vp, *base = NULL;
int err = 0;
/*
@@ -1166,7 +1169,9 @@ static int initvars_srom_pci(struct si_pub *sih, void *curmap, char **vars,
if (!srom)
return -ENOMEM;
- sromwindow = (u16 *) SROM_OFFSET(sih);
+ sromwindow = srom_window_address(sih, curmap);
+
+ crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY);
if (ai_is_sprom_available(sih)) {
err = sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
true);
@@ -1188,50 +1193,106 @@ static int initvars_srom_pci(struct si_pub *sih, void *curmap, char **vars,
if (sromrev == 0x10)
sromrev = 1;
}
- }
-#if defined(BCMNVRAMR)
- /* Use OTP if SPROM not available */
- else {
+ } else {
+ /* Use OTP if SPROM not available */
err = otp_read_pci(sih, srom, SROM_MAX);
if (err == 0)
/* OTP only contain SROM rev8/rev9 for now */
sromrev = srom[SROM4_CRCREV] & 0xff;
}
-#else
- else
- err = -ENODEV;
-#endif
if (!err) {
+ struct si_info *sii = (struct si_info *)sih;
+
/* Bitmask for the sromrev */
sr = 1 << sromrev;
- /* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, 9 */
+ /*
+ * srom version check: Current valid versions: 1, 2, 3, 4, 5, 8,
+ * 9
+ */
if ((sr & 0x33e) == 0) {
err = -EINVAL;
goto errout;
}
- base = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
- if (!base) {
- err = -ENOMEM;
- goto errout;
- }
-
- varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
+ INIT_LIST_HEAD(&sii->var_list);
/* parse SROM into name=value pairs. */
- _initvars_srom_pci(sromrev, srom, 0, &b);
-
- /* final nullbyte terminator */
- vp = b.buf;
- *vp++ = '\0';
-
- err = initvars_table(base, vp, vars, count);
- kfree(base);
+ _initvars_srom_pci(sromrev, srom, &sii->var_list);
}
errout:
kfree(srom);
return err;
}
+
+void srom_free_vars(struct si_pub *sih)
+{
+ struct si_info *sii;
+ struct brcms_srom_list_head *entry, *next;
+
+ sii = (struct si_info *)sih;
+ list_for_each_entry_safe(entry, next, &sii->var_list, var_list) {
+ list_del(&entry->var_list);
+ kfree(entry);
+ }
+}
+/*
+ * Initialize local vars from the right source for this platform.
+ * Return 0 on success, nonzero on error.
+ */
+int srom_var_init(struct si_pub *sih, void __iomem *curmap)
+{
+ uint len;
+
+ len = 0;
+
+ if (curmap != NULL)
+ return initvars_srom_pci(sih, curmap);
+
+ return -EINVAL;
+}
+
+/*
+ * Search the name=value vars for a specific one and return its value.
+ * Returns NULL if not found.
+ */
+char *getvar(struct si_pub *sih, enum brcms_srom_id id)
+{
+ struct si_info *sii;
+ struct brcms_srom_list_head *entry;
+
+ sii = (struct si_info *)sih;
+
+ list_for_each_entry(entry, &sii->var_list, var_list)
+ if (entry->varid == id)
+ return &entry->buf[0];
+
+ /* nothing found */
+ return NULL;
+}
+
+/*
+ * Search the vars for a specific one and return its value as
+ * an integer. Returns 0 if not found.-
+ */
+int getintvar(struct si_pub *sih, enum brcms_srom_id id)
+{
+ struct si_info *sii;
+ struct brcms_srom_list_head *entry;
+ unsigned long res;
+
+ sii = (struct si_info *)sih;
+
+ list_for_each_entry(entry, &sii->var_list, var_list)
+ if (entry->varid == id) {
+ if (entry->var_type == BRCMS_SROM_SNUMBER ||
+ entry->var_type == BRCMS_SROM_UNUMBER)
+ return (int)entry->sval;
+ else if (!kstrtoul(&entry->buf[0], 0, &res))
+ return (int)res;
+ }
+
+ return 0;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/srom.h b/drivers/staging/brcm80211/brcmsmac/srom.h
index efc4d1edd86d..708c43ff51cc 100644
--- a/drivers/staging/brcm80211/brcmsmac/srom.h
+++ b/drivers/staging/brcm80211/brcmsmac/srom.h
@@ -20,8 +20,8 @@
#include "types.h"
/* Prototypes */
-extern int srom_var_init(struct si_pub *sih, uint bus, void *curmap,
- char **vars, uint *count);
+extern int srom_var_init(struct si_pub *sih, void __iomem *curmap);
+extern void srom_free_vars(struct si_pub *sih);
extern int srom_read(struct si_pub *sih, uint bus, void *curmap,
uint byteoff, uint nbytes, u16 *buf, bool check_crc);
diff --git a/drivers/staging/brcm80211/brcmsmac/stf.c b/drivers/staging/brcm80211/brcmsmac/stf.c
index a55ff0101782..d8f528eb180c 100644
--- a/drivers/staging/brcm80211/brcmsmac/stf.c
+++ b/drivers/staging/brcm80211/brcmsmac/stf.c
@@ -22,7 +22,6 @@
#include "phy/phy_hal.h"
#include "channel.h"
#include "main.h"
-#include "bmac.h"
#include "stf.h"
#define MIN_SPATIAL_EXPANSION 0
@@ -31,20 +30,12 @@
#define BRCMS_STF_SS_STBC_RX(wlc) (BRCMS_ISNPHY(wlc->band) && \
NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6))
-static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val);
-static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts, u8 val);
-static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val);
-static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val);
-
-static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
-static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
- ratespec_t rspec);
-
#define NSTS_1 1
#define NSTS_2 2
#define NSTS_3 3
#define NSTS_4 4
-const u8 txcore_default[5] = {
+
+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 */
@@ -60,16 +51,16 @@ static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val)
return;
}
- wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_RX_STBC;
- wlc->ht_cap.cap_info |= (val << IEEE80211_HT_CAP_RX_STBC_SHIFT);
-
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 */
+/*
+ * 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;
@@ -81,21 +72,19 @@ void brcms_c_tempsense_upd(struct brcms_c_info *wlc)
txchain = active_chains & 0xf;
if (wlc->stf->txchain == wlc->stf->hw_txchain) {
- if (txchain && (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) {
+ 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,
- chanspec_t chanspec)
+ u16 chanspec)
{
struct tx_power power;
u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id;
@@ -120,16 +109,19 @@ brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel,
/* 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
+ /*
+ * 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
+ /*
+ * 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);
@@ -137,19 +129,12 @@ brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel,
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)) {
+ if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON))
return false;
- }
if ((int_val == ON) && (wlc->stf->txstreams == 1))
return false;
- if ((int_val == OFF) || (wlc->stf->txstreams == 1)
- || !BRCMS_STBC_CAP_PHY(wlc))
- wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
- else
- wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_TX_STBC;
-
wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val;
wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val;
@@ -159,9 +144,8 @@ static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val)
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)) {
+ && (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)
@@ -179,15 +163,13 @@ static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts,
BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n",
wlc->pub->unit, Nsts, core_mask);
- if (BRCMS_BITSCNT(core_mask) > wlc->stf->txstreams) {
+ if (hweight8(core_mask) > wlc->stf->txstreams)
core_mask = 0;
- }
- if ((BRCMS_BITSCNT(core_mask) == wlc->stf->txstreams) &&
+ if ((hweight8(core_mask) == wlc->stf->txstreams) &&
((core_mask & ~wlc->stf->txchain)
- || !(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 */
@@ -223,6 +205,60 @@ static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val)
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;
@@ -236,41 +272,14 @@ int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force)
|| !(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) BRCMS_BITSCNT(txchain);
+ /*
+ * 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;
- if (txstreams == 1) {
- for (i = 0; i < NBANDS(wlc); i++)
- if ((RSPEC_STF(wlc->bandstate[i]->rspec_override) !=
- PHY_TXC1_MODE_SISO)
- || (RSPEC_STF(wlc->bandstate[i]->mrspec_override) !=
- PHY_TXC1_MODE_SISO)) {
- if (!force)
- return -EBADE;
-
- /* over-write the override rspec */
- if (RSPEC_STF(wlc->bandstate[i]->rspec_override)
- != PHY_TXC1_MODE_SISO) {
- wlc->bandstate[i]->rspec_override = 0;
- wiphy_err(wlc->wiphy, "%s(): temp "
- "sense override non-SISO "
- "rspec_override\n",
- __func__);
- }
- if (RSPEC_STF
- (wlc->bandstate[i]->mrspec_override) !=
- PHY_TXC1_MODE_SISO) {
- wlc->bandstate[i]->mrspec_override = 0;
- wiphy_err(wlc->wiphy, "%s(): temp "
- "sense override non-SISO "
- "mrspec_override\n",
- __func__);
- }
- }
- }
-
wlc->stf->txchain = txchain;
wlc->stf->txstreams = txstreams;
brcms_c_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx);
@@ -289,7 +298,10 @@ int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force)
return 0;
}
-/* update wlc->stf->ss_opmode which represents the operational stf_ss mode we're using */
+/*
+ * 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;
@@ -298,21 +310,22 @@ int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band)
prev_stf_ss = wlc->stf->ss_opmode;
- /* NOTE: opmode can only be SISO or CDD as STBC is decided on a per-packet basis */
+ /*
+ * 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->no_cddstbc || (wlc->stf->txstreams == 1)
- || isset(&wlc->stf->ss_algo_channel,
- PHY_TXC1_MODE_SISO)) ? PHY_TXC1_MODE_SISO
- : PHY_TXC1_MODE_CDD;
+ 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->no_cddstbc
- || (wlc->stf->txstreams ==
- 1)) ? PHY_TXC1_MODE_SISO : band->
- band_stf_ss_mode;
+ 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;
@@ -340,7 +353,8 @@ int brcms_c_stf_attach(struct brcms_c_info *wlc)
if (BRCMS_STBC_CAP_PHY(wlc)) {
wlc->stf->ss_algosel_auto = true;
- wlc->stf->ss_algo_channel = (u16) -1; /* Init the default value */
+ /* Init the default value */
+ wlc->stf->ss_algo_channel = (u16) -1;
}
return 0;
}
@@ -349,59 +363,6 @@ void brcms_c_stf_detach(struct brcms_c_info *wlc)
{
}
-/*
- * 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);
-}
-
void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
{
_brcms_c_stf_phy_txant_upd(wlc);
@@ -410,31 +371,29 @@ void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc)
{
/* get available rx/tx chains */
- wlc->stf->hw_txchain = (u8) getintvar(wlc->pub->vars, "txchain");
- wlc->stf->hw_rxchain = (u8) getintvar(wlc->pub->vars, "rxchain");
+ wlc->stf->hw_txchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_TXCHAIN);
+ wlc->stf->hw_rxchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_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)) {
+ if (BRCMS_ISNPHY(wlc->band))
wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY;
- } else {
+ else
wlc->stf->hw_txchain = TXCHAIN_DEF;
- }
}
wlc->stf->txchain = wlc->stf->hw_txchain;
- wlc->stf->txstreams = (u8) BRCMS_BITSCNT(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)) {
+ if (BRCMS_ISNPHY(wlc->band))
wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY;
- } else {
+ else
wlc->stf->hw_rxchain = RXCHAIN_DEF;
- }
}
wlc->stf->rxchain = wlc->stf->hw_rxchain;
- wlc->stf->rxstreams = (u8) BRCMS_BITSCNT(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));
@@ -445,24 +404,24 @@ void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc)
}
static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
- ratespec_t rspec)
+ u32 rspec)
{
u16 phytxant = wlc->stf->phytxant;
- if (RSPEC_STF(rspec) != PHY_TXC1_MODE_SISO) {
+ if (rspec_stf(rspec) != PHY_TXC1_MODE_SISO)
phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
- } else if (wlc->stf->txant == ANT_TX_DEF)
+ 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, ratespec_t rspec)
+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, ratespec_t 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;
diff --git a/drivers/staging/brcm80211/brcmsmac/stf.h b/drivers/staging/brcm80211/brcmsmac/stf.h
index 06c2a399649e..19f6580f69be 100644
--- a/drivers/staging/brcm80211/brcmsmac/stf.h
+++ b/drivers/staging/brcm80211/brcmsmac/stf.h
@@ -25,7 +25,7 @@ extern void brcms_c_stf_detach(struct brcms_c_info *wlc);
extern void brcms_c_tempsense_upd(struct brcms_c_info *wlc);
extern void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc,
u16 *ss_algo_channel,
- chanspec_t chanspec);
+ u16 chanspec);
extern int brcms_c_stf_ss_update(struct brcms_c_info *wlc,
struct brcms_band *band);
extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
@@ -35,8 +35,8 @@ extern bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val);
extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
extern void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc);
extern u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
- ratespec_t rspec);
+ u32 rspec);
extern u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc,
- ratespec_t rspec);
+ u32 rspec);
#endif /* _BRCM_STF_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/types.h b/drivers/staging/brcm80211/brcmsmac/types.h
index 823b5e4672e2..27a814b07462 100644
--- a/drivers/staging/brcm80211/brcmsmac/types.h
+++ b/drivers/staging/brcm80211/brcmsmac/types.h
@@ -20,59 +20,77 @@
#include <linux/types.h>
#include <linux/io.h>
-/* Bus types */
-#define SI_BUS 0 /* SOC Interconnect */
-#define PCI_BUS 1 /* PCI target */
-#define SDIO_BUS 3 /* SDIO target */
-#define JTAG_BUS 4 /* JTAG */
-#define USB_BUS 5 /* USB (does not support R/W REG) */
-#define SPI_BUS 6 /* gSPI target */
-#define RPC_BUS 7 /* RPC target */
-
#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
-#define MAX_DMA_SEGS 4
-
/* boardflags */
-#define BFL_PACTRL 0x00000002 /* Board has gpio 9 controlling the PA */
-#define BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */
-#define BFL_FEM 0x00000800 /* Board supports the Front End Module */
-#define BFL_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */
-#define BFL_NOPA 0x00010000 /* Board has no PA */
-#define BFL_BUCKBOOST 0x00200000 /* Power topology uses BUCKBOOST */
-#define BFL_FEM_BT 0x00400000 /* Board has FEM and switch to share antenna w/ BT */
-#define BFL_NOCBUCK 0x00800000 /* Power topology doesn't use CBUCK */
-#define BFL_PALDO 0x02000000 /* Power topology uses PALDO */
-#define BFL_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */
+
+/* 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 */
-#define BFL2_RXBB_INT_REG_DIS 0x00000001 /* Board has an external rxbb regulator */
-#define BFL2_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */
-#define BFL2_TXPWRCTRL_EN 0x00000004 /* Board permits enabling TX Power Control */
-#define BFL2_2X4_DIV 0x00000008 /* Board supports the 2X4 diversity switch */
-#define BFL2_5G_PWRGAIN 0x00000010 /* Board supports 5G band power gain */
-#define BFL2_PCIEWAR_OVR 0x00000020 /* Board overrides ASPM and Clkreq settings */
+
+/* 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
-#define BFL2_SKWRKFEM_BRD 0x00000100 /* 4321mcm93 board uses Skyworks FEM */
-#define BFL2_SPUR_WAR 0x00000200 /* Board has a WAR for clock-harmonic spurs */
-#define BFL2_GPLL_WAR 0x00000400 /* Flag to narrow G-band PLL loop b/w */
-#define BFL2_SINGLEANT_CCK 0x00001000 /* Tx CCK pkts on Ant 0 only */
-#define BFL2_2G_SPUR_WAR 0x00002000 /* WAR to reduce and avoid clock-harmonic spurs in 2G */
-#define BFL2_GPLL_WAR2 0x00010000 /* Flag to widen G-band PLL loop b/w */
+/* 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
-#define BFL2_INTERNDET_TXIQCAL 0x00040000 /* Use internal envelope detector for TX IQCAL */
-#define BFL2_XTALBUFOUTEN 0x00080000 /* Keep the buffered Xtal output from radio "ON"
- * Most drivers will turn it off without this flag
- * to save power.
- */
+/* 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 */
-#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */
-#define BOARD_GPIO_12 0x1000 /* gpio 12 */
-#define BOARD_GPIO_13 0x2000 /* gpio 13 */
+/*
+ * 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
@@ -152,30 +170,53 @@
#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 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_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 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 D11REV_IS(var, val) \
+ (D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val))))
-#define PHYTYPE_IS(var, val) (PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val))))
+#define D11REV_GE(var, val) \
+ (D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val))))
-/* Finally, early-exit from switch case if anyone wants it... */
+#define D11REV_GT(var, val) \
+ (D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val))))
-#define CASECHECK(config, val) if (!(CONF_HAS(config, val))) break
-#define CASEMSK(config, mask) if (!(CONF_MSK(config, mask))) break
+#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) */
@@ -203,116 +244,36 @@
* ********************************************************************
*/
-/*************************************************
- * Defaults for tunables (e.g. sizing constants)
- *
- * For each new tunable, add a member to the end
- * of struct brcms_tunables in brcms_c_pub.h to enable
- * runtime checks of tunable values. (Directly
- * using the macros in code invalidates ROM code)
- *
- * ***********************************************
- */
-#define NTXD 256 /* Max # of entries in Tx FIFO based on 4kb page size */
-#define NRXD 256 /* Max # of entries in Rx FIFO based on 4kb page size */
-#define NRXBUFPOST 32 /* try to keep this # rbufs posted to the chip */
-#define MAXSCB 32 /* Maximum SCBs in cache for STA */
-#define AMPDU_NUM_MPDU 16 /* max allowed number of mpdus in an ampdu (2 streams) */
-
-/* Count of packet callback structures. either of following
- * 1. Set to the number of SCBs since a STA
- * can queue up a rate callback for each IBSS STA it knows about, and an AP can
- * queue up an "are you there?" Null Data callback for each associated STA
- * 2. controlled by tunable config file
- */
-#define MAXPKTCB MAXSCB /* Max number of packet callbacks */
-
-/* NetBSD also needs to keep track of this */
-
-/* Number of BSS handled in ucode bcn/prb */
-#define BRCMS_MAX_UCODE_BSS (16)
-/* Number of BSS handled in sw bcn/prb */
-#define BRCMS_MAX_UCODE_BSS4 (4)
-/* max # BSS configs */
-#define BRCMS_MAXBSSCFG (1)
-/* max # available networks */
-#define MAXBSS 64
-/* data msg txq hiwat mark */
-#define BRCMS_DATAHIWAT 50
-#define BRCMS_AMPDUDATAHIWAT 255
-
-/* bounded rx loops */
-#define RXBND 8 /* max # frames to process in brcms_c_recv() */
-#define TXSBND 8 /* max # tx status to process in wlc_txstatus() */
-
-#define BAND_5G(bt) ((bt) == BRCM_BAND_5G)
-#define BAND_2G(bt) ((bt) == BRCM_BAND_2G)
-
#define BCMMSG(dev, fmt, args...) \
do { \
if (brcm_msg_level & LOG_TRACE_VAL) \
wiphy_err(dev, "%s: " fmt, __func__, ##args); \
} while (0)
-#define WL_ERROR_ON() (brcm_msg_level & LOG_ERROR_VAL)
-
-/* register access macros */
-#ifndef __BIG_ENDIAN
-#ifndef __mips__
-#define R_REG(r) \
- ({\
- sizeof(*(r)) == sizeof(u8) ? \
- readb((u8 *)(r)) : \
- sizeof(*(r)) == sizeof(u16) ? readw((u16 *)(r)) : \
- readl((u32 *)(r)); \
- })
-#else /* __mips__ */
-#define R_REG(r) \
- ({ \
- __typeof(*(r)) __osl_v; \
- __asm__ __volatile__("sync"); \
- switch (sizeof(*(r))) { \
- case sizeof(u8): \
- __osl_v = readb((u8 *)(r)); \
- break; \
- case sizeof(u16): \
- __osl_v = readw((u16 *)(r)); \
- break; \
- case sizeof(u32): \
- __osl_v = \
- readl((u32 *)(r)); \
- break; \
- } \
- __asm__ __volatile__("sync"); \
- __osl_v; \
- })
-#endif /* __mips__ */
+/*
+ * Register access macros.
+ *
+ * These macro's take a pointer to the address to read as one of their
+ * arguments. The macro itself deduces the size of the IO transaction (u8, u16
+ * or u32). Advantage of this approach in combination with using a struct to
+ * define the registers in a register block, is that access size and access
+ * location are defined in only one spot. This reduces the risk of the
+ * programmer trying to use an unsupported transaction size on a register.
+ *
+ */
-#define W_REG(r, v) do { \
- switch (sizeof(*(r))) { \
- case sizeof(u8): \
- writeb((u8)(v), (u8 *)(r)); break; \
- case sizeof(u16): \
- writew((u16)(v), (u16 *)(r)); break; \
- case sizeof(u32): \
- writel((u32)(v), (u32 *)(r)); break; \
- }; \
- } while (0)
-#else /* __BIG_ENDIAN */
#define R_REG(r) \
({ \
__typeof(*(r)) __osl_v; \
switch (sizeof(*(r))) { \
case sizeof(u8): \
- __osl_v = \
- readb((u8 *)((r)^3)); \
+ __osl_v = readb((u8 __iomem *)(r)); \
break; \
case sizeof(u16): \
- __osl_v = \
- readw((u16 *)((r)^2)); \
+ __osl_v = readw((u16 __iomem *)(r)); \
break; \
case sizeof(u32): \
- __osl_v = readl((u32 *)(r)); \
+ __osl_v = readl((u32 __iomem *)(r)); \
break; \
} \
__osl_v; \
@@ -321,19 +282,18 @@ do { \
#define W_REG(r, v) do { \
switch (sizeof(*(r))) { \
case sizeof(u8): \
- writeb((u8)(v), \
- (u8 *)((r)^3)); break; \
+ writeb((u8)((v) & 0xFF), (u8 __iomem *)(r)); \
+ break; \
case sizeof(u16): \
- writew((u16)(v), \
- (u16 *)((r)^2)); break; \
+ writew((u16)((v) & 0xFFFF), (u16 __iomem *)(r)); \
+ break; \
case sizeof(u32): \
- writel((u32)(v), \
- (u32 *)(r)); break; \
+ writel((u32)(v), (u32 __iomem *)(r)); \
+ break; \
} \
} while (0)
-#endif /* __BIG_ENDIAN */
-#ifdef __mips__
+#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
@@ -342,7 +302,7 @@ do { \
#define W_REG_FLUSH(r, v) ({ W_REG((r), (v)); (void)R_REG(r); })
#else
#define W_REG_FLUSH(r, v) W_REG((r), (v))
-#endif /* __mips__ */
+#endif /* CONFIG_BCM47XX */
#define AND_REG(r, v) W_REG((r), R_REG(r) & (v))
#define OR_REG(r, v) W_REG((r), R_REG(r) | (v))
@@ -351,12 +311,17 @@ do { \
W_REG((r), ((R_REG(r) & ~(mask)) | (val)))
/* multi-bool data type: set of bools, mbool is true if any is set */
-typedef u32 mbool;
-#define mboolset(mb, bit) ((mb) |= (bit)) /* set one bool */
-#define mboolclr(mb, bit) ((mb) &= ~(bit)) /* clear one bool */
-#define mboolisset(mb, bit) (((mb) & (bit)) != 0) /* true if one bool 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;
@@ -364,34 +329,22 @@ struct ieee80211_tx_queue_params;
struct brcms_info;
struct brcms_c_info;
struct brcms_hardware;
-struct brcms_c_if;
-struct brcmu_iovar;
-struct brcmu_strbuf;
struct brcms_txq_info;
struct brcms_band;
struct dma_pub;
struct si_pub;
struct tx_status;
struct d11rxhdr;
-struct brcms_d11rxhdr;
struct txpwr_limits;
-struct brcms_phy;
-
-typedef volatile struct intctrlregs intctrlregs_t;
-typedef volatile struct pio2regs pio2regs_t;
-typedef volatile struct pio2regp pio2regp_t;
-typedef volatile struct pio4regs pio4regs_t;
-typedef volatile struct pio4regp pio4regp_t;
-typedef volatile struct fifo64 fifo64_t;
-typedef volatile struct d11regs d11regs_t;
-typedef volatile struct dma32diag dma32diag_t;
-typedef volatile struct dma64regs dma64regs_t;
-typedef struct brcms_rateset wlc_rateset_t;
-typedef u32 ratespec_t;
-typedef struct chanvec chanvec_t;
-typedef s32 fixed;
-typedef struct _cs32 cs32;
-typedef volatile union pmqreg pmqreg_t;
+
+/* 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;
diff --git a/drivers/staging/brcm80211/brcmsmac/ucode_loader.c b/drivers/staging/brcm80211/brcmsmac/ucode_loader.c
index bf733fb18ce1..80e3ccf865e3 100644
--- a/drivers/staging/brcm80211/brcmsmac/ucode_loader.c
+++ b/drivers/staging/brcm80211/brcmsmac/ucode_loader.c
@@ -37,79 +37,73 @@ enum {
D11UCODE_OVERSIGHT_BOMMINOR
};
-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;
-u32 *bcm43xx_16_mimo;
-u32 bcm43xx_16_mimosz;
-u32 *bcm43xx_24_lcn;
-u32 bcm43xx_24_lcnsz;
-u32 *bcm43xx_bommajor;
-u32 *bcm43xx_bomminor;
-
-int brcms_ucode_data_init(struct brcms_info *wl)
+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 **)&d11lcn0bsinitvals24,
+ brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0bsinitvals24,
D11LCN0BSINITVALS24);
- rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11lcn0initvals24,
- D11LCN0INITVALS24);
- rc = rc < 0 ? rc :
- brcms_ucode_init_buf(wl, (void **)&d11lcn1bsinitvals24,
- D11LCN1BSINITVALS24);
- rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11lcn1initvals24,
- D11LCN1INITVALS24);
+ 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 **)&d11lcn2bsinitvals24,
+ brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2bsinitvals24,
D11LCN2BSINITVALS24);
- rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11lcn2initvals24,
- D11LCN2INITVALS24);
- rc = rc < 0 ? rc :
- brcms_ucode_init_buf(wl, (void **)&d11n0absinitvals16,
- D11N0ABSINITVALS16);
- rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11n0bsinitvals16,
- D11N0BSINITVALS16);
- rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11n0initvals16,
- D11N0INITVALS16);
- rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_16_mimo,
- D11UCODE_OVERSIGHT16_MIMO);
- rc = rc < 0 ? rc : brcms_ucode_init_uint(wl, &bcm43xx_16_mimosz,
- D11UCODE_OVERSIGHT16_MIMOSZ);
- rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_24_lcn,
- D11UCODE_OVERSIGHT24_LCN);
- rc = rc < 0 ? rc : brcms_ucode_init_uint(wl, &bcm43xx_24_lcnsz,
- D11UCODE_OVERSIGHT24_LCNSZ);
- rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_bommajor,
- D11UCODE_OVERSIGHT_BOMMAJOR);
- rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_bomminor,
- D11UCODE_OVERSIGHT_BOMMINOR);
+ 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(void)
+void brcms_ucode_data_free(struct brcms_ucode *ucode)
{
- brcms_ucode_free_buf((void *)d11lcn0bsinitvals24);
- brcms_ucode_free_buf((void *)d11lcn0initvals24);
- brcms_ucode_free_buf((void *)d11lcn1bsinitvals24);
- brcms_ucode_free_buf((void *)d11lcn1initvals24);
- brcms_ucode_free_buf((void *)d11lcn2bsinitvals24);
- brcms_ucode_free_buf((void *)d11lcn2initvals24);
- brcms_ucode_free_buf((void *)d11n0absinitvals16);
- brcms_ucode_free_buf((void *)d11n0bsinitvals16);
- brcms_ucode_free_buf((void *)d11n0initvals16);
- brcms_ucode_free_buf((void *)bcm43xx_16_mimo);
- brcms_ucode_free_buf((void *)bcm43xx_24_lcn);
- brcms_ucode_free_buf((void *)bcm43xx_bommajor);
- brcms_ucode_free_buf((void *)bcm43xx_bomminor);
-
- return;
+ 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);
}
diff --git a/drivers/staging/brcm80211/brcmsmac/ucode_loader.h b/drivers/staging/brcm80211/brcmsmac/ucode_loader.h
index ca53deced7bf..18750a814b4f 100644
--- a/drivers/staging/brcm80211/brcmsmac/ucode_loader.h
+++ b/drivers/staging/brcm80211/brcmsmac/ucode_loader.h
@@ -13,6 +13,8 @@
* 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 */
@@ -21,32 +23,36 @@
#define UCODE_LOADER_API_VER 0
-struct d11init {
- u16 addr;
- u16 size;
- u32 value;
+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;
};
-extern struct d11init *d11lcn0bsinitvals24;
-extern struct d11init *d11lcn0initvals24;
-extern struct d11init *d11lcn1bsinitvals24;
-extern struct d11init *d11lcn1initvals24;
-extern struct d11init *d11lcn2bsinitvals24;
-extern struct d11init *d11lcn2initvals24;
-extern struct d11init *d11n0absinitvals16;
-extern struct d11init *d11n0bsinitvals16;
-extern struct d11init *d11n0initvals16;
-extern u32 *bcm43xx_16_mimo;
-extern u32 bcm43xx_16_mimosz;
-extern u32 *bcm43xx_24_lcn;
-extern u32 bcm43xx_24_lcnsz;
-
-extern int brcms_ucode_data_init(struct brcms_info *wl);
-extern void brcms_ucode_data_free(void);
+extern int
+brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode);
+
+extern void brcms_ucode_data_free(struct brcms_ucode *ucode);
extern int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf,
unsigned int idx);
-extern int brcms_ucode_init_uint(struct brcms_info *wl, unsigned *data,
- unsigned int idx);
+extern int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes,
+ unsigned int idx);
extern void brcms_ucode_free_buf(void *);
extern int brcms_check_firmwares(struct brcms_info *wl);
+
+#endif /* _BRCM_UCODE_H_ */
diff --git a/drivers/staging/brcm80211/brcmutil/Makefile b/drivers/staging/brcm80211/brcmutil/Makefile
index 6403423c0212..45b808d747e2 100644
--- a/drivers/staging/brcm80211/brcmutil/Makefile
+++ b/drivers/staging/brcm80211/brcmutil/Makefile
@@ -20,8 +20,7 @@ ccflags-y := \
-Idrivers/staging/brcm80211/include
BRCMUTIL_OFILES := \
- utils.o \
- wifi.o
+ utils.o
MODULEPFX := brcmutil
diff --git a/drivers/staging/brcm80211/brcmutil/utils.c b/drivers/staging/brcm80211/brcmutil/utils.c
index 37b6b7797793..f27c48910827 100644
--- a/drivers/staging/brcm80211/brcmutil/utils.c
+++ b/drivers/staging/brcm80211/brcmutil/utils.c
@@ -15,6 +15,7 @@
*/
#include <linux/netdevice.h>
+#include <linux/module.h>
#include <brcmu_utils.h>
MODULE_AUTHOR("Broadcom Corporation");
@@ -219,7 +220,7 @@ EXPORT_SYMBOL(brcmu_pktq_pdeq_tail);
void
brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir,
- ifpkt_cb_t fn, void *arg)
+ bool (*fn)(struct sk_buff *, void *), void *arg)
{
struct pktq_prec *q;
struct sk_buff *p, *prev = NULL;
@@ -244,14 +245,13 @@ brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir,
}
}
- if (q->head == NULL) {
+ if (q->head == NULL)
q->tail = NULL;
- }
}
EXPORT_SYMBOL(brcmu_pktq_pflush);
void brcmu_pktq_flush(struct pktq *pq, bool dir,
- ifpkt_cb_t fn, void *arg)
+ bool (*fn)(struct sk_buff *, void *), void *arg)
{
int prec;
for (prec = 0; prec < pq->num_prec; prec++)
@@ -350,21 +350,6 @@ struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
}
EXPORT_SYMBOL(brcmu_pktq_mdeq);
-/* parse a xx:xx:xx:xx:xx:xx format ethernet address */
-int brcmu_ether_atoe(char *p, u8 *ea)
-{
- int i = 0;
-
- for (;;) {
- ea[i++] = (char)simple_strtoul(p, &p, 16);
- if (!*p++ || i == 6)
- break;
- }
-
- return i == 6;
-}
-EXPORT_SYMBOL(brcmu_ether_atoe);
-
#if defined(BCMDBG)
/* pretty hex print a pkt buffer chain */
void brcmu_prpkt(const char *msg, struct sk_buff *p0)
@@ -380,232 +365,11 @@ void brcmu_prpkt(const char *msg, struct sk_buff *p0)
EXPORT_SYMBOL(brcmu_prpkt);
#endif /* defined(BCMDBG) */
-/* iovar table lookup */
-const struct brcmu_iovar *brcmu_iovar_lookup(const struct brcmu_iovar *table,
- const char *name)
-{
- const struct brcmu_iovar *vi;
- const char *lookup_name;
-
- /* skip any ':' delimited option prefixes */
- lookup_name = strrchr(name, ':');
- if (lookup_name != NULL)
- lookup_name++;
- else
- lookup_name = name;
-
- for (vi = table; vi->name; vi++) {
- if (!strcmp(vi->name, lookup_name))
- return vi;
- }
- /* ran to end of table */
-
- return NULL; /* var name not found */
-}
-EXPORT_SYMBOL(brcmu_iovar_lookup);
-
-int brcmu_iovar_lencheck(const struct brcmu_iovar *vi, void *arg, int len,
- bool set)
-{
- int bcmerror = 0;
-
- /* length check on io buf */
- switch (vi->type) {
- case IOVT_BOOL:
- case IOVT_INT8:
- case IOVT_INT16:
- case IOVT_INT32:
- case IOVT_UINT8:
- case IOVT_UINT16:
- case IOVT_UINT32:
- /* all integers are s32 sized args at the ioctl interface */
- if (len < (int)sizeof(int)) {
- bcmerror = -EOVERFLOW;
- }
- break;
-
- case IOVT_BUFFER:
- /* buffer must meet minimum length requirement */
- if (len < vi->minlen) {
- bcmerror = -EOVERFLOW;
- }
- break;
-
- case IOVT_VOID:
- if (!set) {
- /* Cannot return nil... */
- bcmerror = -ENOTSUPP;
- } else if (len) {
- /* Set is an action w/o parameters */
- bcmerror = -ENOBUFS;
- }
- break;
-
- default:
- /* unknown type for length check in iovar info */
- bcmerror = -ENOTSUPP;
- }
-
- return bcmerror;
-}
-EXPORT_SYMBOL(brcmu_iovar_lencheck);
-
-/*******************************************************************************
- * crc8
- *
- * Computes a crc8 over the input data using the polynomial:
- *
- * x^8 + x^7 +x^6 + x^4 + x^2 + 1
- *
- * The caller provides the initial value (either CRC8_INIT_VALUE
- * or the previous returned value) to allow for processing of
- * discontiguous blocks of data. When generating the CRC the
- * caller is responsible for complementing the final return value
- * and inserting it into the byte stream. When checking, a final
- * return value of CRC8_GOOD_VALUE indicates a valid CRC.
- *
- * Reference: Dallas Semiconductor Application Note 27
- * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
- * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
- * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
- *
- * ****************************************************************************
- */
-
-static const u8 crc8_table[256] = {
- 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
- 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
- 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
- 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
- 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
- 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
- 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
- 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
- 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
- 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
- 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
- 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
- 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
- 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
- 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
- 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
- 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
- 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
- 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
- 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
- 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
- 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
- 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
- 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
- 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
- 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
- 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
- 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
- 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
- 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
- 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
- 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
-};
-
-u8 brcmu_crc8(u8 *pdata, /* pointer to array of data to process */
- uint nbytes, /* number of input data bytes to process */
- u8 crc /* either CRC8_INIT_VALUE or previous return value */
- ) {
- /* loop over the buffer data */
- while (nbytes-- > 0)
- crc = crc8_table[(crc ^ *pdata++) & 0xff];
-
- return crc;
-}
-EXPORT_SYMBOL(brcmu_crc8);
-
+#if defined(BCMDBG)
/*
- * Traverse a string of 1-byte tag/1-byte length/variable-length value
- * triples, returning a pointer to the substring whose first element
- * matches tag
+ * print bytes formatted as hex to a string. return the resulting
+ * string length
*/
-struct brcmu_tlv *brcmu_parse_tlvs(void *buf, int buflen, uint key)
-{
- struct brcmu_tlv *elt;
- int totlen;
-
- elt = (struct brcmu_tlv *) buf;
- totlen = buflen;
-
- /* find tagged parameter */
- while (totlen >= 2) {
- int len = elt->len;
-
- /* validate remaining totlen */
- if ((elt->id == key) && (totlen >= (len + 2)))
- return elt;
-
- elt = (struct brcmu_tlv *) ((u8 *) elt + (len + 2));
- totlen -= (len + 2);
- }
-
- return NULL;
-}
-EXPORT_SYMBOL(brcmu_parse_tlvs);
-
-
-#if defined(BCMDBG)
-int
-brcmu_format_flags(const struct brcmu_bit_desc *bd, u32 flags, char *buf,
- int len)
-{
- int i;
- char *p = buf;
- char hexstr[16];
- int slen = 0, nlen = 0;
- u32 bit;
- const char *name;
-
- if (len < 2 || !buf)
- return 0;
-
- buf[0] = '\0';
-
- for (i = 0; flags != 0; i++) {
- bit = bd[i].bit;
- name = bd[i].name;
- if (bit == 0 && flags != 0) {
- /* print any unnamed bits */
- snprintf(hexstr, 16, "0x%X", flags);
- name = hexstr;
- flags = 0; /* exit loop */
- } else if ((flags & bit) == 0)
- continue;
- flags &= ~bit;
- nlen = strlen(name);
- slen += nlen;
- /* count btwn flag space */
- if (flags != 0)
- slen += 1;
- /* need NULL char as well */
- if (len <= slen)
- break;
- /* copy NULL char but don't count it */
- strncpy(p, name, nlen + 1);
- p += nlen;
- /* copy btwn flag space and NULL char */
- if (flags != 0)
- p += snprintf(p, 2, " ");
- len -= slen;
- }
-
- /* indicate the str was too short */
- if (flags != 0) {
- if (len < 2)
- p -= 2 - len; /* overwrite last char */
- p += snprintf(p, 2, ">");
- }
-
- return (int)(p - buf);
-}
-EXPORT_SYMBOL(brcmu_format_flags);
-
-/* print bytes formatted as hex to a string. return the resulting string length */
int brcmu_format_hex(char *str, const void *bytes, int len)
{
int i;
@@ -620,168 +384,3 @@ int brcmu_format_hex(char *str, const void *bytes, int len)
}
EXPORT_SYMBOL(brcmu_format_hex);
#endif /* defined(BCMDBG) */
-
-char *brcmu_chipname(uint chipid, char *buf, uint len)
-{
- const char *fmt;
-
- fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
- snprintf(buf, len, fmt, chipid);
- return buf;
-}
-EXPORT_SYMBOL(brcmu_chipname);
-
-uint brcmu_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
-{
- uint len;
-
- len = strlen(name) + 1;
-
- if ((len + datalen) > buflen)
- return 0;
-
- strncpy(buf, name, buflen);
-
- /* append data onto the end of the name string */
- memcpy(&buf[len], data, datalen);
- len += datalen;
-
- return len;
-}
-EXPORT_SYMBOL(brcmu_mkiovar);
-
-/* Quarter dBm units to mW
- * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
- * Table is offset so the last entry is largest mW value that fits in
- * a u16.
- */
-
-#define QDBM_OFFSET 153 /* Offset for first entry */
-#define QDBM_TABLE_LEN 40 /* Table size */
-
-/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
- * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
- */
-#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
-
-/* Largest mW value that will round down to the last table entry,
- * QDBM_OFFSET + QDBM_TABLE_LEN-1.
- * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
- * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
- */
-#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
-
-static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
-/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
-/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
-/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
-/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
-/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
-/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
-};
-
-u16 brcmu_qdbm_to_mw(u8 qdbm)
-{
- uint factor = 1;
- int idx = qdbm - QDBM_OFFSET;
-
- if (idx >= QDBM_TABLE_LEN) {
- /* clamp to max u16 mW value */
- return 0xFFFF;
- }
-
- /* scale the qdBm index up to the range of the table 0-40
- * where an offset of 40 qdBm equals a factor of 10 mW.
- */
- while (idx < 0) {
- idx += 40;
- factor *= 10;
- }
-
- /* return the mW value scaled down to the correct factor of 10,
- * adding in factor/2 to get proper rounding.
- */
- return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
-}
-EXPORT_SYMBOL(brcmu_qdbm_to_mw);
-
-u8 brcmu_mw_to_qdbm(u16 mw)
-{
- u8 qdbm;
- int offset;
- uint mw_uint = mw;
- uint boundary;
-
- /* handle boundary case */
- if (mw_uint <= 1)
- return 0;
-
- offset = QDBM_OFFSET;
-
- /* move mw into the range of the table */
- while (mw_uint < QDBM_TABLE_LOW_BOUND) {
- mw_uint *= 10;
- offset -= 40;
- }
-
- for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
- boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
- nqdBm_to_mW_map[qdbm]) / 2;
- if (mw_uint < boundary)
- break;
- }
-
- qdbm += (u8) offset;
-
- return qdbm;
-}
-EXPORT_SYMBOL(brcmu_mw_to_qdbm);
-
-uint brcmu_bitcount(u8 *bitmap, uint length)
-{
- uint bitcount = 0, i;
- u8 tmp;
- for (i = 0; i < length; i++) {
- tmp = bitmap[i];
- while (tmp) {
- bitcount++;
- tmp &= (tmp - 1);
- }
- }
- return bitcount;
-}
-EXPORT_SYMBOL(brcmu_bitcount);
-
-/* Initialization of brcmu_strbuf structure */
-void brcmu_binit(struct brcmu_strbuf *b, char *buf, uint size)
-{
- b->origsize = b->size = size;
- b->origbuf = b->buf = buf;
-}
-EXPORT_SYMBOL(brcmu_binit);
-
-/* Buffer sprintf wrapper to guard against buffer overflow */
-int brcmu_bprintf(struct brcmu_strbuf *b, const char *fmt, ...)
-{
- va_list ap;
- int r;
-
- va_start(ap, fmt);
- r = vsnprintf(b->buf, b->size, fmt, ap);
-
- /* Non Ansi C99 compliant returns -1,
- * Ansi compliant return r >= b->size,
- * stdlib returns 0, handle all
- */
- if ((r == -1) || (r >= (int)b->size) || (r == 0)) {
- b->size = 0;
- } else {
- b->size -= r;
- b->buf += r;
- }
-
- va_end(ap);
-
- return r;
-}
-EXPORT_SYMBOL(brcmu_bprintf);
diff --git a/drivers/staging/brcm80211/brcmutil/wifi.c b/drivers/staging/brcm80211/brcmutil/wifi.c
deleted file mode 100644
index b9ffe8682a27..000000000000
--- a/drivers/staging/brcm80211/brcmutil/wifi.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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>
-
-/*
- * 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.
- */
-bool brcmu_chspec_malformed(chanspec_t 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;
-}
-EXPORT_SYMBOL(brcmu_chspec_malformed);
-
-/*
- * This function returns the channel number that control traffic is being sent on, for legacy
- * channels this is just the channel number, for 40MHZ channels it is the upper or lowre 20MHZ
- * sideband depending on the chanspec selected
- */
-u8 brcmu_chspec_ctlchan(chanspec_t chspec)
-{
- u8 ctl_chan;
-
- /* Is there a sideband ? */
- if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) {
- return CHSPEC_CHANNEL(chspec);
- } else {
- /* we only support 40MHZ with sidebands */
- /* chanspec channel holds the centre frequency, use that and the
- * side band information to reconstruct the control channel number
- */
- if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) {
- /* control chan is the upper 20 MHZ SB of the 40MHZ channel */
- ctl_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec));
- } else {
- /* control chan is the lower 20 MHZ SB of the 40MHZ channel */
- ctl_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec));
- }
- }
-
- return ctl_chan;
-}
-EXPORT_SYMBOL(brcmu_chspec_ctlchan);
-
-/*
- * Return the channel number for a given frequency and base frequency.
- * The returned channel number is relative to the given base frequency.
- * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
- * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
- *
- * Frequency is specified in MHz.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
- * 2.4 GHz and 5 GHz bands.
- *
- * The returned channel will be in the range [1, 14] in the 2.4 GHz band
- * and [0, 200] otherwise.
- * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
- * frequency is not a 2.4 GHz channel, or if the frequency is not and even
- * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- */
-int brcmu_mhz2channel(uint freq, uint start_factor)
-{
- int ch = -1;
- uint base;
- int offset;
-
- /* take the default channel start frequency */
- if (start_factor == 0) {
- if (freq >= 2400 && freq <= 2500)
- start_factor = WF_CHAN_FACTOR_2_4_G;
- else if (freq >= 5000 && freq <= 6000)
- start_factor = WF_CHAN_FACTOR_5_G;
- }
-
- if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G)
- return 14;
-
- base = start_factor / 2;
-
- /* check that the frequency is in 1GHz range of the base */
- if ((freq < base) || (freq > base + 1000))
- return -1;
-
- offset = freq - base;
- ch = offset / 5;
-
- /* check that frequency is a 5MHz multiple from the base */
- if (offset != (ch * 5))
- return -1;
-
- /* restricted channel range check for 2.4G */
- if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13))
- return -1;
-
- return ch;
-}
-EXPORT_SYMBOL(brcmu_mhz2channel);
diff --git a/drivers/staging/brcm80211/include/brcmu_utils.h b/drivers/staging/brcm80211/include/brcmu_utils.h
index 2d54cc5f4b11..7d0f46e0eb95 100644
--- a/drivers/staging/brcm80211/include/brcmu_utils.h
+++ b/drivers/staging/brcm80211/include/brcmu_utils.h
@@ -19,18 +19,6 @@
#include <linux/skbuff.h>
-/* Buffer structure for collecting string-formatted data
-* using brcmu_bprintf() API.
-* Use brcmu_binit() to initialize before use
-*/
-
-struct brcmu_strbuf {
- char *buf; /* pointer to current position in origbuf */
- unsigned int size; /* current (residual) size in bytes */
- char *origbuf; /* unmodified pointer to orignal buffer */
- unsigned int origsize; /* unmodified orignal buffer size in bytes */
-};
-
/*
* Spin at most 'us' microseconds while 'exp' is true.
* Caller should explicitly test 'exp' when this completes
@@ -45,12 +33,36 @@ struct brcmu_strbuf {
}
/* osl multi-precedence packet queue */
-#ifndef PKTQ_LEN_DEFAULT
#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */
-#endif
-#ifndef PKTQ_MAX_PREC
#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */
-#endif
+
+#define BCME_STRLEN 64 /* Max string length for BCM errors */
+
+/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
+#define PKTBUFSZ 2048
+
+#ifndef setbit
+#ifndef NBBY /* the BSD family defines NBBY */
+#define NBBY 8 /* 8 bits per byte */
+#endif /* #ifndef NBBY */
+#define setbit(a, i) (((u8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY))
+#define clrbit(a, i) (((u8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define isset(a, i) (((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY)))
+#define isclr(a, i) ((((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#endif /* setbit */
+
+#define NBITS(type) (sizeof(type) * 8)
+#define NBITVAL(nbits) (1 << (nbits))
+#define MAXBITVAL(nbits) ((1 << (nbits)) - 1)
+#define NBITMASK(nbits) MAXBITVAL(nbits)
+#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8)
+
+/* crc defines */
+#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */
+#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */
+
+/* 18-bytes of Ethernet address buffer length */
+#define ETHER_ADDR_STR_LEN 18
struct pktq_prec {
struct sk_buff *head; /* first packet to dequeue */
@@ -72,19 +84,37 @@ struct pktq {
struct pktq_prec q[PKTQ_MAX_PREC];
};
-/* fn(pkt, arg). return true if pkt belongs to if */
-typedef bool(*ifpkt_cb_t) (struct sk_buff *, void *);
-
/* operations on a specific precedence in packet queue */
-#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max))
-#define pktq_plen(pq, prec) ((pq)->q[prec].len)
-#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len)
-#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max)
-#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0)
+static inline int pktq_plen(struct pktq *pq, int prec)
+{
+ return pq->q[prec].len;
+}
-#define pktq_ppeek(pq, prec) ((pq)->q[prec].head)
-#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail)
+static inline int pktq_pavail(struct pktq *pq, int prec)
+{
+ return pq->q[prec].max - pq->q[prec].len;
+}
+
+static inline bool pktq_pfull(struct pktq *pq, int prec)
+{
+ return pq->q[prec].len >= pq->q[prec].max;
+}
+
+static inline bool pktq_pempty(struct pktq *pq, int prec)
+{
+ return pq->q[prec].len == 0;
+}
+
+static inline struct sk_buff *pktq_ppeek(struct pktq *pq, int prec)
+{
+ return pq->q[prec].head;
+}
+
+static inline struct sk_buff *pktq_ppeek_tail(struct pktq *pq, int prec)
+{
+ return pq->q[prec].tail;
+}
extern struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec,
struct sk_buff *p);
@@ -98,8 +128,9 @@ extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len);
extern void brcmu_pkt_buf_free_skb(struct sk_buff *skb);
/* Empty the queue at particular precedence level */
+/* callback function fn(pkt, arg) returns true if pkt belongs to if */
extern void brcmu_pktq_pflush(struct pktq *pq, int prec,
- bool dir, ifpkt_cb_t fn, void *arg);
+ bool dir, bool (*fn)(struct sk_buff *, void *), void *arg);
/* operations on a set of precedences in packet queue */
@@ -109,25 +140,36 @@ extern struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
/* operations on packet queue as a whole */
-#define pktq_len(pq) ((int)(pq)->len)
-#define pktq_max(pq) ((int)(pq)->max)
-#define pktq_avail(pq) ((int)((pq)->max - (pq)->len))
-#define pktq_full(pq) ((pq)->len >= (pq)->max)
-#define pktq_empty(pq) ((pq)->len == 0)
+static inline int pktq_len(struct pktq *pq)
+{
+ return (int)pq->len;
+}
+
+static inline int pktq_max(struct pktq *pq)
+{
+ return (int)pq->max;
+}
+
+static inline int pktq_avail(struct pktq *pq)
+{
+ return (int)(pq->max - pq->len);
+}
+
+static inline bool pktq_full(struct pktq *pq)
+{
+ return pq->len >= pq->max;
+}
-/* operations for single precedence queues */
-#define pktenq(pq, p) brcmu_pktq_penq(((struct pktq *)pq), 0, (p))
-#define pktenq_head(pq, p)\
- brcmu_pktq_penq_head(((struct pktq *)pq), 0, (p))
-#define pktdeq(pq) brcmu_pktq_pdeq(((struct pktq *)pq), 0)
-#define pktdeq_tail(pq) brcmu_pktq_pdeq_tail(((struct pktq *)pq), 0)
-#define pktqinit(pq, len) brcmu_pktq_init(((struct pktq *)pq), 1, len)
+static inline bool pktq_empty(struct pktq *pq)
+{
+ return pq->len == 0;
+}
extern void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len);
/* prec_out may be NULL if caller is not interested in return value */
extern struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out);
extern void brcmu_pktq_flush(struct pktq *pq, bool dir,
- ifpkt_cb_t fn, void *arg);
+ bool (*fn)(struct sk_buff *, void *), void *arg);
/* externs */
/* packet */
@@ -135,9 +177,6 @@ extern uint brcmu_pktfrombuf(struct sk_buff *p,
uint offset, int len, unsigned char *buf);
extern uint brcmu_pkttotlen(struct sk_buff *p);
-/* ethernet address */
-extern int brcmu_ether_atoe(char *p, u8 *ea);
-
/* ip address */
struct ipv4_addr;
@@ -147,155 +186,10 @@ extern void brcmu_prpkt(const char *msg, struct sk_buff *p0);
#define brcmu_prpkt(a, b)
#endif /* BCMDBG */
-/* Support for sharing code across in-driver iovar implementations.
- * The intent is that a driver use this structure to map iovar names
- * to its (private) iovar identifiers, and the lookup function to
- * find the entry. Macros are provided to map ids and get/set actions
- * into a single number space for a switch statement.
- */
-
-/* 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 */
-};
-
-/* varid definitions are per-driver, may use these get/set bits */
-
-/* IOVar action bits for id mapping */
-#define IOV_GET 0 /* Get an iovar */
-#define IOV_SET 1 /* Set an iovar */
-
-/* Varid to actionid mapping */
-#define IOV_GVAL(id) ((id)*2)
-#define IOV_SVAL(id) (((id)*2)+IOV_SET)
-#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET)
-#define IOV_ID(actionid) (actionid >> 1)
-
-extern const struct
-brcmu_iovar *brcmu_iovar_lookup(const struct brcmu_iovar *table,
- const char *name);
-extern int brcmu_iovar_lencheck(const struct brcmu_iovar *table, void *arg,
- int len, bool set);
-
-/* Base type definitions */
-#define IOVT_VOID 0 /* no value (implictly set only) */
-#define IOVT_BOOL 1 /* any value ok (zero/nonzero) */
-#define IOVT_INT8 2 /* integer values are range-checked */
-#define IOVT_UINT8 3 /* unsigned int 8 bits */
-#define IOVT_INT16 4 /* int 16 bits */
-#define IOVT_UINT16 5 /* unsigned int 16 bits */
-#define IOVT_INT32 6 /* int 32 bits */
-#define IOVT_UINT32 7 /* unsigned int 32 bits */
-#define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */
-#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER)
-
-/* ** driver/apps-shared section ** */
-
-#define BCME_STRLEN 64 /* Max string length for BCM errors */
-
-#ifndef ABS
-#define ABS(a) (((a) < 0) ? -(a) : (a))
-#endif /* ABS */
-
-#define CEIL(x, y) (((x) + ((y)-1)) / (y))
-#define ISPOWEROF2(x) ((((x)-1)&(x)) == 0)
-
-/* map physical to virtual I/O */
-#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), \
- (unsigned long)(size))
-
-/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
-#define PKTBUFSZ 2048
-
-#define OSL_SYSUPTIME() ((u32)jiffies * (1000 / HZ))
-
-#ifndef setbit
-#ifndef NBBY /* the BSD family defines NBBY */
-#define NBBY 8 /* 8 bits per byte */
-#endif /* #ifndef NBBY */
-#define setbit(a, i) (((u8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY))
-#define clrbit(a, i) (((u8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
-#define isset(a, i) (((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY)))
-#define isclr(a, i) ((((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
-#endif /* setbit */
-
-#define NBITS(type) (sizeof(type) * 8)
-#define NBITVAL(nbits) (1 << (nbits))
-#define MAXBITVAL(nbits) ((1 << (nbits)) - 1)
-#define NBITMASK(nbits) MAXBITVAL(nbits)
-#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8)
-
-/* basic mux operation - can be optimized on several architectures */
-#define MUX(pred, true, false) ((pred) ? (true) : (false))
-
-/* modulo inc/dec - assumes x E [0, bound - 1] */
-#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1)
-#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
-
-/* modulo inc/dec, bound = 2^k */
-#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
-#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
-
-/* modulo add/sub - assumes x, y E [0, bound - 1] */
-#define MODADD(x, y, bound) \
- MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y))
-#define MODSUB(x, y, bound) \
- MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y))
-
-/* module add/sub, bound = 2^k */
-#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
-#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
-
-/* crc defines */
-#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */
-#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */
-#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */
-#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */
-
-/* brcmu_format_flags() bit description structure */
-struct brcmu_bit_desc {
- u32 bit;
- const char *name;
-};
-
-/* tag_ID/length/value_buffer tuple */
-struct brcmu_tlv {
- u8 id;
- u8 len;
- u8 data[1];
-};
-
-#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */
-
/* externs */
-/* crc */
-extern u8 brcmu_crc8(u8 *p, uint nbytes, u8 crc);
-
/* format/print */
#if defined(BCMDBG)
-extern int brcmu_format_flags(const struct brcmu_bit_desc *bd, u32 flags,
- char *buf, int len);
extern int brcmu_format_hex(char *str, const void *bytes, int len);
#endif
-extern char *brcmu_chipname(uint chipid, char *buf, uint len);
-
-extern struct brcmu_tlv *brcmu_parse_tlvs(void *buf, int buflen,
- uint key);
-
-/* power conversion */
-extern u16 brcmu_qdbm_to_mw(u8 qdbm);
-extern u8 brcmu_mw_to_qdbm(u16 mw);
-
-extern void brcmu_binit(struct brcmu_strbuf *b, char *buf, uint size);
-extern int brcmu_bprintf(struct brcmu_strbuf *b, const char *fmt, ...);
-
-extern uint brcmu_mkiovar(char *name, char *data, uint datalen,
- char *buf, uint len);
-extern uint brcmu_bitcount(u8 *bitmap, uint bytelength);
-
#endif /* _BRCMU_UTILS_H_ */
diff --git a/drivers/staging/brcm80211/include/brcmu_wifi.h b/drivers/staging/brcm80211/include/brcmu_wifi.h
index fde592bd9177..f10d30274c23 100644
--- a/drivers/staging/brcm80211/include/brcmu_wifi.h
+++ b/drivers/staging/brcm80211/include/brcmu_wifi.h
@@ -20,8 +20,10 @@
#include <linux/if_ether.h> /* for ETH_ALEN */
#include <linux/ieee80211.h> /* for WLAN_PMKID_LEN */
-/* A chanspec holds the channel number, band, bandwidth and control sideband */
-typedef u16 chanspec_t;
+/*
+ * A chanspec (u16) holds the channel number, band, bandwidth and control
+ * sideband
+ */
/* channel defines */
#define CH_UPPER_SB 0x01
@@ -29,13 +31,20 @@ typedef u16 chanspec_t;
#define CH_EWA_VALID 0x04
#define CH_20MHZ_APART 4
#define CH_10MHZ_APART 2
-#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
+#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */
#define BRCM_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL /* legacy define */
-#define MAXCHANNEL 224 /* max # supported channels. The max channel no is 216,
- * this is that + 1 rounded up to a multiple of NBBY (8).
- * DO NOT MAKE it > 255: channels are u8's all over
- */
+
+/* bandstate array indices */
+#define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */
+#define BAND_5G_INDEX 1 /* wlc->bandstate[x] index */
+
+/*
+ * max # supported channels. The max channel no is 216, this is that + 1
+ * rounded up to a multiple of NBBY (8). DO NOT MAKE it > 255: channels are
+ * u8's all over
+*/
+#define MAXCHANNEL 224
#define WL_CHANSPEC_CHAN_MASK 0x00ff
#define WL_CHANSPEC_CHAN_SHIFT 0
@@ -63,58 +72,78 @@ typedef u16 chanspec_t;
#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */
#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */
-/* channel defines */
-#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0)
-#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
- ((channel) + CH_10MHZ_APART) : 0)
-#define CHSPEC_BANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : \
- BAND_2G_INDEX)
-#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
- WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
- WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \
- ((channel) + CH_20MHZ_APART) : 0)
-#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
- ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
- ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
- WL_CHANSPEC_BAND_5G))
#define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK))
#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
-#ifdef WL11N_20MHZONLY
+#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK)
+#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK)
-#define CHSPEC_CTL_SB(chspec) WL_CHANSPEC_CTL_SB_NONE
-#define CHSPEC_BW(chspec) WL_CHANSPEC_BW_20
-#define CHSPEC_IS10(chspec) 0
-#define CHSPEC_IS20(chspec) 1
-#ifndef CHSPEC_IS40
-#define CHSPEC_IS40(chspec) 0
-#endif
+#define CHSPEC_IS10(chspec) \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
-#else /* !WL11N_20MHZONLY */
+#define CHSPEC_IS20(chspec) \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
-#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK)
-#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK)
-#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
-#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
#ifndef CHSPEC_IS40
-#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
+#define CHSPEC_IS40(chspec) \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
#endif
-#endif /* !WL11N_20MHZONLY */
+#define CHSPEC_IS5G(chspec) \
+ (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
+
+#define CHSPEC_IS2G(chspec) \
+ (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
+
+#define CHSPEC_SB_NONE(chspec) \
+ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE)
+
+#define CHSPEC_SB_UPPER(chspec) \
+ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER)
+
+#define CHSPEC_SB_LOWER(chspec) \
+ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER)
+
+#define CHSPEC_CTL_CHAN(chspec) \
+ ((CHSPEC_SB_LOWER(chspec)) ? \
+ (lower_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \
+ (upper_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK))))
-#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
-#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
-#define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE)
-#define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER)
-#define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER)
-#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \
- (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \
- (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))))
#define CHSPEC2BAND(chspec) (CHSPEC_IS5G(chspec) ? BRCM_BAND_5G : BRCM_BAND_2G)
#define CHANSPEC_STR_LEN 8
+static inline int lower_20_sb(int channel)
+{
+ return channel > CH_10MHZ_APART ? (channel - CH_10MHZ_APART) : 0;
+}
+
+static inline int upper_20_sb(int channel)
+{
+ return (channel < (MAXCHANNEL - CH_10MHZ_APART)) ?
+ channel + CH_10MHZ_APART : 0;
+}
+
+static inline int chspec_bandunit(u16 chspec)
+{
+ return CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX;
+}
+
+static inline u16 ch20mhz_chspec(int channel)
+{
+ u16 rc = channel <= CH_MAX_2G_CHANNEL ?
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G;
+
+ return (u16)((u16)channel | WL_CHANSPEC_BW_20 |
+ WL_CHANSPEC_CTL_SB_NONE | rc);
+}
+
+static inline int next_20mhz_chan(int channel)
+{
+ return channel < (MAXCHANNEL - CH_20MHZ_APART) ?
+ channel + CH_20MHZ_APART : 0;
+}
+
/* defined rate in 500kbps */
#define BRCM_MAXRATE 108 /* in 500kbps units */
#define BRCM_RATE_1M 2 /* in 500kbps units */
@@ -134,43 +163,10 @@ typedef u16 chanspec_t;
#define MCSSET_LEN 16
-#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0)
-
-/*
- * 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.
- */
-extern bool brcmu_chspec_malformed(chanspec_t chanspec);
-
-/*
- * This function returns the channel number that control traffic is being sent on, for legacy
- * channels this is just the channel number, for 40MHZ channels it is the upper or lowre 20MHZ
- * sideband depending on the chanspec selected
- */
-extern u8 brcmu_chspec_ctlchan(chanspec_t chspec);
-
-/*
- * Return the channel number for a given frequency and base frequency.
- * The returned channel number is relative to the given base frequency.
- * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
- * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
- *
- * Frequency is specified in MHz.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
- * 2.4 GHz and 5 GHz bands.
- *
- * The returned channel will be in the range [1, 14] in the 2.4 GHz band
- * and [0, 200] otherwise.
- * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
- * frequency is not a 2.4 GHz channel, or if the frequency is not and even
- * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- */
-extern int brcmu_mhz2channel(uint freq, uint start_factor);
+static inline bool ac_bitmap_tst(u8 bitmap, int prec)
+{
+ return (bitmap & (1 << (prec))) != 0;
+}
/* Enumerate crypto algorithms */
#define CRYPTO_ALGO_OFF 0
@@ -183,11 +179,13 @@ extern int brcmu_mhz2channel(uint freq, uint start_factor);
#define CRYPTO_ALGO_NALG 7
/* wireless security bitvec */
+
#define WEP_ENABLED 0x0001
#define TKIP_ENABLED 0x0002
#define AES_ENABLED 0x0004
#define WSEC_SWFLAG 0x0008
-#define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */
+/* to go into transition mode without setting wep */
+#define SES_OW_ENABLED 0x0040
/* WPA authentication mode bitvec */
#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */
@@ -196,7 +194,7 @@ extern int brcmu_mhz2channel(uint freq, uint start_factor);
#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */
#define WPA_AUTH_RESERVED1 0x0008
#define WPA_AUTH_RESERVED2 0x0010
- /* #define WPA_AUTH_8021X 0x0020 *//* 802.1x, reserved */
+
#define WPA2_AUTH_RESERVED1 0x0020
#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */
#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */
@@ -218,26 +216,24 @@ extern int brcmu_mhz2channel(uint freq, uint start_factor);
#define HT_CAP_RX_STBC_NO 0x0
#define HT_CAP_RX_STBC_ONE_STREAM 0x1
-typedef struct _pmkid {
+struct pmkid {
u8 BSSID[ETH_ALEN];
u8 PMKID[WLAN_PMKID_LEN];
-} pmkid_t;
+};
-typedef struct _pmkid_list {
- u32 npmkid;
- pmkid_t pmkid[1];
-} pmkid_list_t;
+struct pmkid_list {
+ __le32 npmkid;
+ struct pmkid pmkid[1];
+};
-typedef struct _pmkid_cand {
+struct pmkid_cand {
u8 BSSID[ETH_ALEN];
u8 preauth;
-} pmkid_cand_t;
+};
-typedef struct _pmkid_cand_list {
+struct pmkid_cand_list {
u32 npmkid_cand;
- pmkid_cand_t pmkid_cand[1];
-} pmkid_cand_list_t;
-
-typedef u8 ac_bitmap_t;
+ struct pmkid_cand pmkid_cand[1];
+};
#endif /* _BRCMU_WIFI_H_ */
diff --git a/drivers/staging/brcm80211/include/chipcommon.h b/drivers/staging/brcm80211/include/chipcommon.h
index 296582aced69..fefabc39e646 100644
--- a/drivers/staging/brcm80211/include/chipcommon.h
+++ b/drivers/staging/brcm80211/include/chipcommon.h
@@ -19,7 +19,7 @@
#include "defs.h" /* for PAD macro */
-typedef volatile struct {
+struct chipcregs {
u32 chipid; /* 0x0 */
u32 capabilities;
u32 corecontrol; /* corerev >= 1 */
@@ -214,7 +214,7 @@ typedef volatile struct {
u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */
u32 PAD[100];
u16 sromotp[768];
-} chipcregs_t;
+};
/* chipid */
#define CID_ID_MASK 0x0000ffff /* Chip Id mask */
@@ -231,7 +231,8 @@ typedef volatile struct {
#define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */
#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */
#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */
-#define CC_CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */
+/* UARTs are driven by internal divided clock */
+#define CC_CAP_UINTCLK 0x00000008
#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */
#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */
#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */
@@ -248,10 +249,12 @@ typedef volatile struct {
#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */
#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */
#define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */
-#define CC_CAP_NFLASH 0x80000000 /* Nand flash present, rev >= 35 */
+/* Nand flash present, rev >= 35 */
+#define CC_CAP_NFLASH 0x80000000
#define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */
-#define CC_CAP2_GSIO 0x00000002 /* GSIO (spi/i2c) present, rev >= 37 */
+/* GSIO (spi/i2c) present, rev >= 37 */
+#define CC_CAP2_GSIO 0x00000002
/* pmucapabilities */
#define PCAP_REV_MASK 0x000000ff
diff --git a/drivers/staging/brcm80211/include/defs.h b/drivers/staging/brcm80211/include/defs.h
index 8b3e17dec150..1e5f310af1e7 100644
--- a/drivers/staging/brcm80211/include/defs.h
+++ b/drivers/staging/brcm80211/include/defs.h
@@ -27,14 +27,8 @@
#define USB_BUS 5
#define SPI_BUS 6
-#ifndef OFF
#define OFF 0
-#endif
-
-#ifndef ON
#define ON 1 /* ON = 1 */
-#endif
-
#define AUTO (-1) /* Auto = -1 */
/*
@@ -54,27 +48,23 @@
#define WL_NUMRATES 16 /* max # of rates in a rateset */
-typedef struct wl_rateset {
- u32 count; /* # rates in this set */
- u8 rates[WL_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */
-} wl_rateset_t;
-
#define BRCM_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */
-#define BRCM_SET_CHANNEL 30
-#define BRCM_SET_SRL 32
-#define BRCM_SET_LRL 34
+#define BRCM_SET_CHANNEL 30
+#define BRCM_SET_SRL 32
+#define BRCM_SET_LRL 34
+#define BRCM_SET_BCNPRD 76
-#define BRCM_SET_RATESET 72
-#define BRCM_SET_BCNPRD 76
-#define BRCM_GET_CURR_RATESET 114 /* current rateset */
-#define BRCM_GET_PHYLIST 180
+#define BRCM_GET_CURR_RATESET 114 /* current rateset */
+#define BRCM_GET_PHYLIST 180
/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
+
#define WL_RADIO_SW_DISABLE (1<<0)
#define WL_RADIO_HW_DISABLE (1<<1)
#define WL_RADIO_MPC_DISABLE (1<<2)
-#define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */
+/* some countries don't support any channel */
+#define WL_RADIO_COUNTRY_DISABLE (1<<3)
/* Override bit for SET_TXPWR. if set, ignore other level limits */
#define WL_TXPWR_OVERRIDE (1U<<31)
@@ -100,7 +90,9 @@ typedef struct wl_rateset {
/*
* Sonics Configuration Space Registers.
*/
-#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */
+
+/* core sbconfig regs are top 256bytes of regs */
+#define SBCONFIGOFF 0xf00
/* cpp contortions to concatenate w/arg prescan */
#ifndef PAD
diff --git a/drivers/staging/brcm80211/include/soc.h b/drivers/staging/brcm80211/include/soc.h
index 6e5a705c4937..4fcb956ad9e0 100644
--- a/drivers/staging/brcm80211/include/soc.h
+++ b/drivers/staging/brcm80211/include/soc.h
@@ -17,11 +17,7 @@
#ifndef _BRCM_SOC_H
#define _BRCM_SOC_H
-#ifdef SI_ENUM_BASE_VARIABLE
-#define SI_ENUM_BASE (sii->pub.si_enum_base)
-#else
#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */
-#endif /* SI_ENUM_BASE_VARIABLE */
/* core codes */
#define NODEV_CORE_ID 0x700 /* Invalid coreid */
@@ -81,9 +77,8 @@
#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */
#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */
#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */
-#define DEF_AI_COMP 0xfff /* Default component, in ai chips it maps all
- * unused address ranges
- */
+/* Default component, in ai chips it maps all unused address ranges */
+#define DEF_AI_COMP 0xfff
/* Common core control flags */
#define SICF_BIST_EN 0x8000
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 72258e8c64ca..be3c392d83b3 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -353,7 +353,6 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
if(err < 0)
dev_err(nvec->dev, "couldn't request gpio\n");
- tegra_gpio_enable(nvec->gpio);
gpio_direction_output(nvec->gpio, 1);
gpio_set_value(nvec->gpio, 1);
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 438af89db55e..efb9c27efbf3 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o
+CFLAGS_tegra_hsuart.o = -Werror
obj-$(CONFIG_SERIAL_TEGRA) += tegra_hsuart.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
diff --git a/drivers/tty/serial/tegra_hsuart.c b/drivers/tty/serial/tegra_hsuart.c
index ea20de6ebb41..b2fa281492a7 100644
--- a/drivers/tty/serial/tegra_hsuart.c
+++ b/drivers/tty/serial/tegra_hsuart.c
@@ -3,7 +3,7 @@
*
* High-speed serial driver for NVIDIA Tegra SoCs
*
- * Copyright (C) 2009-2011 NVIDIA Corporation
+ * Copyright (C) 2009-2012 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -59,6 +59,8 @@
#define UART_MCR_CTS_EN 0x20
#define UART_LSR_ANY (UART_LSR_OE | UART_LSR_BI | \
UART_LSR_PE | UART_LSR_FE)
+#define TEGRA_UART_IRDA_CSR 0x8
+#define TEGRA_UART_SIR_ENABLED 0x80
#define TX_FORCE_PIO 0
#define RX_FORCE_PIO 0
@@ -92,6 +94,12 @@ const int dma_req_sel[] = {
struct tegra_uart_port {
struct uart_port uport;
char port_name[32];
+ bool is_irda;
+ int (*irda_init)(void);
+ void (*irda_start)(void);
+ int (*irda_mode_switch)(int);
+ void (*irda_shutdown)(void);
+ void (*irda_remove)(void);
/* Module info */
unsigned long size;
@@ -130,6 +138,8 @@ static void tegra_set_baudrate(struct tegra_uart_port *t, unsigned int baud);
static void do_handle_rx_pio(struct tegra_uart_port *t);
static void do_handle_rx_dma(struct tegra_uart_port *t);
static void set_rts(struct tegra_uart_port *t, bool active);
+static void tegra_start_rx(struct uart_port *u);
+static void tegra_stop_rx(struct uart_port *u);
static inline u8 uart_readb(struct tegra_uart_port *t, unsigned long reg)
{
@@ -224,6 +234,8 @@ static void tegra_start_next_tx(struct tegra_uart_port *t)
{
unsigned long tail;
unsigned long count;
+ unsigned long lsr;
+ struct uart_port *u = &t->uport;
struct circ_buf *xmit;
@@ -235,8 +247,22 @@ static void tegra_start_next_tx(struct tegra_uart_port *t)
dev_vdbg(t->uport.dev, "+%s %lu %d\n", __func__, count,
t->tx_in_progress);
- if (count == 0)
+ if (count == 0) {
+ if (t->is_irda) {
+ do {
+ lsr = uart_readb(t, UART_LSR);
+ if (lsr & UART_LSR_TEMT)
+ break;
+ } while (1);
+ tegra_start_rx(u);
+ }
goto out;
+ }
+
+ if (t->is_irda) {
+ if (t->rx_in_progress)
+ tegra_stop_rx(u);
+ }
if (!t->use_tx_dma || count < TEGRA_UART_MIN_DMA)
tegra_start_pio_tx(t, count);
@@ -599,6 +625,42 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
}
}
+static void tegra_start_rx(struct uart_port *u)
+{
+ struct tegra_uart_port *t;
+ unsigned char ier;
+
+ t = container_of(u, struct tegra_uart_port, uport);
+
+ if (t->rts_active)
+ set_rts(t, true);
+
+ if (!t->rx_in_progress) {
+ wait_sym_time(t, 1); /* wait a character interval */
+
+ /* Clear the received Bytes from FIFO */
+ tegra_fifo_reset(t, UART_FCR_CLEAR_RCVR);
+ uart_readb(t, UART_LSR);
+ ier = 0;
+ ier |= (UART_IER_RLSI | UART_IER_RTOIE);
+ if (t->use_rx_dma)
+ ier |= UART_IER_EORD;
+ else
+ ier |= UART_IER_RDI;
+ t->ier_shadow |= ier;
+ uart_writeb(t, t->ier_shadow, UART_IER);
+
+ t->rx_in_progress = 1;
+
+ if (t->use_rx_dma && t->rx_dma)
+ tegra_dma_enqueue_req(t->rx_dma, &t->rx_dma_req);
+
+ tty_flip_buffer_push(u->state->port.tty);
+ }
+
+ return;
+}
+
static void tegra_stop_rx(struct uart_port *u)
{
struct tegra_uart_port *t;
@@ -705,6 +767,7 @@ static void tegra_uart_free_rx_dma(struct tegra_uart_port *t)
static int tegra_uart_hw_init(struct tegra_uart_port *t)
{
unsigned char ier;
+ unsigned char sir;
dev_vdbg(t->uport.dev, "+tegra_uart_hw_init\n");
@@ -800,6 +863,16 @@ static int tegra_uart_hw_init(struct tegra_uart_port *t)
t->ier_shadow = ier;
uart_writeb(t, ier, UART_IER);
+ /*
+ * Tegra UART controller also support SIR PHY
+ * Enabled IRDA will transmit each zero bit as a short IR pulse.
+ */
+ if (t->is_irda) {
+ dev_vdbg(t->uport.dev, "SIR enabled\n");
+ sir = TEGRA_UART_SIR_ENABLED;
+ uart_writeb(t, sir, TEGRA_UART_IRDA_CSR);
+ }
+
t->uart_state = TEGRA_UART_OPENED;
dev_vdbg(t->uport.dev, "-tegra_uart_hw_init\n");
return 0;
@@ -894,6 +967,9 @@ static int tegra_startup(struct uart_port *u)
if (ret)
goto fail;
+ if (t->is_irda && t->irda_start)
+ t->irda_start();
+
pdata = u->dev->platform_data;
if (pdata && pdata->is_loopback)
t->mcr_shadow |= UART_MCR_LOOP;
@@ -920,6 +996,9 @@ static void tegra_shutdown(struct uart_port *u)
t = container_of(u, struct tegra_uart_port, uport);
dev_vdbg(u->dev, "+tegra_shutdown\n");
+ if (t->is_irda && t->irda_shutdown)
+ t->irda_shutdown();
+
tegra_uart_hw_deinit(t);
t->rx_in_progress = 0;
@@ -1418,6 +1497,7 @@ static int __init tegra_uart_probe(struct platform_device *pdev)
{
struct tegra_uart_port *t;
struct uart_port *u;
+ struct tegra_uart_platform_data *pdata;
struct resource *resource;
int ret;
char name[64];
@@ -1439,6 +1519,20 @@ static int __init tegra_uart_probe(struct platform_device *pdev)
u->type = PORT_TEGRA;
u->fifosize = 32;
+ pdata = u->dev->platform_data;
+ if (pdata && pdata->is_irda) {
+ dev_info(&pdev->dev, "Initialized UART %d as SIR PHY\n",
+ u->line);
+ t->is_irda = pdata->is_irda;
+ t->irda_init = pdata->irda_init;
+ t->irda_start = pdata->irda_start;
+ t->irda_mode_switch = pdata->irda_mode_switch;
+ t->irda_shutdown = pdata->irda_shutdown;
+ t->irda_remove = pdata->irda_remove;
+ if (t->irda_init)
+ t->irda_init();
+ }
+
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (unlikely(!resource)) {
ret = -ENXIO;
@@ -1509,6 +1603,9 @@ static int __devexit tegra_uart_remove(struct platform_device *pdev)
if (pdev->id < 0 || pdev->id > tegra_uart_driver.nr)
pr_err("Invalid Uart instance (%d)\n", pdev->id);
+ if (t->is_irda && t->irda_remove)
+ t->irda_remove();
+
u = &t->uport;
uart_remove_one_port(&tegra_uart_driver, u);
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 8fb105e03658..cd16e13f61c9 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -416,7 +416,7 @@ static void acm_read_bulk_callback(struct urb *urb)
}
usb_mark_last_busy(acm->dev);
- if (urb->status) {
+ if (urb->status && !urb->actual_length) {
dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n",
__func__, urb->status);
return;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 8e051d72d6aa..e7c6ca49ab8e 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -143,7 +143,7 @@ config USB_FSL_USB2
tristate "Freescale Highspeed USB DR Peripheral Controller"
depends on FSL_SOC || ARCH_MXC || ARCH_TEGRA
select USB_GADGET_DUALSPEED
- select USB_FSL_MPH_DR_OF if OF
+ select USB_FSL_MPH_DR_OF if OF && FSL_SOC
help
Some of Freescale PowerPC processors have a High Speed
Dual-Role(DR) USB controller, which supports device mode.
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index c8c7c687010d..13f24548cee1 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
fsl_usb2_udc-y := fsl_udc_core.o
fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o
+CFLAGS_tegra_udc.o = -Werror
obj-$(CONFIG_USB_TEGRA) += tegra_udc.o
obj-$(CONFIG_USB_M66592) += m66592-udc.o
obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index dbc22802b43c..9f79c267890e 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -45,6 +45,7 @@
#include "epautoconf.c"
#include "composite.c"
+#include "f_audio_source.c"
#include "f_mass_storage.c"
#include "u_serial.c"
#include "f_acm.c"
@@ -649,6 +650,67 @@ static struct android_usb_function accessory_function = {
.ctrlrequest = accessory_function_ctrlrequest,
};
+static int audio_source_function_init(struct android_usb_function *f,
+ struct usb_composite_dev *cdev)
+{
+ struct audio_source_config *config;
+
+ config = kzalloc(sizeof(struct audio_source_config), GFP_KERNEL);
+ if (!config)
+ return -ENOMEM;
+ config->card = -1;
+ config->device = -1;
+ f->config = config;
+ return 0;
+}
+
+static void audio_source_function_cleanup(struct android_usb_function *f)
+{
+ kfree(f->config);
+}
+
+static int audio_source_function_bind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ struct audio_source_config *config = f->config;
+
+ return audio_source_bind_config(c, config);
+}
+
+static void audio_source_function_unbind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ struct audio_source_config *config = f->config;
+
+ config->card = -1;
+ config->device = -1;
+}
+
+static ssize_t audio_source_pcm_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct audio_source_config *config = f->config;
+
+ /* print PCM card and device numbers */
+ return sprintf(buf, "%d %d\n", config->card, config->device);
+}
+
+static DEVICE_ATTR(pcm, S_IRUGO | S_IWUSR, audio_source_pcm_show, NULL);
+
+static struct device_attribute *audio_source_function_attributes[] = {
+ &dev_attr_pcm,
+ NULL
+};
+
+static struct android_usb_function audio_source_function = {
+ .name = "audio_source",
+ .init = audio_source_function_init,
+ .cleanup = audio_source_function_cleanup,
+ .bind_config = audio_source_function_bind_config,
+ .unbind_config = audio_source_function_unbind_config,
+ .attributes = audio_source_function_attributes,
+};
static struct android_usb_function *supported_functions[] = {
&adb_function,
@@ -658,6 +720,7 @@ static struct android_usb_function *supported_functions[] = {
&rndis_function,
&mass_storage_function,
&accessory_function,
+ &audio_source_function,
NULL
};
@@ -1113,6 +1176,11 @@ static void android_disconnect(struct usb_gadget *gadget)
unsigned long flags;
composite_disconnect(gadget);
+ /* accessory HID support can be active while the
+ accessory function is not actually enabled,
+ so we need to inform it when we are disconnected.
+ */
+ acc_disconnect();
spin_lock_irqsave(&cdev->lock, flags);
dev->connected = 0;
diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c
index ae65faaf3d77..d248ef98b532 100644
--- a/drivers/usb/gadget/f_accessory.c
+++ b/drivers/usb/gadget/f_accessory.c
@@ -33,6 +33,8 @@
#include <linux/device.h>
#include <linux/miscdevice.h>
+#include <linux/hid.h>
+#include <linux/hiddev.h>
#include <linux/usb.h>
#include <linux/usb/ch9.h>
#include <linux/usb/f_accessory.h>
@@ -40,7 +42,7 @@
#define BULK_BUFFER_SIZE 16384
#define ACC_STRING_SIZE 256
-#define PROTOCOL_VERSION 1
+#define PROTOCOL_VERSION 2
/* String IDs */
#define INTERFACE_STRING_INDEX 0
@@ -49,6 +51,20 @@
#define TX_REQ_MAX 4
#define RX_REQ_MAX 2
+struct acc_hid_dev {
+ struct list_head list;
+ struct hid_device *hid;
+ struct acc_dev *dev;
+ /* accessory defined ID */
+ int id;
+ /* HID report descriptor */
+ u8 *report_desc;
+ /* length of HID report descriptor */
+ int report_desc_len;
+ /* number of bytes of report_desc we have received so far */
+ int report_desc_offset;
+};
+
struct acc_dev {
struct usb_function function;
struct usb_composite_dev *cdev;
@@ -78,6 +94,8 @@ struct acc_dev {
/* set to 1 if we have a pending start request */
int start_requested;
+ int audio_mode;
+
/* synchronize access to our device file */
atomic_t open_excl;
@@ -87,7 +105,21 @@ struct acc_dev {
wait_queue_head_t write_wq;
struct usb_request *rx_req[RX_REQ_MAX];
int rx_done;
- struct delayed_work work;
+
+ /* delayed work for handling ACCESSORY_START */
+ struct delayed_work start_work;
+
+ /* worker for registering and unregistering hid devices */
+ struct work_struct hid_work;
+
+ /* list of active HID devices */
+ struct list_head hid_list;
+
+ /* list of new HID devices to register */
+ struct list_head new_hid_list;
+
+ /* list of dead HID devices to unregister */
+ struct list_head dead_hid_list;
};
static struct usb_interface_descriptor acc_interface_desc = {
@@ -296,7 +328,161 @@ static void acc_complete_set_string(struct usb_ep *ep, struct usb_request *req)
}
}
-static int __init create_bulk_endpoints(struct acc_dev *dev,
+static void acc_complete_set_hid_report_desc(struct usb_ep *ep,
+ struct usb_request *req)
+{
+ struct acc_hid_dev *hid = req->context;
+ struct acc_dev *dev = hid->dev;
+ int length = req->actual;
+
+ if (req->status != 0) {
+ pr_err("acc_complete_set_hid_report_desc, err %d\n",
+ req->status);
+ return;
+ }
+
+ memcpy(hid->report_desc + hid->report_desc_offset, req->buf, length);
+ hid->report_desc_offset += length;
+ if (hid->report_desc_offset == hid->report_desc_len) {
+ /* After we have received the entire report descriptor
+ * we schedule work to initialize the HID device
+ */
+ schedule_work(&dev->hid_work);
+ }
+}
+
+static void acc_complete_send_hid_event(struct usb_ep *ep,
+ struct usb_request *req)
+{
+ struct acc_hid_dev *hid = req->context;
+ int length = req->actual;
+
+ if (req->status != 0) {
+ pr_err("acc_complete_send_hid_event, err %d\n", req->status);
+ return;
+ }
+
+ hid_report_raw_event(hid->hid, HID_INPUT_REPORT, req->buf, length, 1);
+}
+
+static int acc_hid_parse(struct hid_device *hid)
+{
+ struct acc_hid_dev *hdev = hid->driver_data;
+
+ hid_parse_report(hid, hdev->report_desc, hdev->report_desc_len);
+ return 0;
+}
+
+static int acc_hid_start(struct hid_device *hid)
+{
+ return 0;
+}
+
+static void acc_hid_stop(struct hid_device *hid)
+{
+}
+
+static int acc_hid_open(struct hid_device *hid)
+{
+ return 0;
+}
+
+static void acc_hid_close(struct hid_device *hid)
+{
+}
+
+static struct hid_ll_driver acc_hid_ll_driver = {
+ .parse = acc_hid_parse,
+ .start = acc_hid_start,
+ .stop = acc_hid_stop,
+ .open = acc_hid_open,
+ .close = acc_hid_close,
+};
+
+static struct acc_hid_dev *acc_hid_new(struct acc_dev *dev,
+ int id, int desc_len)
+{
+ struct acc_hid_dev *hdev;
+
+ hdev = kzalloc(sizeof(*hdev), GFP_ATOMIC);
+ if (!hdev)
+ return NULL;
+ hdev->report_desc = kzalloc(desc_len, GFP_ATOMIC);
+ if (!hdev->report_desc) {
+ kfree(hdev);
+ return NULL;
+ }
+ hdev->dev = dev;
+ hdev->id = id;
+ hdev->report_desc_len = desc_len;
+
+ return hdev;
+}
+
+static struct acc_hid_dev *acc_hid_get(struct list_head *list, int id)
+{
+ struct acc_hid_dev *hid;
+
+ list_for_each_entry(hid, list, list) {
+ if (hid->id == id)
+ return hid;
+ }
+ return NULL;
+}
+
+static int acc_register_hid(struct acc_dev *dev, int id, int desc_length)
+{
+ struct acc_hid_dev *hid;
+ unsigned long flags;
+
+ /* report descriptor length must be > 0 */
+ if (desc_length <= 0)
+ return -EINVAL;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ /* replace HID if one already exists with this ID */
+ hid = acc_hid_get(&dev->hid_list, id);
+ if (!hid)
+ hid = acc_hid_get(&dev->new_hid_list, id);
+ if (hid)
+ list_move(&hid->list, &dev->dead_hid_list);
+
+ hid = acc_hid_new(dev, id, desc_length);
+ if (!hid) {
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return -ENOMEM;
+ }
+
+ list_add(&hid->list, &dev->new_hid_list);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ /* schedule work to register the HID device */
+ schedule_work(&dev->hid_work);
+ return 0;
+}
+
+static int acc_unregister_hid(struct acc_dev *dev, int id)
+{
+ struct acc_hid_dev *hid;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ hid = acc_hid_get(&dev->hid_list, id);
+ if (!hid)
+ hid = acc_hid_get(&dev->new_hid_list, id);
+ if (!hid) {
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return -EINVAL;
+ }
+
+ list_move(&hid->list, &dev->dead_hid_list);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ schedule_work(&dev->hid_work);
+ return 0;
+}
+
+static int create_bulk_endpoints(struct acc_dev *dev,
struct usb_endpoint_descriptor *in_desc,
struct usb_endpoint_descriptor *out_desc)
{
@@ -353,7 +539,7 @@ static int __init create_bulk_endpoints(struct acc_dev *dev,
return 0;
fail:
- printk(KERN_ERR "acc_bind() could not allocate requests\n");
+ pr_err("acc_bind() could not allocate requests\n");
while ((req = req_get(dev, &dev->tx_idle)))
acc_request_free(req, dev->ep_in);
for (i = 0; i < RX_REQ_MAX; i++)
@@ -510,6 +696,8 @@ static long acc_ioctl(struct file *fp, unsigned code, unsigned long value)
break;
case ACCESSORY_IS_START_REQUESTED:
return dev->start_requested;
+ case ACCESSORY_GET_AUDIO_MODE:
+ return dev->audio_mode;
}
if (!src)
return -EINVAL;
@@ -540,7 +728,7 @@ static int acc_release(struct inode *ip, struct file *fp)
return 0;
}
-/* file operations for /dev/acc_usb */
+/* file operations for /dev/usb_accessory */
static const struct file_operations acc_fops = {
.owner = THIS_MODULE,
.read = acc_read,
@@ -550,23 +738,47 @@ static const struct file_operations acc_fops = {
.release = acc_release,
};
+static int acc_hid_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret)
+ return ret;
+ return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+}
+
static struct miscdevice acc_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "usb_accessory",
.fops = &acc_fops,
};
+static const struct hid_device_id acc_hid_table[] = {
+ { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) },
+ { }
+};
+
+static struct hid_driver acc_hid_driver = {
+ .name = "USB accessory",
+ .id_table = acc_hid_table,
+ .probe = acc_hid_probe,
+};
static int acc_ctrlrequest(struct usb_composite_dev *cdev,
const struct usb_ctrlrequest *ctrl)
{
struct acc_dev *dev = _acc_dev;
int value = -EOPNOTSUPP;
+ struct acc_hid_dev *hid;
+ int offset;
u8 b_requestType = ctrl->bRequestType;
u8 b_request = ctrl->bRequest;
u16 w_index = le16_to_cpu(ctrl->wIndex);
u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength);
+ unsigned long flags;
/*
printk(KERN_INFO "acc_ctrlrequest "
@@ -579,20 +791,56 @@ static int acc_ctrlrequest(struct usb_composite_dev *cdev,
if (b_request == ACCESSORY_START) {
dev->start_requested = 1;
schedule_delayed_work(
- &dev->work, msecs_to_jiffies(10));
+ &dev->start_work, msecs_to_jiffies(10));
value = 0;
} else if (b_request == ACCESSORY_SEND_STRING) {
dev->string_index = w_index;
cdev->gadget->ep0->driver_data = dev;
cdev->req->complete = acc_complete_set_string;
value = w_length;
+ } else if (b_request == ACCESSORY_SET_AUDIO_MODE &&
+ w_index == 0 && w_length == 0) {
+ dev->audio_mode = w_value;
+ value = 0;
+ } else if (b_request == ACCESSORY_REGISTER_HID) {
+ value = acc_register_hid(dev, w_value, w_index);
+ } else if (b_request == ACCESSORY_UNREGISTER_HID) {
+ value = acc_unregister_hid(dev, w_value);
+ } else if (b_request == ACCESSORY_SET_HID_REPORT_DESC) {
+ spin_lock_irqsave(&dev->lock, flags);
+ hid = acc_hid_get(&dev->new_hid_list, w_value);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ if (!hid) {
+ value = -EINVAL;
+ goto err;
+ }
+ offset = w_index;
+ if (offset != hid->report_desc_offset
+ || offset + w_length > hid->report_desc_len) {
+ value = -EINVAL;
+ goto err;
+ }
+ cdev->req->context = hid;
+ cdev->req->complete = acc_complete_set_hid_report_desc;
+ value = w_length;
+ } else if (b_request == ACCESSORY_SEND_HID_EVENT) {
+ spin_lock_irqsave(&dev->lock, flags);
+ hid = acc_hid_get(&dev->hid_list, w_value);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ if (!hid) {
+ value = -EINVAL;
+ goto err;
+ }
+ cdev->req->context = hid;
+ cdev->req->complete = acc_complete_send_hid_event;
+ value = w_length;
}
} else if (b_requestType == (USB_DIR_IN | USB_TYPE_VENDOR)) {
if (b_request == ACCESSORY_GET_PROTOCOL) {
*((u16 *)cdev->req->buf) = PROTOCOL_VERSION;
value = sizeof(u16);
- /* clear any strings left over from a previous session */
+ /* clear strings left over from a previous session */
memset(dev->manufacturer, 0, sizeof(dev->manufacturer));
memset(dev->model, 0, sizeof(dev->model));
memset(dev->description, 0, sizeof(dev->description));
@@ -600,6 +848,7 @@ static int acc_ctrlrequest(struct usb_composite_dev *cdev,
memset(dev->uri, 0, sizeof(dev->uri));
memset(dev->serial, 0, sizeof(dev->serial));
dev->start_requested = 0;
+ dev->audio_mode = 0;
}
}
@@ -612,6 +861,7 @@ static int acc_ctrlrequest(struct usb_composite_dev *cdev,
__func__);
}
+err:
if (value == -EOPNOTSUPP)
VDBG(cdev,
"unknown class-specific control req "
@@ -631,6 +881,10 @@ acc_function_bind(struct usb_configuration *c, struct usb_function *f)
DBG(cdev, "acc_function_bind dev: %p\n", dev);
+ ret = hid_register_driver(&acc_hid_driver);
+ if (ret)
+ return ret;
+
dev->start_requested = 0;
/* allocate interface ID(s) */
@@ -660,6 +914,36 @@ acc_function_bind(struct usb_configuration *c, struct usb_function *f)
}
static void
+kill_all_hid_devices(struct acc_dev *dev)
+{
+ struct acc_hid_dev *hid;
+ struct list_head *entry, *temp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ list_for_each_safe(entry, temp, &dev->hid_list) {
+ hid = list_entry(entry, struct acc_hid_dev, list);
+ list_del(&hid->list);
+ list_add(&hid->list, &dev->dead_hid_list);
+ }
+ list_for_each_safe(entry, temp, &dev->new_hid_list) {
+ hid = list_entry(entry, struct acc_hid_dev, list);
+ list_del(&hid->list);
+ list_add(&hid->list, &dev->dead_hid_list);
+ }
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ schedule_work(&dev->hid_work);
+}
+
+static void
+acc_hid_unbind(struct acc_dev *dev)
+{
+ hid_unregister_driver(&acc_hid_driver);
+ kill_all_hid_devices(dev);
+}
+
+static void
acc_function_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct acc_dev *dev = func_to_dev(f);
@@ -670,14 +954,104 @@ acc_function_unbind(struct usb_configuration *c, struct usb_function *f)
acc_request_free(req, dev->ep_in);
for (i = 0; i < RX_REQ_MAX; i++)
acc_request_free(dev->rx_req[i], dev->ep_out);
+
+ acc_hid_unbind(dev);
}
-static void acc_work(struct work_struct *data)
+static void acc_start_work(struct work_struct *data)
{
char *envp[2] = { "ACCESSORY=START", NULL };
kobject_uevent_env(&acc_device.this_device->kobj, KOBJ_CHANGE, envp);
}
+static int acc_hid_init(struct acc_hid_dev *hdev)
+{
+ struct hid_device *hid;
+ int ret;
+
+ hid = hid_allocate_device();
+ if (IS_ERR(hid))
+ return PTR_ERR(hid);
+
+ hid->ll_driver = &acc_hid_ll_driver;
+ hid->dev.parent = acc_device.this_device;
+
+ hid->bus = BUS_USB;
+ hid->vendor = HID_ANY_ID;
+ hid->product = HID_ANY_ID;
+ hid->driver_data = hdev;
+ ret = hid_add_device(hid);
+ if (ret) {
+ pr_err("can't add hid device: %d\n", ret);
+ hid_destroy_device(hid);
+ return ret;
+ }
+
+ hdev->hid = hid;
+ return 0;
+}
+
+static void acc_hid_delete(struct acc_hid_dev *hid)
+{
+ kfree(hid->report_desc);
+ kfree(hid);
+}
+
+static void acc_hid_work(struct work_struct *data)
+{
+ struct acc_dev *dev = _acc_dev;
+ struct list_head *entry, *temp;
+ struct acc_hid_dev *hid;
+ struct list_head new_list, dead_list;
+ unsigned long flags;
+
+ INIT_LIST_HEAD(&new_list);
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ /* copy hids that are ready for initialization to new_list */
+ list_for_each_safe(entry, temp, &dev->new_hid_list) {
+ hid = list_entry(entry, struct acc_hid_dev, list);
+ if (hid->report_desc_offset == hid->report_desc_len)
+ list_move(&hid->list, &new_list);
+ }
+
+ if (list_empty(&dev->dead_hid_list)) {
+ INIT_LIST_HEAD(&dead_list);
+ } else {
+ /* move all of dev->dead_hid_list to dead_list */
+ dead_list.prev = dev->dead_hid_list.prev;
+ dead_list.next = dev->dead_hid_list.next;
+ dead_list.next->prev = &dead_list;
+ dead_list.prev->next = &dead_list;
+ INIT_LIST_HEAD(&dev->dead_hid_list);
+ }
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ /* register new HID devices */
+ list_for_each_safe(entry, temp, &new_list) {
+ hid = list_entry(entry, struct acc_hid_dev, list);
+ if (acc_hid_init(hid)) {
+ pr_err("can't add HID device %p\n", hid);
+ acc_hid_delete(hid);
+ } else {
+ spin_lock_irqsave(&dev->lock, flags);
+ list_move(&hid->list, &dev->hid_list);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ }
+ }
+
+ /* remove dead HID devices */
+ list_for_each_safe(entry, temp, &dead_list) {
+ hid = list_entry(entry, struct acc_hid_dev, list);
+ list_del(&hid->list);
+ if (hid->hid)
+ hid_destroy_device(hid->hid);
+ acc_hid_delete(hid);
+ }
+}
+
static int acc_function_set_alt(struct usb_function *f,
unsigned intf, unsigned alt)
{
@@ -763,7 +1137,11 @@ static int acc_setup(void)
init_waitqueue_head(&dev->write_wq);
atomic_set(&dev->open_excl, 0);
INIT_LIST_HEAD(&dev->tx_idle);
- INIT_DELAYED_WORK(&dev->work, acc_work);
+ INIT_LIST_HEAD(&dev->hid_list);
+ INIT_LIST_HEAD(&dev->new_hid_list);
+ INIT_LIST_HEAD(&dev->dead_hid_list);
+ INIT_DELAYED_WORK(&dev->start_work, acc_start_work);
+ INIT_WORK(&dev->hid_work, acc_hid_work);
/* _acc_dev must be set before calling usb_gadget_register_driver */
_acc_dev = dev;
@@ -776,10 +1154,16 @@ static int acc_setup(void)
err:
kfree(dev);
- printk(KERN_ERR "USB accessory gadget driver failed to initialize\n");
+ pr_err("USB accessory gadget driver failed to initialize\n");
return ret;
}
+static void acc_disconnect(void)
+{
+ /* unregister all HID devices if USB is disconnected */
+ kill_all_hid_devices(_acc_dev);
+}
+
static void acc_cleanup(void)
{
misc_deregister(&acc_device);
diff --git a/drivers/usb/gadget/f_audio_source.c b/drivers/usb/gadget/f_audio_source.c
new file mode 100644
index 000000000000..3ba7d7569b12
--- /dev/null
+++ b/drivers/usb/gadget/f_audio_source.c
@@ -0,0 +1,827 @@
+/*
+ * Gadget Function Driver for USB audio source device
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/usb/audio.h>
+#include <linux/wait.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+
+#define SAMPLE_RATE 44100
+/* Each frame is two 16 bit integers (one per channel) */
+#define BYTES_PER_FRAME 4
+#define FRAMES_PER_MSEC (SAMPLE_RATE / 1000)
+
+#define IN_EP_MAX_PACKET_SIZE 256
+
+/* Number of requests to allocate */
+#define IN_EP_REQ_COUNT 4
+
+#define AUDIO_AC_INTERFACE 0
+#define AUDIO_AS_INTERFACE 1
+#define AUDIO_NUM_INTERFACES 2
+
+/* B.3.1 Standard AC Interface Descriptor */
+static struct usb_interface_descriptor ac_interface_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
+};
+
+DECLARE_UAC_AC_HEADER_DESCRIPTOR(2);
+
+#define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(AUDIO_NUM_INTERFACES)
+/* 1 input terminal, 1 output terminal and 1 feature unit */
+#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH \
+ + UAC_DT_INPUT_TERMINAL_SIZE + UAC_DT_OUTPUT_TERMINAL_SIZE \
+ + UAC_DT_FEATURE_UNIT_SIZE(0))
+/* B.3.2 Class-Specific AC Interface Descriptor */
+static struct uac1_ac_header_descriptor_2 ac_header_desc = {
+ .bLength = UAC_DT_AC_HEADER_LENGTH,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_HEADER,
+ .bcdADC = __constant_cpu_to_le16(0x0100),
+ .wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH),
+ .bInCollection = AUDIO_NUM_INTERFACES,
+ .baInterfaceNr = {
+ [0] = AUDIO_AC_INTERFACE,
+ [1] = AUDIO_AS_INTERFACE,
+ }
+};
+
+#define INPUT_TERMINAL_ID 1
+static struct uac_input_terminal_descriptor input_terminal_desc = {
+ .bLength = UAC_DT_INPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_INPUT_TERMINAL,
+ .bTerminalID = INPUT_TERMINAL_ID,
+ .wTerminalType = UAC_INPUT_TERMINAL_MICROPHONE,
+ .bAssocTerminal = 0,
+ .wChannelConfig = 0x3,
+};
+
+DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0);
+
+#define FEATURE_UNIT_ID 2
+static struct uac_feature_unit_descriptor_0 feature_unit_desc = {
+ .bLength = UAC_DT_FEATURE_UNIT_SIZE(0),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FEATURE_UNIT,
+ .bUnitID = FEATURE_UNIT_ID,
+ .bSourceID = INPUT_TERMINAL_ID,
+ .bControlSize = 2,
+};
+
+#define OUTPUT_TERMINAL_ID 3
+static struct uac1_output_terminal_descriptor output_terminal_desc = {
+ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+ .bTerminalID = OUTPUT_TERMINAL_ID,
+ .wTerminalType = UAC_TERMINAL_STREAMING,
+ .bAssocTerminal = FEATURE_UNIT_ID,
+ .bSourceID = FEATURE_UNIT_ID,
+};
+
+/* B.4.1 Standard AS Interface Descriptor */
+static struct usb_interface_descriptor as_interface_alt_0_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+static struct usb_interface_descriptor as_interface_alt_1_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+/* B.4.2 Class-Specific AS Interface Descriptor */
+static struct uac1_as_header_descriptor as_header_desc = {
+ .bLength = UAC_DT_AS_HEADER_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_AS_GENERAL,
+ .bTerminalLink = INPUT_TERMINAL_ID,
+ .bDelay = 1,
+ .wFormatTag = UAC_FORMAT_TYPE_I_PCM,
+};
+
+DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(1);
+
+static struct uac_format_type_i_discrete_descriptor_1 as_type_i_desc = {
+ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FORMAT_TYPE,
+ .bFormatType = UAC_FORMAT_TYPE_I,
+ .bSubframeSize = 2,
+ .bBitResolution = 16,
+ .bSamFreqType = 1,
+};
+
+/* Standard ISO IN Endpoint Descriptor for highspeed */
+static struct usb_endpoint_descriptor hs_as_in_ep_desc = {
+ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_SYNC_SYNC
+ | USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = __constant_cpu_to_le16(IN_EP_MAX_PACKET_SIZE),
+ .bInterval = 4, /* poll 1 per millisecond */
+};
+
+/* Standard ISO IN Endpoint Descriptor for highspeed */
+static struct usb_endpoint_descriptor fs_as_in_ep_desc = {
+ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_SYNC_SYNC
+ | USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = __constant_cpu_to_le16(IN_EP_MAX_PACKET_SIZE),
+ .bInterval = 1, /* poll 1 per millisecond */
+};
+
+/* Class-specific AS ISO OUT Endpoint Descriptor */
+static struct uac_iso_endpoint_descriptor as_iso_in_desc = {
+ .bLength = UAC_ISO_ENDPOINT_DESC_SIZE,
+ .bDescriptorType = USB_DT_CS_ENDPOINT,
+ .bDescriptorSubtype = UAC_EP_GENERAL,
+ .bmAttributes = 1,
+ .bLockDelayUnits = 1,
+ .wLockDelay = __constant_cpu_to_le16(1),
+};
+
+static struct usb_descriptor_header *hs_audio_desc[] = {
+ (struct usb_descriptor_header *)&ac_interface_desc,
+ (struct usb_descriptor_header *)&ac_header_desc,
+
+ (struct usb_descriptor_header *)&input_terminal_desc,
+ (struct usb_descriptor_header *)&output_terminal_desc,
+ (struct usb_descriptor_header *)&feature_unit_desc,
+
+ (struct usb_descriptor_header *)&as_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_header_desc,
+
+ (struct usb_descriptor_header *)&as_type_i_desc,
+
+ (struct usb_descriptor_header *)&hs_as_in_ep_desc,
+ (struct usb_descriptor_header *)&as_iso_in_desc,
+ NULL,
+};
+
+static struct usb_descriptor_header *fs_audio_desc[] = {
+ (struct usb_descriptor_header *)&ac_interface_desc,
+ (struct usb_descriptor_header *)&ac_header_desc,
+
+ (struct usb_descriptor_header *)&input_terminal_desc,
+ (struct usb_descriptor_header *)&output_terminal_desc,
+ (struct usb_descriptor_header *)&feature_unit_desc,
+
+ (struct usb_descriptor_header *)&as_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_header_desc,
+
+ (struct usb_descriptor_header *)&as_type_i_desc,
+
+ (struct usb_descriptor_header *)&fs_as_in_ep_desc,
+ (struct usb_descriptor_header *)&as_iso_in_desc,
+ NULL,
+};
+
+static struct snd_pcm_hardware audio_hw_info = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER,
+
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 2,
+ .channels_max = 2,
+ .rate_min = SAMPLE_RATE,
+ .rate_max = SAMPLE_RATE,
+
+ .buffer_bytes_max = 1024 * 1024,
+ .period_bytes_min = 64,
+ .period_bytes_max = 512 * 1024,
+ .periods_min = 2,
+ .periods_max = 1024,
+};
+
+/*-------------------------------------------------------------------------*/
+
+struct audio_source_config {
+ int card;
+ int device;
+};
+
+struct audio_dev {
+ struct usb_function func;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *substream;
+
+ struct list_head idle_reqs;
+ struct usb_ep *in_ep;
+ struct usb_endpoint_descriptor *in_desc;
+
+ spinlock_t lock;
+
+ /* beginning, end and current position in our buffer */
+ void *buffer_start;
+ void *buffer_end;
+ void *buffer_pos;
+
+ /* byte size of a "period" */
+ unsigned int period;
+ /* bytes sent since last call to snd_pcm_period_elapsed */
+ unsigned int period_offset;
+ /* time we started playing */
+ ktime_t start_time;
+ /* number of frames sent since start_time */
+ s64 frames_sent;
+};
+
+static inline struct audio_dev *func_to_audio(struct usb_function *f)
+{
+ return container_of(f, struct audio_dev, func);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_request *audio_request_new(struct usb_ep *ep, int buffer_size)
+{
+ struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);
+ if (!req)
+ return NULL;
+
+ req->buf = kmalloc(buffer_size, GFP_KERNEL);
+ if (!req->buf) {
+ usb_ep_free_request(ep, req);
+ return NULL;
+ }
+ req->length = buffer_size;
+ return req;
+}
+
+static void audio_request_free(struct usb_request *req, struct usb_ep *ep)
+{
+ if (req) {
+ kfree(req->buf);
+ usb_ep_free_request(ep, req);
+ }
+}
+
+static void audio_req_put(struct audio_dev *audio, struct usb_request *req)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->lock, flags);
+ list_add_tail(&req->list, &audio->idle_reqs);
+ spin_unlock_irqrestore(&audio->lock, flags);
+}
+
+static struct usb_request *audio_req_get(struct audio_dev *audio)
+{
+ unsigned long flags;
+ struct usb_request *req;
+
+ spin_lock_irqsave(&audio->lock, flags);
+ if (list_empty(&audio->idle_reqs)) {
+ req = 0;
+ } else {
+ req = list_first_entry(&audio->idle_reqs, struct usb_request,
+ list);
+ list_del(&req->list);
+ }
+ spin_unlock_irqrestore(&audio->lock, flags);
+ return req;
+}
+
+/* send the appropriate number of packets to match our bitrate */
+static void audio_send(struct audio_dev *audio)
+{
+ struct snd_pcm_runtime *runtime;
+ struct usb_request *req;
+ int length, length1, length2, ret;
+ s64 msecs;
+ s64 frames;
+ ktime_t now;
+
+ /* audio->substream will be null if we have been closed */
+ if (!audio->substream)
+ return;
+ /* audio->buffer_pos will be null if we have been stopped */
+ if (!audio->buffer_pos)
+ return;
+
+ runtime = audio->substream->runtime;
+
+ /* compute number of frames to send */
+ now = ktime_get();
+ msecs = ktime_to_ns(now) - ktime_to_ns(audio->start_time);
+ do_div(msecs, 1000000);
+ frames = msecs * SAMPLE_RATE;
+ do_div(frames, 1000);
+
+ /* Readjust our frames_sent if we fall too far behind.
+ * If we get too far behind it is better to drop some frames than
+ * to keep sending data too fast in an attempt to catch up.
+ */
+ if (frames - audio->frames_sent > 10 * FRAMES_PER_MSEC)
+ audio->frames_sent = frames - FRAMES_PER_MSEC;
+
+ frames -= audio->frames_sent;
+
+ /* We need to send something to keep the pipeline going */
+ if (frames <= 0)
+ frames = FRAMES_PER_MSEC;
+
+ while (frames > 0) {
+ req = audio_req_get(audio);
+ if (!req)
+ break;
+
+ length = frames_to_bytes(runtime, frames);
+ if (length > IN_EP_MAX_PACKET_SIZE)
+ length = IN_EP_MAX_PACKET_SIZE;
+
+ if (audio->buffer_pos + length > audio->buffer_end)
+ length1 = audio->buffer_end - audio->buffer_pos;
+ else
+ length1 = length;
+ memcpy(req->buf, audio->buffer_pos, length1);
+ if (length1 < length) {
+ /* Wrap around and copy remaining length
+ * at beginning of buffer.
+ */
+ length2 = length - length1;
+ memcpy(req->buf + length1, audio->buffer_start,
+ length2);
+ audio->buffer_pos = audio->buffer_start + length2;
+ } else {
+ audio->buffer_pos += length1;
+ if (audio->buffer_pos >= audio->buffer_end)
+ audio->buffer_pos = audio->buffer_start;
+ }
+
+ req->length = length;
+ ret = usb_ep_queue(audio->in_ep, req, GFP_ATOMIC);
+ if (ret < 0) {
+ pr_err("usb_ep_queue failed ret: %d\n", ret);
+ audio_req_put(audio, req);
+ break;
+ }
+
+ frames -= bytes_to_frames(runtime, length);
+ audio->frames_sent += bytes_to_frames(runtime, length);
+ }
+}
+
+static void audio_control_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ /* nothing to do here */
+}
+
+static void audio_data_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct audio_dev *audio = req->context;
+
+ pr_debug("audio_data_complete req->status %d req->actual %d\n",
+ req->status, req->actual);
+
+ audio_req_put(audio, req);
+
+ if (!audio->buffer_start)
+ return;
+
+ audio->period_offset += req->actual;
+ if (audio->period_offset >= audio->period) {
+ snd_pcm_period_elapsed(audio->substream);
+ audio->period_offset = 0;
+ }
+ audio_send(audio);
+}
+
+static int audio_set_endpoint_req(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ int value = -EOPNOTSUPP;
+ u16 ep = le16_to_cpu(ctrl->wIndex);
+ u16 len = le16_to_cpu(ctrl->wLength);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+
+ pr_debug("bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n",
+ ctrl->bRequest, w_value, len, ep);
+
+ switch (ctrl->bRequest) {
+ case UAC_SET_CUR:
+ case UAC_SET_MIN:
+ case UAC_SET_MAX:
+ case UAC_SET_RES:
+ value = len;
+ break;
+ default:
+ break;
+ }
+
+ return value;
+}
+
+static int audio_get_endpoint_req(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_composite_dev *cdev = f->config->cdev;
+ int value = -EOPNOTSUPP;
+ u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
+ u16 len = le16_to_cpu(ctrl->wLength);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u8 *buf = cdev->req->buf;
+
+ pr_debug("bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n",
+ ctrl->bRequest, w_value, len, ep);
+
+ if (w_value == UAC_EP_CS_ATTR_SAMPLE_RATE << 8) {
+ switch (ctrl->bRequest) {
+ case UAC_GET_CUR:
+ case UAC_GET_MIN:
+ case UAC_GET_MAX:
+ case UAC_GET_RES:
+ /* return our sample rate */
+ buf[0] = (u8)SAMPLE_RATE;
+ buf[1] = (u8)(SAMPLE_RATE >> 8);
+ buf[2] = (u8)(SAMPLE_RATE >> 16);
+ value = 3;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return value;
+}
+
+static int
+audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+ /* composite driver infrastructure handles everything; interface
+ * activation uses set_alt().
+ */
+ switch (ctrl->bRequestType) {
+ case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
+ value = audio_set_endpoint_req(f, ctrl);
+ break;
+
+ case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
+ value = audio_get_endpoint_req(f, ctrl);
+ break;
+ }
+
+ /* respond with data transfer or status phase? */
+ if (value >= 0) {
+ pr_debug("audio req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ req->zero = 0;
+ req->length = value;
+ req->complete = audio_control_complete;
+ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0)
+ pr_err("audio response on err %d\n", value);
+ }
+
+ /* device either stalls (value < 0) or reports success */
+ return value;
+}
+
+static int audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct audio_dev *audio = func_to_audio(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ pr_debug("audio_set_alt intf %d, alt %d\n", intf, alt);
+ config_ep_by_speed(cdev->gadget, f, audio->in_ep);
+ usb_ep_enable(audio->in_ep);
+ return 0;
+}
+
+static void audio_disable(struct usb_function *f)
+{
+ struct audio_dev *audio = func_to_audio(f);
+
+ pr_debug("audio_disable\n");
+ usb_ep_disable(audio->in_ep);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void audio_build_desc(struct audio_dev *audio)
+{
+ u8 *sam_freq;
+ int rate;
+
+ /* Set channel numbers */
+ input_terminal_desc.bNrChannels = 2;
+ as_type_i_desc.bNrChannels = 2;
+
+ /* Set sample rates */
+ rate = SAMPLE_RATE;
+ sam_freq = as_type_i_desc.tSamFreq[0];
+ memcpy(sam_freq, &rate, 3);
+}
+
+/* audio function driver setup/binding */
+static int
+audio_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct audio_dev *audio = func_to_audio(f);
+ int status;
+ struct usb_ep *ep;
+ struct usb_request *req;
+ int i;
+
+ audio_build_desc(audio);
+
+ /* allocate instance-specific interface IDs, and patch descriptors */
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ ac_interface_desc.bInterfaceNumber = status;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ as_interface_alt_0_desc.bInterfaceNumber = status;
+ as_interface_alt_1_desc.bInterfaceNumber = status;
+
+ status = -ENODEV;
+
+ /* allocate our endpoint */
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_as_in_ep_desc);
+ if (!ep)
+ goto fail;
+ audio->in_ep = ep;
+ ep->driver_data = audio; /* claim */
+
+ if (gadget_is_dualspeed(c->cdev->gadget))
+ hs_as_in_ep_desc.bEndpointAddress =
+ fs_as_in_ep_desc.bEndpointAddress;
+
+ f->descriptors = fs_audio_desc;
+ f->hs_descriptors = hs_audio_desc;
+
+ for (i = 0, status = 0; i < IN_EP_REQ_COUNT && status == 0; i++) {
+ req = audio_request_new(ep, IN_EP_MAX_PACKET_SIZE);
+ if (req) {
+ req->context = audio;
+ req->complete = audio_data_complete;
+ audio_req_put(audio, req);
+ } else
+ status = -ENOMEM;
+ }
+
+fail:
+ return status;
+}
+
+static void
+audio_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct audio_dev *audio = func_to_audio(f);
+ struct usb_request *req;
+
+ while ((req = audio_req_get(audio)))
+ audio_request_free(req, audio->in_ep);
+
+ snd_card_free_when_closed(audio->card);
+ kfree(audio);
+}
+
+static void audio_pcm_playback_start(struct audio_dev *audio)
+{
+ audio->start_time = ktime_get();
+ audio->frames_sent = 0;
+ audio_send(audio);
+}
+
+static void audio_pcm_playback_stop(struct audio_dev *audio)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->lock, flags);
+ audio->buffer_start = 0;
+ audio->buffer_end = 0;
+ audio->buffer_pos = 0;
+ spin_unlock_irqrestore(&audio->lock, flags);
+}
+
+static int audio_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct audio_dev *audio = substream->private_data;
+
+ runtime->private_data = audio;
+ runtime->hw = audio_hw_info;
+ snd_pcm_limit_hw_rates(runtime);
+ runtime->hw.channels_max = 2;
+
+ audio->substream = substream;
+ return 0;
+}
+
+static int audio_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct audio_dev *audio = substream->private_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->lock, flags);
+ audio->substream = NULL;
+ spin_unlock_irqrestore(&audio->lock, flags);
+
+ return 0;
+}
+
+static int audio_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ unsigned int channels = params_channels(params);
+ unsigned int rate = params_rate(params);
+
+ if (rate != SAMPLE_RATE)
+ return -EINVAL;
+ if (channels != 2)
+ return -EINVAL;
+
+ return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+ params_buffer_bytes(params));
+}
+
+static int audio_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+static int audio_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct audio_dev *audio = runtime->private_data;
+
+ audio->period = snd_pcm_lib_period_bytes(substream);
+ audio->period_offset = 0;
+ audio->buffer_start = runtime->dma_area;
+ audio->buffer_end = audio->buffer_start
+ + snd_pcm_lib_buffer_bytes(substream);
+ audio->buffer_pos = audio->buffer_start;
+
+ return 0;
+}
+
+static snd_pcm_uframes_t audio_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct audio_dev *audio = runtime->private_data;
+ ssize_t bytes = audio->buffer_pos - audio->buffer_start;
+
+ /* return offset of next frame to fill in our buffer */
+ return bytes_to_frames(runtime, bytes);
+}
+
+static int audio_pcm_playback_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct audio_dev *audio = substream->runtime->private_data;
+ int ret = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ audio_pcm_playback_start(audio);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ audio_pcm_playback_stop(audio);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static struct snd_pcm_ops audio_playback_ops = {
+ .open = audio_pcm_open,
+ .close = audio_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = audio_pcm_hw_params,
+ .hw_free = audio_pcm_hw_free,
+ .prepare = audio_pcm_prepare,
+ .trigger = audio_pcm_playback_trigger,
+ .pointer = audio_pcm_pointer,
+};
+
+int audio_source_bind_config(struct usb_configuration *c,
+ struct audio_source_config *config)
+{
+ struct audio_dev *audio;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ int err;
+
+ config->card = -1;
+ config->device = -1;
+
+ audio = kzalloc(sizeof *audio, GFP_KERNEL);
+ if (!audio)
+ return -ENOMEM;
+
+ audio->func.name = "audio_source";
+
+ spin_lock_init(&audio->lock);
+
+ audio->func.bind = audio_bind;
+ audio->func.unbind = audio_unbind;
+ audio->func.set_alt = audio_set_alt;
+ audio->func.setup = audio_setup;
+ audio->func.disable = audio_disable;
+ audio->in_desc = &fs_as_in_ep_desc;
+
+ INIT_LIST_HEAD(&audio->idle_reqs);
+
+ err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+ THIS_MODULE, 0, &card);
+ if (err)
+ goto snd_card_fail;
+
+ snd_card_set_dev(card, &c->cdev->gadget->dev);
+
+ err = snd_pcm_new(card, "USB audio source", 0, 1, 0, &pcm);
+ if (err)
+ goto pcm_fail;
+ pcm->private_data = audio;
+ pcm->info_flags = 0;
+ audio->pcm = pcm;
+
+ strlcpy(pcm->name, "USB gadget audio", sizeof(pcm->name));
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &audio_playback_ops);
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ NULL, 0, 64 * 1024);
+
+ strlcpy(card->driver, "audio_source", sizeof(card->driver));
+ strlcpy(card->shortname, card->driver, sizeof(card->shortname));
+ strlcpy(card->longname, "USB accessory audio source",
+ sizeof(card->longname));
+
+ err = snd_card_register(card);
+ if (err)
+ goto register_fail;
+
+ err = usb_add_function(c, &audio->func);
+ if (err)
+ goto add_fail;
+
+ config->card = pcm->card->number;
+ config->device = pcm->device;
+ audio->card = card;
+ return 0;
+
+add_fail:
+register_fail:
+pcm_fail:
+ snd_card_free(audio->card);
+snd_card_fail:
+ kfree(audio);
+ return err;
+}
diff --git a/drivers/usb/gadget/tegra_udc.c b/drivers/usb/gadget/tegra_udc.c
index aad99a6cd66e..ddf9c602dc89 100644
--- a/drivers/usb/gadget/tegra_udc.c
+++ b/drivers/usb/gadget/tegra_udc.c
@@ -129,8 +129,9 @@ static void done(struct tegra_ep *ep, struct tegra_req *req, int status)
{
struct tegra_udc *udc = NULL;
unsigned char stopped = ep->stopped;
- struct ep_td_struct *curr_td, *next_td;
+ struct ep_td_struct *curr_td, *next_td = 0;
int j;
+ int count;
BUG_ON(!(in_irq() || irqs_disabled()));
udc = (struct tegra_udc *)ep->udc;
/* Removed the req from tegra_ep->queue */
@@ -143,12 +144,19 @@ static void done(struct tegra_ep *ep, struct tegra_req *req, int status)
status = req->req.status;
/* Free dtd for the request */
- next_td = req->head;
- for (j = 0; j < req->dtd_count; j++) {
+ count = 0;
+ if (ep->last_td) {
+ next_td = ep->last_td;
+ count = ep->last_dtd_count;
+ }
+ ep->last_td = req->head;
+ ep->last_dtd_count = req->dtd_count;
+
+ for (j = 0; j < count; j++) {
curr_td = next_td;
- if (j != req->dtd_count - 1)
+ if (j != count - 1) {
next_td = curr_td->next_td_virt;
-
+ }
dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
}
@@ -568,6 +576,8 @@ static int tegra_ep_enable(struct usb_ep *_ep,
ep->ep.maxpacket = max;
ep->desc = desc;
ep->stopped = 0;
+ ep->last_td = 0;
+ ep->last_dtd_count = 0;
/* Controller related setup
* Init EPx Queue Head (Ep Capabilites field in QH
@@ -610,6 +620,8 @@ static int tegra_ep_disable(struct usb_ep *_ep)
unsigned long flags = 0;
u32 epctrl;
int ep_num;
+ struct ep_td_struct *curr_td, *next_td;
+ int j;
ep = container_of(_ep, struct tegra_ep, ep);
if (!_ep || !ep->desc) {
@@ -638,6 +650,18 @@ static int tegra_ep_disable(struct usb_ep *_ep)
ep->desc = NULL;
ep->stopped = 1;
+ if (ep->last_td) {
+ next_td = ep->last_td;
+ for (j = 0; j < ep->last_dtd_count; j++) {
+ curr_td = next_td;
+ dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
+ if (j != ep->last_dtd_count - 1) {
+ next_td = curr_td->next_td_virt;
+ }
+ }
+ }
+ ep->last_td =0;
+ ep->last_dtd_count = 0;
spin_unlock_irqrestore(&udc->lock, flags);
VDBG("disabled %s OK", _ep->name);
@@ -1216,6 +1240,76 @@ static int tegra_set_selfpowered(struct usb_gadget *gadget, int is_on)
return 0;
}
+static int tegra_usb_set_charging_current(struct tegra_udc *udc)
+{
+ int max_ua;
+
+ if (NULL == udc->vbus_reg)
+ return 0;
+
+ switch (udc->connect_type) {
+ case CONNECT_TYPE_NONE:
+ pr_debug("detected USB charging is disabled");
+ max_ua = 0;
+ break;
+ case CONNECT_TYPE_SDP:
+ pr_debug("detected SDP port");
+ max_ua = USB_CHARGING_SDP_CURRENT_LIMIT_UA;
+ break;
+ case CONNECT_TYPE_DCP:
+ pr_debug("detected DCP port(wall charger)");
+ max_ua = USB_CHARGING_DCP_CURRENT_LIMIT_UA;
+ break;
+ case CONNECT_TYPE_CDP:
+ pr_debug("detected CDP port(1A USB port)");
+ max_ua = USB_CHARGING_CDP_CURRENT_LIMIT_UA;
+ break;
+ case CONNECT_TYPE_NON_STANDARD_CHARGER:
+ pr_debug("detected non-standard charging port");
+ max_ua = USB_CHARGING_NON_STANDARD_CHARGER_CURRENT_LIMIT_UA;
+ break;
+ default:
+ pr_debug("detected USB charging type is unknown");
+ max_ua = 0;
+ }
+
+ return regulator_set_current_limit(udc->vbus_reg, 0, max_ua);
+}
+
+static void tegra_detect_charging_type_is_cdp_or_dcp(struct tegra_udc *udc)
+{
+ u32 portsc;
+ u32 temp;
+ unsigned long flags;
+
+ /* use spinlock to prevent kernel preemption here */
+ spin_lock_irqsave(&udc->lock, flags);
+
+ /* set controller to run which cause D+ pull high */
+ temp = udc_readl(udc, USB_CMD_REG_OFFSET);
+ temp |= USB_CMD_RUN_STOP;
+ udc_writel(udc, temp, USB_CMD_REG_OFFSET);
+
+ udelay(10);
+
+ /* use D+ and D- status to check it is CDP or DCP */
+ portsc = udc_readl(udc, PORTSCX_REG_OFFSET) & PORTSCX_LINE_STATUS_BITS;
+ if (portsc == (PORTSCX_LINE_STATUS_DP_BIT | PORTSCX_LINE_STATUS_DM_BIT))
+ udc->connect_type = CONNECT_TYPE_DCP;
+ else if (portsc == PORTSCX_LINE_STATUS_DP_BIT)
+ udc->connect_type = CONNECT_TYPE_CDP;
+ else
+ /*
+ * If it take more 100mS between D+ pull high and read Line
+ * Status, host might initiate the RESET, then we see both
+ * line status as 0 (SE0). This really should not happen as we
+ * disabled the kernel preemption before reaching here.
+ */
+ BUG();
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+}
+
/**
* Notify controller that VBUS is powered, called by whatever
* detects VBUS sessions
@@ -1238,13 +1332,10 @@ static int tegra_vbus_session(struct usb_gadget *gadget, int is_active)
dr_controller_reset(udc);
udc->vbus_active = 0;
udc->usb_state = USB_STATE_DEFAULT;
+ udc->connect_type = CONNECT_TYPE_NONE;
spin_unlock_irqrestore(&udc->lock,flags);
tegra_usb_phy_power_off(udc->phy);
- if (udc->vbus_reg) {
- /* set the current limit to 0mA */
- regulator_set_current_limit(
- udc->vbus_reg, 0, 0);
- }
+ tegra_usb_set_charging_current(udc);
} else if (!udc->vbus_active && is_active) {
tegra_usb_phy_power_on(udc->phy);
/* setup the controller in the device mode */
@@ -1256,18 +1347,23 @@ static int tegra_vbus_session(struct usb_gadget *gadget, int is_active)
udc->ep0_state = WAIT_FOR_SETUP;
udc->ep0_dir = 0;
udc->vbus_active = 1;
+ if (tegra_usb_phy_charger_detected(udc->phy)) {
+ tegra_detect_charging_type_is_cdp_or_dcp(udc);
+ } else {
+ udc->connect_type = CONNECT_TYPE_SDP;
+ /*
+ * Schedule work to wait for 1000 msec and check for
+ * a non-standard charger if setup packet is not
+ * received.
+ */
+ schedule_delayed_work(&udc->work, msecs_to_jiffies(
+ USB_CHARGER_DETECTION_WAIT_TIME_MS));
+ }
/* start the controller */
dr_controller_run(udc);
- if (udc->vbus_reg) {
- /* set the current limit to 100mA */
- regulator_set_current_limit(
- udc->vbus_reg, 0, 100);
- }
- /* Schedule work to wait for 1000 msec and check for
- * charger if setup packet is not received */
- schedule_delayed_work(&udc->work,
- USB_CHARGER_DETECTION_WAIT_TIME_MS);
+ tegra_usb_set_charging_current(udc);
}
+
return 0;
}
@@ -2095,26 +2191,18 @@ static void tegra_udc_irq_work(struct work_struct *irq_work)
DBG("%s(%d) END\n", __func__, __LINE__);
}
-/**
- * If VBUS is detected and setup packet is not received in 100ms then
- * work thread starts and checks for the USB charger detection.
+/*
+ * When VBUS is detected we already know it is DCP/SDP/CDP devices if it is a
+ * standard device; If we did not receive EP0 setup packet, we can assuming it
+ * is a charger capable of 1.8A charging.
*/
static void tegra_udc_charger_detect_work(struct work_struct *work)
{
struct tegra_udc *udc = container_of(work, struct tegra_udc, work.work);
DBG("%s(%d) BEGIN\n", __func__, __LINE__);
- /* check for the platform charger detection */
- if (tegra_usb_phy_charger_detected(udc->phy)) {
- printk(KERN_INFO "USB compliant charger detected\n");
- /* check udc regulator is available for drawing vbus current*/
- if (udc->vbus_reg) {
- /* set the current limit in uA */
- regulator_set_current_limit(
- udc->vbus_reg, 0,
- USB_CHARGING_CURRENT_LIMIT_MA*1000);
- }
- }
+ udc->connect_type = CONNECT_TYPE_NON_STANDARD_CHARGER;
+ tegra_usb_set_charging_current(udc);
DBG("%s(%d) END\n", __func__, __LINE__);
}
@@ -2159,10 +2247,8 @@ static irqreturn_t tegra_udc_irq(int irq, void *_udc)
}
/* Disable ISR for OTG host mode */
- if (udc->stopped) {
- spin_unlock_irqrestore(&udc->lock, flags);
- return status;
- }
+ if (udc->stopped)
+ goto done;
/* Fence read for coherency of AHB master intiated writes */
readb(IO_ADDRESS(IO_PPCS_PHYS + USB1_PREFETCH_ID));
@@ -2170,6 +2256,9 @@ static irqreturn_t tegra_udc_irq(int irq, void *_udc)
irq_src = udc_readl(udc, USB_STS_REG_OFFSET) &
udc_readl(udc, USB_INTR_REG_OFFSET);
+ if (irq_src == 0)
+ goto done;
+
/* Clear notification bits */
udc_writel(udc, irq_src, USB_STS_REG_OFFSET);
@@ -2226,6 +2315,7 @@ static irqreturn_t tegra_udc_irq(int irq, void *_udc)
if (irq_src & (USB_STS_ERR | USB_STS_SYS_ERR))
VDBG("Error IRQ %x", irq_src);
+done:
spin_unlock_irqrestore(&udc->lock, flags);
return status;
}
@@ -2274,11 +2364,13 @@ static int tegra_udc_start(struct usb_gadget_driver *driver,
/* Enable DR IRQ reg and Set usbcmd reg Run bit */
- dr_controller_run(udc);
- udc->usb_state = USB_STATE_ATTACHED;
- udc->ep0_state = WAIT_FOR_SETUP;
- udc->ep0_dir = 0;
- udc->vbus_active = vbus_enabled(udc);
+ if (vbus_enabled(udc)) {
+ dr_controller_run(udc);
+ udc->usb_state = USB_STATE_ATTACHED;
+ udc->ep0_state = WAIT_FOR_SETUP;
+ udc->ep0_dir = 0;
+ udc->vbus_active = vbus_enabled(udc);
+ }
printk(KERN_INFO "%s: bind to driver %s\n",
udc->gadget.name, driver->driver.name);
@@ -2632,7 +2724,7 @@ static int __init tegra_udc_probe(struct platform_device *pdev)
}
#else
/* Power down the phy if cable is not connected */
- if (!vbus_enabled())
+ if (!vbus_enabled(udc))
tegra_usb_phy_power_off(udc->phy);
#endif
diff --git a/drivers/usb/gadget/tegra_udc.h b/drivers/usb/gadget/tegra_udc.h
index e94543fd98e3..094e3eb0e458 100644
--- a/drivers/usb/gadget/tegra_udc.h
+++ b/drivers/usb/gadget/tegra_udc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 NVIDIA Corporation
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
* Description:
* High-speed USB device controller driver.
@@ -38,7 +38,11 @@
#define USB_MAX_CTRL_PAYLOAD 64
/* Charger current limit=1800mA, as per the USB charger spec */
-#define USB_CHARGING_CURRENT_LIMIT_MA 1800
+#define USB_CHARGING_DCP_CURRENT_LIMIT_UA 1800000
+#define USB_CHARGING_CDP_CURRENT_LIMIT_UA 900000
+#define USB_CHARGING_SDP_CURRENT_LIMIT_UA 100000
+#define USB_CHARGING_NON_STANDARD_CHARGER_CURRENT_LIMIT_UA 1800000
+
/* 1 sec wait time for charger detection after vbus is detected */
#define USB_CHARGER_DETECTION_WAIT_TIME_MS 1000
#define BOOST_TRIGGER_SIZE 4096
@@ -156,6 +160,8 @@
#define PORTSCX_PORT_SUSPEND 0x00000080
#define PORTSCX_PORT_RESET 0x00000100
#define PORTSCX_LINE_STATUS_BITS 0x00000C00
+#define PORTSCX_LINE_STATUS_DP_BIT 0x00000800
+#define PORTSCX_LINE_STATUS_DM_BIT 0x00000400
#define PORTSCX_PORT_POWER 0x00001000
#define PORTSCX_PORT_INDICTOR_CTRL 0x0000C000
#define PORTSCX_PORT_TEST_CTRL 0x000F0000
@@ -390,11 +396,21 @@ struct tegra_ep {
struct ep_queue_head *qh;
const struct usb_endpoint_descriptor *desc;
struct usb_gadget *gadget;
+ struct ep_td_struct *last_td;
+ int last_dtd_count;
char name[14];
unsigned stopped:1;
};
+enum tegra_connect_type {
+ CONNECT_TYPE_NONE,
+ CONNECT_TYPE_SDP,
+ CONNECT_TYPE_DCP,
+ CONNECT_TYPE_CDP,
+ CONNECT_TYPE_NON_STANDARD_CHARGER
+};
+
struct tegra_udc {
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
@@ -415,6 +431,7 @@ struct tegra_udc {
struct work_struct boost_cpufreq_work;
/* irq work for controlling the usb power */
struct work_struct irq_work;
+ enum tegra_connect_type connect_type;
void __iomem *regs;
size_t ep_qh_size; /* size after alignment adjustment*/
dma_addr_t ep_qh_dma; /* dma address of QH */
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 5c25783a7643..0eb20989d67e 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -334,6 +334,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
qh->qh_state = QH_STATE_COMPLETING;
stopped = (state == QH_STATE_IDLE);
+ ehci_sync_qh(ehci, qh);
rescan:
last = NULL;
last_status = -EINPROGRESS;
@@ -367,6 +368,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
if (qtd == end)
break;
+ ehci_sync_qtd(ehci, qtd);
/* hardware copies qtd out of qh overlay */
rmb ();
token = hc32_to_cpu(ehci, qtd->hw_token);
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 33504e402611..af6fa87fb645 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -156,7 +156,6 @@ static irqreturn_t tegra_ehci_irq(struct usb_hcd *hcd)
struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
irqreturn_t irq_status;
- bool pmc_remote_wakeup = false;
spin_lock(&ehci->lock);
irq_status = tegra_usb_phy_irq(tegra->phy);
@@ -166,8 +165,9 @@ static irqreturn_t tegra_ehci_irq(struct usb_hcd *hcd)
}
if (tegra_usb_phy_remote_wakeup(tegra->phy)) {
ehci_info(ehci, "remote wakeup detected\n");
- pmc_remote_wakeup = true;
usb_hcd_resume_root_hub(hcd);
+ spin_unlock(&ehci->lock);
+ return irq_status;
}
spin_unlock(&ehci->lock);
@@ -178,10 +178,6 @@ static irqreturn_t tegra_ehci_irq(struct usb_hcd *hcd)
irq_status = ehci_irq(hcd);
- if (pmc_remote_wakeup) {
- ehci->controller_remote_wakeup = false;
- }
-
if (ehci->controller_remote_wakeup) {
ehci->controller_remote_wakeup = false;
tegra_usb_phy_pre_resume(tegra->phy, true);
@@ -202,7 +198,6 @@ static int tegra_ehci_hub_control(
{
struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- unsigned long flags;
int retval = 0;
u32 __iomem *status_reg;
@@ -216,6 +211,7 @@ static int tegra_ehci_hub_control(
switch (typeReq) {
case GetPortStatus:
if (tegra->port_resuming) {
+ u32 cmd;
int delay = ehci->reset_done[wIndex-1] - jiffies;
/* Sometimes it seems we get called too soon... In that case, wait.*/
if (delay > 0) {
@@ -230,9 +226,11 @@ static int tegra_ehci_hub_control(
tegra_usb_phy_post_resume(tegra->phy);
tegra->port_resuming = 0;
/* If run bit is not set by now enable it */
- if (ehci->command & CMD_RUN) {
+ cmd = ehci_readl(ehci, &ehci->regs->command);
+ if (!(cmd & CMD_RUN)) {
+ cmd |= CMD_RUN;
ehci->command |= CMD_RUN;
- ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ ehci_writel(ehci, cmd, &ehci->regs->command);
}
/* Now we can safely re-enable irqs */
ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
@@ -553,10 +551,10 @@ static int tegra_ehci_remove(struct platform_device *pdev)
tegra_usb_phy_power_on(tegra->phy);
usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
tegra_usb_phy_power_off(tegra->phy);
tegra_usb_phy_close(tegra->phy);
iounmap(hcd->regs);
+ usb_put_hcd(hcd);
return 0;
}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index cfbdf32ec0b2..569cdf5a4c03 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -767,10 +767,32 @@ static inline void ehci_sync_mem(void)
{
mb();
}
+
+/*
+ * DMA coherent memory on ARM which features speculative prefetcher doesn't
+ * guarantee coherency, so introduce the helpers which can invalidate QH and
+ * QTD in L1/L2 cache. It enforces CPU reads from memory directly.
+ */
+static inline void ehci_sync_qh(struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+ dma_sync_single_for_cpu(ehci_to_hcd(ehci)->self.controller, qh->qh_dma,
+ sizeof(struct ehci_qh_hw), DMA_FROM_DEVICE);
+}
+static inline void ehci_sync_qtd(struct ehci_hcd *ehci, struct ehci_qtd *qtd)
+{
+ dma_sync_single_for_cpu(ehci_to_hcd(ehci)->self.controller,
+ qtd->qtd_dma, sizeof(struct ehci_qtd), DMA_FROM_DEVICE);
+}
#else
static inline void ehci_sync_mem()
{
}
+static inline void ehci_sync_qh(struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+}
+static inline void ehci_sync_qtd(struct ehci_hcd *ehci, struct ehci_qtd *qtd)
+{
+}
#endif
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index c09f9b829382..cbedff4e254f 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg_id.o
# transceiver drivers
obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o
obj-$(CONFIG_USB_COLIBRI_OTG) += colibri-otg.o
+CFLAGS_tegra-otg.o = -Werror
obj-$(CONFIG_USB_TEGRA_OTG) += tegra-otg.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c
index a5e85bf90d14..22e303ede24e 100644
--- a/drivers/usb/otg/tegra-otg.c
+++ b/drivers/usb/otg/tegra-otg.c
@@ -53,6 +53,7 @@ struct tegra_otg_data {
struct otg_transceiver otg;
unsigned long int_status;
spinlock_t lock;
+ struct mutex irq_work_mutex;
void __iomem *regs;
struct clk *clk;
int irq;
@@ -62,7 +63,7 @@ struct tegra_otg_data {
bool clk_enabled;
bool interrupt_mode;
bool builtin_host;
- bool suspended
+ bool suspended;
};
static struct tegra_otg_data *tegra_clone;
@@ -105,7 +106,7 @@ static unsigned long enable_interrupt(struct tegra_otg_data *tegra, bool en)
if (tegra->builtin_host)
val |= USB_INT_EN;
else
- val = USB_VBUS_INT_EN | USB_VBUS_WAKEUP_EN | USB_ID_PIN_WAKEUP_EN;
+ val |= USB_VBUS_INT_EN | USB_VBUS_WAKEUP_EN | USB_ID_PIN_WAKEUP_EN;
}
else
val &= ~USB_INT_EN;
@@ -181,6 +182,12 @@ static void tegra_stop_host(struct tegra_otg_data *tegra)
DBG("%s(%d) End\n", __func__, __LINE__);
}
+static void tegra_otg_notify_event(struct otg_transceiver *otg,
+ enum usb_xceiv_events event)
+{
+ otg->last_event = event;
+ atomic_notifier_call_chain(&otg->notifier, event, NULL);
+}
static void tegra_change_otg_state(struct tegra_otg_data *tegra,
enum usb_otg_state to)
@@ -202,16 +209,24 @@ static void tegra_change_otg_state(struct tegra_otg_data *tegra,
tegra_state_name(to));
if (from == OTG_STATE_A_SUSPEND) {
- if (to == OTG_STATE_B_PERIPHERAL && otg->gadget)
+ if (to == OTG_STATE_B_PERIPHERAL && otg->gadget) {
usb_gadget_vbus_connect(otg->gadget);
- else if (to == OTG_STATE_A_HOST)
+ tegra_otg_notify_event(otg, USB_EVENT_VBUS);
+ }
+ else if (to == OTG_STATE_A_HOST) {
tegra_start_host(tegra);
+ tegra_otg_notify_event(otg, USB_EVENT_ID);
+ }
} else if (from == OTG_STATE_A_HOST) {
- if (to == OTG_STATE_A_SUSPEND)
+ if (to == OTG_STATE_A_SUSPEND) {
tegra_stop_host(tegra);
+ tegra_otg_notify_event(otg, USB_EVENT_NONE);
+ }
} else if (from == OTG_STATE_B_PERIPHERAL && otg->gadget) {
- if (to == OTG_STATE_A_SUSPEND)
+ if (to == OTG_STATE_A_SUSPEND) {
usb_gadget_vbus_disconnect(otg->gadget);
+ tegra_otg_notify_event(otg, USB_EVENT_NONE);
+ }
}
}
}
@@ -221,16 +236,19 @@ static void irq_work(struct work_struct *work)
struct tegra_otg_data *tegra =
container_of(work, struct tegra_otg_data, work);
struct otg_transceiver *otg = &tegra->otg;
- enum usb_otg_state from = otg->state;
+ enum usb_otg_state from;
enum usb_otg_state to = OTG_STATE_UNDEFINED;
unsigned long flags;
unsigned long status;
+ mutex_lock(&tegra->irq_work_mutex);
+
spin_lock_irqsave(&tegra->lock, flags);
+ from = otg->state;
status = tegra->int_status;
/* Debug prints */
- DBG("%s(%d) status = 0x%x\n", __func__, __LINE__, status);
+ DBG("%s(%d) status = 0x%lx\n", __func__, __LINE__, status);
if ((status & USB_ID_INT_STATUS) &&
(status & USB_VBUS_INT_STATUS))
DBG("%s(%d) got vbus & id interrupt\n", __func__, __LINE__);
@@ -250,6 +268,7 @@ static void irq_work(struct work_struct *work)
spin_unlock_irqrestore(&tegra->lock, flags);
tegra_change_otg_state(tegra, to);
+ mutex_unlock(&tegra->irq_work_mutex);
}
static irqreturn_t tegra_otg_irq(int irq, void *data)
@@ -260,10 +279,10 @@ static irqreturn_t tegra_otg_irq(int irq, void *data)
spin_lock_irqsave(&tegra->lock, flags);
val = otg_readl(tegra, USB_PHY_WAKEUP);
- DBG("%s(%d) interrupt val = 0x%x\n", __func__, __LINE__, val);
+ DBG("%s(%d) interrupt val = 0x%lx\n", __func__, __LINE__, val);
if (val & (USB_VBUS_INT_EN | USB_ID_INT_EN)) {
- DBG("%s(%d) PHY_WAKEUP = 0x%x\n", __func__, __LINE__, val);
+ DBG("%s(%d) PHY_WAKEUP = 0x%lx\n", __func__, __LINE__, val);
otg_writel(tegra, val, USB_PHY_WAKEUP);
if ((val & USB_ID_INT_STATUS) || (val & USB_VBUS_INT_STATUS)) {
tegra->int_status = val;
@@ -355,7 +374,7 @@ static ssize_t store_host_en(struct device *dev, struct device_attribute *attr,
{
struct platform_device *pdev = to_platform_device(dev);
struct tegra_otg_data *tegra = platform_get_drvdata(pdev);
- unsigned long host;
+ unsigned int host;
if (sscanf(buf, "%d", &host) != 1 || host < 0 || host > 1)
return -EINVAL;
@@ -395,6 +414,7 @@ static int tegra_otg_probe(struct platform_device *pdev)
tegra->otg.set_suspend = tegra_otg_set_suspend;
tegra->otg.set_power = tegra_otg_set_power;
spin_lock_init(&tegra->lock);
+ mutex_init(&tegra->irq_work_mutex);
if (pdata) {
tegra->builtin_host = !pdata->ehci_pdata->builtin_host_disabled;
@@ -498,6 +518,7 @@ static int __exit tegra_otg_remove(struct platform_device *pdev)
clk_disable(tegra->clk);
clk_put(tegra->clk);
platform_set_drvdata(pdev, NULL);
+ mutex_destroy(&tegra->irq_work_mutex);
kfree(tegra);
return 0;
@@ -510,6 +531,8 @@ static int tegra_otg_suspend(struct device *dev)
struct tegra_otg_data *tegra = platform_get_drvdata(pdev);
struct otg_transceiver *otg = &tegra->otg;
int val;
+
+ mutex_lock(&tegra->irq_work_mutex);
DBG("%s(%d) BEGIN state : %s\n", __func__, __LINE__,
tegra_state_name(otg->state));
@@ -526,6 +549,7 @@ static int tegra_otg_suspend(struct device *dev)
tegra->suspended = true;
DBG("%s(%d) END\n", __func__, __LINE__);
+ mutex_unlock(&tegra->irq_work_mutex);
return 0;
}
@@ -533,13 +557,15 @@ static void tegra_otg_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct tegra_otg_data *tegra = platform_get_drvdata(pdev);
- struct otg_transceiver *otg = &tegra->otg;
int val;
unsigned long flags;
DBG("%s(%d) BEGIN\n", __func__, __LINE__);
- if (!tegra->suspended)
+ mutex_lock(&tegra->irq_work_mutex);
+ if (!tegra->suspended) {
+ mutex_unlock(&tegra->irq_work_mutex);
return;
+ }
/* Clear pending interrupts */
clk_enable(tegra->clk);
@@ -548,10 +574,6 @@ static void tegra_otg_resume(struct device *dev)
DBG("%s(%d) PHY WAKEUP register : 0x%x\n", __func__, __LINE__, val);
clk_disable(tegra->clk);
- /* Handle if host cable is replaced with device during suspend state */
- if (otg->state == OTG_STATE_A_HOST && (val & USB_ID_STATUS))
- tegra_change_otg_state(tegra, OTG_STATE_A_SUSPEND);
-
/* Enable interrupt and call work to set to appropriate state */
spin_lock_irqsave(&tegra->lock, flags);
if (tegra->builtin_host)
@@ -561,13 +583,13 @@ static void tegra_otg_resume(struct device *dev)
USB_ID_PIN_WAKEUP_EN;
spin_unlock_irqrestore(&tegra->lock, flags);
- irq_work(&tegra->work);
-
+ schedule_work(&tegra->work);
enable_interrupt(tegra, true);
tegra->suspended = false;
DBG("%s(%d) END\n", __func__, __LINE__);
+ mutex_unlock(&tegra->irq_work_mutex);
}
static const struct dev_pm_ops tegra_otg_pm_ops = {
diff --git a/drivers/usb/serial/baseband_usb_chr.c b/drivers/usb/serial/baseband_usb_chr.c
index 96db92715207..c4eda3fe1ab7 100644
--- a/drivers/usb/serial/baseband_usb_chr.c
+++ b/drivers/usb/serial/baseband_usb_chr.c
@@ -74,6 +74,13 @@ static struct workqueue_struct *chr_ipc_wq;
static atomic_t g_rx_count = ATOMIC_INIT(0);
+struct usb_chr_resource {
+ unsigned char *ipc_rx;
+ unsigned char *ipc_tx;
+ unsigned char *rx_buf;
+};
+static struct usb_chr_resource usb_chr_res;
+
/* baseband ipc functions */
static void baseband_ipc_dump(const char *prefix, unsigned long int offset,
@@ -521,9 +528,7 @@ static void baseband_ipc_close(struct baseband_ipc *ipc)
memset(&ipc->rx.wait, 0, sizeof(ipc->rx.wait));
/* destroy data buffers */
- kfree(ipc->ipc_tx);
ipc->ipc_tx = (unsigned char *) 0;
- kfree(ipc->ipc_rx);
ipc->ipc_rx = (unsigned char *) 0;
list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx_free.buf, list)
{
@@ -601,16 +606,14 @@ static struct baseband_ipc *baseband_ipc_open(work_func_t work_func,
ipc_buf);
list_add_tail(&ipc_buf->list, &ipc->tx_free.buf);
}
- ipc->ipc_rx = kmalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL);
+ ipc->ipc_rx = usb_chr_res.ipc_rx;
if (!ipc->ipc_rx) {
- pr_err("baseband_ipc_open - "
- "cannot allocate ipc->ipc_rx\n");
+ pr_err("%s: cannot find ipc->ipc_rx\n", __func__);
goto error_exit;
}
- ipc->ipc_tx = kmalloc(USB_CHR_TX_BUFSIZ, GFP_KERNEL);
+ ipc->ipc_tx = usb_chr_res.ipc_tx;
if (!ipc->ipc_tx) {
- pr_err("baseband_ipc_open - "
- "cannot allocate ipc->ipc_tx\n");
+ pr_err("%s: cannot find ipc->ipc_tx\n", __func__);
goto error_exit;
}
@@ -867,6 +870,7 @@ static void baseband_usb_driver_disconnect(struct usb_interface *intf)
&& baseband_usb_chr->ipc->workqueue)
flush_workqueue(baseband_usb_chr->ipc->workqueue);
usb_device_connection = false;
+ probe_usb_intf = NULL;
}
pr_debug("%s(%d) }\n", __func__, __LINE__);
}
@@ -956,7 +960,6 @@ static void baseband_usb_close(struct baseband_usb *usb)
usb_kill_urb(usb->usb.rx_urb);
if (usb->usb.rx_urb->transfer_buffer) {
pr_debug("%s: free rx urb transfer buffer\n", __func__);
- kfree(usb->usb.rx_urb->transfer_buffer);
usb->usb.rx_urb->transfer_buffer = (void *) 0;
}
}
@@ -966,13 +969,6 @@ static void baseband_usb_close(struct baseband_usb *usb)
flush_work_sync(&usb->ipc->rx_work);
}
- /* close usb driver */
- if (usb->usb.driver) {
- pr_debug("close usb driver {\n");
- usb_deregister(usb->usb.driver);
- usb->usb.driver = (struct usb_driver *) 0;
- pr_debug("close usb driver }\n");
- }
/* close baseband ipc */
if (usb->ipc) {
@@ -1014,24 +1010,17 @@ static struct baseband_usb *baseband_usb_open(work_func_t work_func,
goto error_exit;
}
- /* open usb driver */
- probe_usb_intf = (struct usb_interface *) 0;
usb->usb.driver = &baseband_usb_driver;
- err = usb_register(&baseband_usb_driver);
- if (err < 0) {
- pr_err("cannot open usb driver - err %d\n", err);
- goto error_exit;
- }
- /* wait for probe */
- pr_info("%s: waiting for usb probe...\n", __func__);
- for (i = 0; i < 5 * 10; i++) {
+ for (i = 0; i < 5 * 50; i++) {
if (probe_usb_intf && usb_device_connection)
break;
- msleep(100);
+ /* wait for probe */
+ pr_debug("%s: waiting for usb probe...\n", __func__);
+ msleep(20);
}
if (!probe_usb_intf || !usb_device_connection) {
- pr_info("%s: probe timed out!\n", __func__);
+ pr_err("%s: probe timed out!\n", __func__);
goto error_exit;
}
@@ -1066,9 +1055,9 @@ static struct baseband_usb *baseband_usb_open(work_func_t work_func,
pr_err("usb_alloc_urb() failed\n");
goto error_exit;
}
- buf = kmalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL);
+ buf = usb_chr_res.rx_buf;
if (!buf) {
- pr_err("%s: usb buffer kmalloc() failed\n", __func__);
+ pr_err("%s: usb rx buffer not found\n", __func__);
usb_free_urb(urb);
goto error_exit;
}
@@ -1222,17 +1211,33 @@ static const struct file_operations baseband_usb_chr_fops = {
static int baseband_usb_chr_init(void)
{
- int err;
+ int err = -ENOMEM;
pr_debug("baseband_usb_chr_init {\n");
+ usb_chr_res.ipc_rx = kmalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL);
+ if (!usb_chr_res.ipc_rx) {
+ pr_err("cannot allocate ipc_rx\n");
+ goto error;
+ }
+ usb_chr_res.ipc_tx = kmalloc(USB_CHR_TX_BUFSIZ, GFP_KERNEL);
+ if (!usb_chr_res.ipc_tx) {
+ pr_err("cannot allocate ipc_tx\n");
+ goto error;
+ }
+ usb_chr_res.rx_buf = kmalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL);
+ if (!usb_chr_res.rx_buf) {
+ pr_err("%s: usb buffer kmalloc() failed\n", __func__);
+ goto error;
+ }
+
/* register character device */
err = register_chrdev(BASEBAND_USB_CHR_DEV_MAJOR,
BASEBAND_USB_CHR_DEV_NAME,
&baseband_usb_chr_fops);
if (err < 0) {
pr_err("cannot register character device - %d\n", err);
- return err;
+ goto error;
}
pr_debug("registered baseband usb character device - major %d\n",
BASEBAND_USB_CHR_DEV_MAJOR);
@@ -1243,11 +1248,30 @@ static int baseband_usb_chr_init(void)
pr_err("cannot create workqueue\n");
unregister_chrdev(BASEBAND_USB_CHR_DEV_MAJOR,
BASEBAND_USB_CHR_DEV_NAME);
- return -ENODEV;
+ err = -ENODEV;
+ goto error;
+ }
+
+ /* register usb driver */
+ err = usb_register(&baseband_usb_driver);
+ if (err < 0) {
+ pr_err("%s: cannot register usb driver %d\n", __func__, err);
+ goto error2;
}
pr_debug("baseband_usb_chr_init }\n");
return 0;
+
+error2:
+ unregister_chrdev(BASEBAND_USB_CHR_DEV_MAJOR,
+ BASEBAND_USB_CHR_DEV_NAME);
+ destroy_workqueue(chr_ipc_wq);
+ chr_ipc_wq = NULL;
+error:
+ kfree(usb_chr_res.ipc_rx);
+ kfree(usb_chr_res.ipc_tx);
+ kfree(usb_chr_res.rx_buf);
+ return err;
}
static void baseband_usb_chr_exit(void)
@@ -1262,6 +1286,14 @@ static void baseband_usb_chr_exit(void)
destroy_workqueue(chr_ipc_wq);
chr_ipc_wq = NULL;
}
+
+ /* close usb driver */
+ usb_deregister(&baseband_usb_driver);
+
+ kfree(usb_chr_res.ipc_rx);
+ kfree(usb_chr_res.ipc_tx);
+ kfree(usb_chr_res.rx_buf);
+
pr_debug("baseband_usb_chr_exit }\n");
}
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index debd41c9313e..400cf43c5972 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
+CFLAGS_tegra_pwm_bl.o = -Werror
obj-$(CONFIG_BACKLIGHT_TEGRA_PWM) += tegra_pwm_bl.o
obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o
diff --git a/drivers/video/tegra/Kconfig b/drivers/video/tegra/Kconfig
index b5540a5793b2..68cf54264403 100644
--- a/drivers/video/tegra/Kconfig
+++ b/drivers/video/tegra/Kconfig
@@ -119,7 +119,7 @@ config NVMAP_PAGE_POOL_SIZE
default 0x0
config NVMAP_CACHE_MAINT_BY_SET_WAYS
- bool "Enalbe cache maintenance by set/ways"
+ bool "Enable cache maintenance by set/ways"
depends on TEGRA_NVMAP
help
Say Y here to reduce cache maintenance overhead by MVA.
@@ -127,6 +127,14 @@ config NVMAP_CACHE_MAINT_BY_SET_WAYS
where inner cache includes only L1. For the systems, where inner cache
includes L1 and L2, keep this option disabled.
+config NVMAP_OUTER_CACHE_MAINT_BY_SET_WAYS
+ bool "Enable outer cache maintenance by set/ways"
+ depends on TEGRA_NVMAP
+ help
+ Say Y here if you want to optimize cache maintenance for ranges
+ bigger than size of outer cache. This option has no effect on
+ system without outer cache.
+
config NVMAP_VPR
bool "Enable VPR Heap."
depends on TEGRA_NVMAP
@@ -135,6 +143,15 @@ config NVMAP_VPR
Say Y here to enable Video Protection Region(VPR) heap.
if unsure, say N.
+config NVMAP_FORCE_ZEROED_USER_PAGES
+ bool "Only alloc zeroed pages for user space"
+ depends on TEGRA_NVMAP
+ help
+ Say Y here to force zeroing of pages allocated for user space. This
+ avoids leaking kernel secure data to user space. This can add
+ significant overhead to allocation operations depending on the
+ allocation size requested.
+
config TEGRA_DSI
bool "Enable DSI panel."
default n
diff --git a/drivers/video/tegra/dc/csc.c b/drivers/video/tegra/dc/csc.c
index 74fa900352a1..09db5fee4c6f 100644
--- a/drivers/video/tegra/dc/csc.c
+++ b/drivers/video/tegra/dc/csc.c
@@ -54,10 +54,12 @@ int tegra_dc_update_csc(struct tegra_dc *dc, int win_idx)
return -EFAULT;
}
+ tegra_dc_hold_dc_out(dc);
tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
DC_CMD_DISPLAY_WINDOW_HEADER);
tegra_dc_set_csc(dc, &dc->windows[win_idx].csc);
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 1f7e2ce67682..d01df2f520b8 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -82,7 +82,7 @@ struct tegra_dc *tegra_dcs[TEGRA_MAX_DC];
DEFINE_MUTEX(tegra_dc_lock);
DEFINE_MUTEX(shared_lock);
-static inline void tegra_dc_clk_enable(struct tegra_dc *dc)
+void tegra_dc_clk_enable(struct tegra_dc *dc)
{
if (!tegra_is_clk_enabled(dc->clk)) {
clk_enable(dc->clk);
@@ -90,7 +90,7 @@ static inline void tegra_dc_clk_enable(struct tegra_dc *dc)
}
}
-static inline void tegra_dc_clk_disable(struct tegra_dc *dc)
+void tegra_dc_clk_disable(struct tegra_dc *dc)
{
if (tegra_is_clk_enabled(dc->clk)) {
clk_disable(dc->clk);
@@ -98,6 +98,18 @@ static inline void tegra_dc_clk_disable(struct tegra_dc *dc)
}
}
+void tegra_dc_hold_dc_out(struct tegra_dc *dc)
+{
+ if (dc->out_ops->hold)
+ dc->out_ops->hold(dc);
+}
+
+void tegra_dc_release_dc_out(struct tegra_dc *dc)
+{
+ if (dc->out_ops->release)
+ dc->out_ops->release(dc);
+}
+
#define DUMP_REG(a) do { \
snprintf(buff, sizeof(buff), "%-32s\t%03x\t%08lx\n", \
#a, a, tegra_dc_readl(dc, a)); \
@@ -121,8 +133,9 @@ static void _dump_regs(struct tegra_dc *dc, void *data,
int i;
char buff[256];
+ mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
tegra_dc_io_start(dc);
- tegra_dc_clk_enable(dc);
DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
DUMP_REG(DC_CMD_DISPLAY_COMMAND);
@@ -272,8 +285,9 @@ static void _dump_regs(struct tegra_dc *dc, void *data,
DUMP_REG(DC_COM_PM1_DUTY_CYCLE);
DUMP_REG(DC_DISP_SD_CONTROL);
- tegra_dc_clk_disable(dc);
tegra_dc_io_end(dc);
+ tegra_dc_release_dc_out(dc);
+ mutex_unlock(&dc->lock);
}
#undef DUMP_REG
@@ -488,9 +502,13 @@ int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win)
if (!dc->enabled)
return 0;
BUG_ON(win > DC_N_WINDOWS);
+ mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
tegra_dc_writel(dc, WINDOW_A_SELECT << win,
DC_CMD_DISPLAY_WINDOW_HEADER);
stride = tegra_dc_readl(dc, DC_WIN_LINE_STRIDE);
+ tegra_dc_release_dc_out(dc);
+ mutex_unlock(&dc->lock);
return GET_LINE_STRIDE(stride);
}
EXPORT_SYMBOL(tegra_dc_get_stride);
@@ -550,17 +568,6 @@ static void tegra_dc_set_scaling_filter(struct tegra_dc *dc)
}
}
-void tegra_dc_host_suspend(struct tegra_dc *dc)
-{
- tegra_dsi_host_suspend(dc);
- tegra_dc_clk_disable(dc);
-}
-
-void tegra_dc_host_resume(struct tegra_dc *dc) {
- tegra_dc_clk_enable(dc);
- tegra_dsi_host_resume(dc);
-}
-
static inline void disable_dc_irq(unsigned int irq)
{
disable_irq(irq);
@@ -577,9 +584,11 @@ u32 tegra_dc_incr_syncpt_max(struct tegra_dc *dc, int i)
u32 max;
mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
max = nvhost_syncpt_incr_max_ext(dc->ndev,
dc->syncpt[i].id, ((dc->enabled) ? 1 : 0));
dc->syncpt[i].max = max;
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
return max;
@@ -588,11 +597,14 @@ u32 tegra_dc_incr_syncpt_max(struct tegra_dc *dc, int i)
void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, int i, u32 val)
{
mutex_lock(&dc->lock);
- if ( dc->enabled )
+ if (dc->enabled) {
+ tegra_dc_hold_dc_out(dc);
while (dc->syncpt[i].min < val) {
dc->syncpt[i].min++;
nvhost_syncpt_cpu_incr_ext(dc->ndev, dc->syncpt[i].id);
}
+ tegra_dc_release_dc_out(dc);
+ }
mutex_unlock(&dc->lock);
}
@@ -609,8 +621,7 @@ tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg)
return;
}
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
+ tegra_dc_hold_dc_out(dc);
ctrl = ((cfg->period << PM_PERIOD_SHIFT) |
(cfg->clk_div << PM_CLK_DIVIDER_SHIFT) |
@@ -644,6 +655,7 @@ tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg)
break;
}
tegra_dc_writel(dc, cmd_state, DC_CMD_STATE_ACCESS);
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
}
EXPORT_SYMBOL(tegra_dc_config_pwm);
@@ -790,6 +802,9 @@ EXPORT_SYMBOL(tegra_dc_get_out_max_pixclock);
void tegra_dc_enable_crc(struct tegra_dc *dc)
{
u32 val;
+
+ mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
tegra_dc_io_start(dc);
val = CRC_ALWAYS_ENABLE | CRC_INPUT_DATA_ACTIVE_DATA |
@@ -797,15 +812,21 @@ void tegra_dc_enable_crc(struct tegra_dc *dc)
tegra_dc_writel(dc, val, DC_COM_CRC_CONTROL);
tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+ tegra_dc_release_dc_out(dc);
+ mutex_unlock(&dc->lock);
}
void tegra_dc_disable_crc(struct tegra_dc *dc)
{
+ mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
tegra_dc_writel(dc, 0x0, DC_COM_CRC_CONTROL);
tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
tegra_dc_io_end(dc);
+ tegra_dc_release_dc_out(dc);
+ mutex_unlock(&dc->lock);
}
u32 tegra_dc_read_checksum_latched(struct tegra_dc *dc)
@@ -821,7 +842,11 @@ u32 tegra_dc_read_checksum_latched(struct tegra_dc *dc)
* DC_COM_CRC_CHECKSUM_LATCHED is available after VBLANK */
mdelay(TEGRA_CRC_LATCHED_DELAY);
+ mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
crc = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM_LATCHED);
+ tegra_dc_release_dc_out(dc);
+ mutex_unlock(&dc->lock);
crc_error:
return crc;
}
@@ -848,6 +873,36 @@ static inline void enable_dc_irq(unsigned int irq)
#endif
}
+void tegra_dc_get_fbvblank(struct tegra_dc *dc, struct fb_vblank *vblank)
+{
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ vblank->flags = FB_VBLANK_HAVE_VSYNC;
+}
+
+int tegra_dc_wait_for_vsync(struct tegra_dc *dc)
+{
+ int ret = -ENOTTY;
+
+ if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) || !dc->enabled)
+ return ret;
+
+ /*
+ * Logic is as follows
+ * a) Indicate we need a vblank.
+ * b) Wait for completion to be signalled from isr.
+ * c) Initialize completion for next iteration.
+ */
+
+ tegra_dc_hold_dc_out(dc);
+ dc->out->user_needs_vblank = true;
+
+ ret = wait_for_completion_interruptible(&dc->out->user_vblank_comp);
+ init_completion(&dc->out->user_vblank_comp);
+ tegra_dc_release_dc_out(dc);
+
+ return ret;
+}
+
static void tegra_dc_vblank(struct work_struct *work)
{
struct tegra_dc *dc = container_of(work, struct tegra_dc, vblank_work);
@@ -860,6 +915,7 @@ static void tegra_dc_vblank(struct work_struct *work)
return;
}
+ tegra_dc_hold_dc_out(dc);
/* use the new frame's bandwidth setting instead of max(current, new),
* skip this if we're using tegra_dc_one_shot_worker() */
if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE))
@@ -886,6 +942,7 @@ static void tegra_dc_vblank(struct work_struct *work)
if (!dc->vblank_ref_count)
tegra_dc_mask_interrupt(dc, V_BLANK_INT);
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
/* Do the actual brightness update outside of the mutex */
@@ -908,8 +965,8 @@ static void tegra_dc_one_shot_worker(struct work_struct *work)
/* memory client has gone idle */
tegra_dc_clear_bandwidth(dc);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_suspend(dc);
+ if (dc->out_ops->idle)
+ dc->out_ops->idle(dc);
mutex_unlock(&dc->lock);
}
@@ -962,9 +1019,9 @@ static void tegra_dc_underflow_handler(struct tegra_dc *dc)
#endif
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
if (dc->windows[i].underflows > 4) {
- printk("%s:dc in underflow state."
+ trace_printk("%s:window %c in underflow state."
" enable UF_LINE_FLUSH to clear up\n",
- __func__);
+ dc->ndev->name, (65 + i));
tegra_dc_writel(dc, UF_LINE_FLUSH,
DC_DISP_DISP_MISC_CONTROL);
tegra_dc_writel(dc, GENERAL_UPDATE,
@@ -996,6 +1053,13 @@ static void tegra_dc_underflow_handler(struct tegra_dc *dc)
#ifndef CONFIG_TEGRA_FPGA_PLATFORM
static void tegra_dc_one_shot_irq(struct tegra_dc *dc, unsigned long status)
{
+ /* pending user vblank, so wakeup */
+ if ((status & (V_BLANK_INT | MSF_INT)) &&
+ (dc->out->user_needs_vblank)) {
+ dc->out->user_needs_vblank = false;
+ complete(&dc->out->user_vblank_comp);
+ }
+
if (status & V_BLANK_INT) {
/* Sync up windows. */
tegra_dc_trigger_windows(dc);
@@ -1018,6 +1082,10 @@ static void tegra_dc_continuous_irq(struct tegra_dc *dc, unsigned long status)
queue_work(system_freezable_wq, &dc->vblank_work);
if (status & FRAME_END_INT) {
+ struct timespec tm = CURRENT_TIME;
+ dc->frame_end_timestamp = timespec_to_ns(&tm);
+ wake_up(&dc->timestamp_wq);
+
/* Mark the frame_end as complete. */
if (!completion_done(&dc->frame_end_complete))
complete(&dc->frame_end_complete);
@@ -1025,6 +1093,22 @@ static void tegra_dc_continuous_irq(struct tegra_dc *dc, unsigned long status)
tegra_dc_trigger_windows(dc);
}
}
+
+/* XXX: Not sure if we limit look ahead to 1 frame */
+bool tegra_dc_is_within_n_vsync(struct tegra_dc *dc, s64 ts)
+{
+ BUG_ON(!dc->frametime_ns);
+ return ((ts - dc->frame_end_timestamp) < dc->frametime_ns);
+}
+
+bool tegra_dc_does_vsync_separate(struct tegra_dc *dc, s64 new_ts, s64 old_ts)
+{
+ BUG_ON(!dc->frametime_ns);
+ return (((new_ts - old_ts) > dc->frametime_ns)
+ || (div_s64((new_ts - dc->frame_end_timestamp), dc->frametime_ns)
+ != div_s64((old_ts - dc->frame_end_timestamp),
+ dc->frametime_ns)));
+}
#endif
static irqreturn_t tegra_dc_irq(int irq, void *ptr)
@@ -1187,6 +1271,7 @@ static u32 get_syncpt(struct tegra_dc *dc, int idx)
static int tegra_dc_init(struct tegra_dc *dc)
{
int i;
+ int int_enable;
tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
if (dc->ndev->id == 0) {
@@ -1222,8 +1307,12 @@ static int tegra_dc_init(struct tegra_dc *dc)
tegra_dc_writel(dc, 0x00000000, DC_DISP_DISP_MISC_CONTROL);
#endif
/* enable interrupts for vblank, frame_end and underflows */
- tegra_dc_writel(dc, (FRAME_END_INT | V_BLANK_INT | ALL_UF_INT),
- DC_CMD_INT_ENABLE);
+ int_enable = (FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
+ /* for panels with one-shot mode enable tearing effect interrupt */
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ int_enable |= MSF_INT;
+
+ tegra_dc_writel(dc, int_enable, DC_CMD_INT_ENABLE);
tegra_dc_writel(dc, ALL_UF_INT, DC_CMD_INT_MASK);
tegra_dc_writel(dc, 0x00000000, DC_DISP_BORDER_COLOR);
@@ -1272,14 +1361,18 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc)
tegra_dc_clk_enable(dc);
/* do not accept interrupts during initialization */
- tegra_dc_writel(dc, 0, DC_CMD_INT_ENABLE);
tegra_dc_writel(dc, 0, DC_CMD_INT_MASK);
enable_dc_irq(dc->irq);
failed_init = tegra_dc_init(dc);
if (failed_init) {
- _tegra_dc_controller_disable(dc);
+ tegra_dc_writel(dc, 0, DC_CMD_INT_MASK);
+ disable_irq(dc->irq);
+ tegra_dc_clear_bandwidth(dc);
+ tegra_dc_clk_disable(dc);
+ if (dc->out && dc->out->disable)
+ dc->out->disable();
return false;
}
@@ -1367,19 +1460,14 @@ static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc)
static int _tegra_dc_set_default_videomode(struct tegra_dc *dc)
{
- return tegra_dc_set_fb_mode(dc, &tegra_dc_hdmi_fallback_mode, 0);
-}
-
-static bool _tegra_dc_enable(struct tegra_dc *dc)
-{
if (dc->mode.pclk == 0) {
switch (dc->out->type) {
case TEGRA_DC_OUT_HDMI:
/* DC enable called but no videomode is loaded.
Check if HDMI is connected, then set fallback mdoe */
if (tegra_dc_hpd(dc)) {
- if (_tegra_dc_set_default_videomode(dc))
- return false;
+ return tegra_dc_set_fb_mode(dc,
+ &tegra_dc_hdmi_fallback_mode, 0);
} else
return false;
@@ -1395,12 +1483,24 @@ static bool _tegra_dc_enable(struct tegra_dc *dc)
}
}
+ return false;
+}
+
+static bool _tegra_dc_enable(struct tegra_dc *dc)
+{
+ if (dc->mode.pclk == 0)
+ return false;
+
if (!dc->out)
return false;
tegra_dc_io_start(dc);
- return _tegra_dc_controller_enable(dc);
+ if (!_tegra_dc_controller_enable(dc)) {
+ tegra_dc_io_end(dc);
+ return false;
+ }
+ return true;
}
void tegra_dc_enable(struct tegra_dc *dc)
@@ -1505,8 +1605,20 @@ void tegra_dc_blank(struct tegra_dc *dc)
static void _tegra_dc_disable(struct tegra_dc *dc)
{
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
+ mutex_lock(&dc->one_shot_lock);
+ cancel_delayed_work_sync(&dc->one_shot_work);
+ }
+
+ tegra_dc_hold_dc_out(dc);
+
_tegra_dc_controller_disable(dc);
tegra_dc_io_end(dc);
+
+ tegra_dc_release_dc_out(dc);
+
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ mutex_unlock(&dc->one_shot_lock);
}
void tegra_dc_disable(struct tegra_dc *dc)
@@ -1516,16 +1628,9 @@ void tegra_dc_disable(struct tegra_dc *dc)
/* it's important that new underflow work isn't scheduled before the
* lock is acquired. */
cancel_delayed_work_sync(&dc->underflow_work);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
- mutex_lock(&dc->one_shot_lock);
- cancel_delayed_work_sync(&dc->one_shot_work);
- }
mutex_lock(&dc->lock);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
-
if (dc->enabled) {
dc->enabled = false;
@@ -1538,8 +1643,6 @@ void tegra_dc_disable(struct tegra_dc *dc)
#endif
mutex_unlock(&dc->lock);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
- mutex_unlock(&dc->one_shot_lock);
print_mode_info(dc, dc->mode);
}
@@ -1605,12 +1708,12 @@ static void tegra_dc_underflow_worker(struct work_struct *work)
to_delayed_work(work), struct tegra_dc, underflow_work);
mutex_lock(&dc->lock);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
+ tegra_dc_hold_dc_out(dc);
if (dc->enabled) {
tegra_dc_underflow_handler(dc);
}
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
}
@@ -1721,6 +1824,7 @@ static int tegra_dc_probe(struct nvhost_device *ndev,
mutex_init(&dc->one_shot_lock);
init_completion(&dc->frame_end_complete);
init_waitqueue_head(&dc->wq);
+ init_waitqueue_head(&dc->timestamp_wq);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
INIT_WORK(&dc->reset_work, tegra_dc_reset_worker);
#endif
@@ -1772,8 +1876,10 @@ static int tegra_dc_probe(struct nvhost_device *ndev,
}
mutex_lock(&dc->lock);
- if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED)
+ if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED) {
+ _tegra_dc_set_default_videomode(dc);
dc->enabled = _tegra_dc_enable(dc);
+ }
mutex_unlock(&dc->lock);
/* interrupt handler must be registered before tegra_fb_register() */
@@ -1789,7 +1895,7 @@ static int tegra_dc_probe(struct nvhost_device *ndev,
dev_info(&ndev->dev, "probed\n");
if (dc->pdata->fb) {
- if (dc->pdata->fb->bits_per_pixel == -1) {
+ if (dc->enabled && dc->pdata->fb->bits_per_pixel == -1) {
unsigned long fmt;
tegra_dc_writel(dc,
WINDOW_A_SELECT << dc->pdata->fb->win,
@@ -1921,8 +2027,10 @@ static int tegra_dc_resume(struct nvhost_device *ndev)
mutex_lock(&dc->lock);
dc->suspended = false;
- if (dc->enabled)
+ if (dc->enabled) {
+ _tegra_dc_set_default_videomode(dc);
_tegra_dc_enable(dc);
+ }
if (dc->out && dc->out->hotplug_init)
dc->out->hotplug_init();
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
index fb1243593587..75c3a2a29658 100644
--- a/drivers/video/tegra/dc/dc_priv.h
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -75,6 +75,12 @@ struct tegra_dc_out_ops {
void (*enable)(struct tegra_dc *dc);
/* disable output. dc clocks are on at this point */
void (*disable)(struct tegra_dc *dc);
+ /* hold output. keeps dc clocks on. */
+ void (*hold)(struct tegra_dc *dc);
+ /* release output. dc clocks may turn off after this. */
+ void (*release)(struct tegra_dc *dc);
+ /* idle routine of output. dc clocks may turn off after this. */
+ void (*idle)(struct tegra_dc *dc);
/* suspend output. dc clocks are on at this point */
void (*suspend)(struct tegra_dc *dc);
/* resume output. dc clocks are on at this point */
@@ -107,12 +113,14 @@ struct tegra_dc {
void *out_data;
struct tegra_dc_mode mode;
+ s64 frametime_ns;
struct tegra_dc_win windows[DC_N_WINDOWS];
struct tegra_dc_blend blend;
int n_windows;
wait_queue_head_t wq;
+ wait_queue_head_t timestamp_wq;
struct mutex lock;
struct mutex one_shot_lock;
@@ -157,6 +165,7 @@ struct tegra_dc {
struct delayed_work underflow_work;
u32 one_shot_delay_ms;
struct delayed_work one_shot_work;
+ s64 frame_end_timestamp;
};
#define print_mode_info(dc, mode) do { \
@@ -366,9 +375,17 @@ void tegra_dc_disable_crc(struct tegra_dc *dc);
void tegra_dc_set_out_pin_polars(struct tegra_dc *dc,
const struct tegra_dc_out_pin *pins,
const unsigned int n_pins);
-/* defined in dc.c, used in bandwidth.c */
+/* defined in dc.c, used in bandwidth.c and ext/dev.c */
unsigned int tegra_dc_has_multiple_dc(void);
+/* defined in dc.c, used in dsi.c */
+void tegra_dc_clk_enable(struct tegra_dc *dc);
+void tegra_dc_clk_disable(struct tegra_dc *dc);
+
+/* defined in dc.c, used in nvsd.c and dsi.c */
+void tegra_dc_hold_dc_out(struct tegra_dc *dc);
+void tegra_dc_release_dc_out(struct tegra_dc *dc);
+
/* defined in bandwidth.c, used in dc.c */
void tegra_dc_clear_bandwidth(struct tegra_dc *dc);
void tegra_dc_program_bandwidth(struct tegra_dc *dc, bool use_new);
diff --git a/drivers/video/tegra/dc/dc_sysfs.c b/drivers/video/tegra/dc/dc_sysfs.c
index bf27e963f233..09a8e2dbb5b1 100644
--- a/drivers/video/tegra/dc/dc_sysfs.c
+++ b/drivers/video/tegra/dc/dc_sysfs.c
@@ -313,6 +313,14 @@ static ssize_t nvdps_store(struct device *dev,
static DEVICE_ATTR(nvdps, S_IRUGO|S_IWUSR, nvdps_show, nvdps_store);
+static ssize_t smart_panel_show(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "1\n");
+}
+
+static DEVICE_ATTR(smart_panel, S_IRUGO, smart_panel_show, NULL);
+
void __devexit tegra_dc_remove_sysfs(struct device *dev)
{
struct nvhost_device *ndev = to_nvhost_device(dev);
@@ -332,6 +340,9 @@ void __devexit tegra_dc_remove_sysfs(struct device *dev)
if (sd_settings)
nvsd_remove_sysfs(dev);
+
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ device_remove_file(dev, &dev_attr_smart_panel);
}
void tegra_dc_create_sysfs(struct device *dev)
@@ -355,6 +366,9 @@ void tegra_dc_create_sysfs(struct device *dev)
if (sd_settings)
error |= nvsd_create_sysfs(dev);
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ error |= device_create_file(dev, &dev_attr_smart_panel);
+
if (error)
dev_err(&ndev->dev, "Failed to create sysfs attributes!\n");
}
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c
index 7ee9375f58f1..d3b1d40d535b 100644
--- a/drivers/video/tegra/dc/dsi.c
+++ b/drivers/video/tegra/dc/dsi.c
@@ -79,6 +79,8 @@
#define DSI_LP_OP_WRITE 0x1
#define DSI_LP_OP_READ 0x2
+#define DSI_HOST_IDLE_PERIOD 1000
+
static bool enable_read_debug;
module_param(enable_read_debug, bool, 0644);
MODULE_PARM_DESC(enable_read_debug,
@@ -129,6 +131,11 @@ struct tegra_dc_dsi_data {
bool ulpm;
bool enabled;
bool host_suspended;
+ struct mutex host_resume_lock;
+ struct delayed_work idle_work;
+ unsigned long idle_delay;
+ spinlock_t host_ref_lock;
+ u8 host_ref;
u8 driven_mode;
u8 controller_index;
@@ -294,6 +301,10 @@ const u32 init_reg[] = {
DSI_PKT_LEN_6_7,
};
+static int tegra_dsi_host_suspend(struct tegra_dc *dc);
+static int tegra_dsi_host_resume(struct tegra_dc *dc);
+static void tegra_dc_dsi_idle_work(struct work_struct *work);
+
inline unsigned long tegra_dsi_readl(struct tegra_dc_dsi_data *dsi, u32 reg)
{
unsigned long ret;
@@ -331,6 +342,7 @@ static int dbg_dsi_show(struct seq_file *s, void *unused)
DUMP_REG(DSI_CTXSW);
DUMP_REG(DSI_POWER_CONTROL);
DUMP_REG(DSI_INT_ENABLE);
+ DUMP_REG(DSI_HOST_DSI_CONTROL);
DUMP_REG(DSI_CONTROL);
DUMP_REG(DSI_SOL_DELAY);
DUMP_REG(DSI_MAX_THRESHOLD);
@@ -650,6 +662,13 @@ static void tegra_dsi_init_sw(struct tegra_dc *dc,
dsi->info.video_clock_mode = TEGRA_DSI_VIDEO_CLOCK_CONTINUOUS;
}
+ dsi->host_ref = 0;
+ dsi->host_suspended = false;
+ spin_lock_init(&dsi->host_ref_lock);
+ mutex_init(&dsi->host_resume_lock);
+ init_completion(&dc->out->user_vblank_comp);
+ INIT_DELAYED_WORK(&dsi->idle_work, tegra_dc_dsi_idle_work);
+ dsi->idle_delay = msecs_to_jiffies(DSI_HOST_IDLE_PERIOD);
}
#define SELECT_T_PHY(platform_t_phy_ns, default_phy, clk_ns, hw_inc) ( \
@@ -1341,9 +1360,38 @@ static void tegra_dsi_reset_underflow_overflow
}
}
+static void tegra_dsi_soft_reset(struct tegra_dc_dsi_data *dsi)
+{
+ u32 trigger;
+
+ tegra_dsi_writel(dsi,
+ DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE),
+ DSI_POWER_CONTROL);
+ /* stabilization delay */
+ udelay(300);
+
+ tegra_dsi_writel(dsi,
+ DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_ENABLE),
+ DSI_POWER_CONTROL);
+ /* stabilization delay */
+ udelay(300);
+
+ /* dsi HW does not clear host trigger bit automatically
+ * on dsi interface disable if host fifo is empty or in mid
+ * of host transmission
+ */
+ trigger = tegra_dsi_readl(dsi, DSI_TRIGGER);
+ if (trigger)
+ tegra_dsi_writel(dsi, 0x0, DSI_TRIGGER);
+}
+
static void tegra_dsi_stop_dc_stream(struct tegra_dc *dc,
struct tegra_dc_dsi_data *dsi)
{
+ /* Mask the MSF interrupt. */
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ tegra_dc_mask_interrupt(dc, MSF_INT);
+
tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
tegra_dc_writel(dc, 0, DC_DISP_DISP_WIN_OPTIONS);
tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
@@ -1359,13 +1407,13 @@ static void tegra_dsi_stop_dc_stream_at_frame_end(struct tegra_dc *dc,
long timeout;
u32 frame_period = DIV_ROUND_UP(S_TO_MS(1), dsi->info.refresh_rate);
- /* stop dc */
- tegra_dsi_stop_dc_stream(dc, dsi);
+ INIT_COMPLETION(dc->frame_end_complete);
- /* enable frame end interrupt */
+ /* unmask frame end interrupt */
val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
- val |= FRAME_END_INT;
- tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
+ tegra_dc_writel(dc, val | FRAME_END_INT, DC_CMD_INT_MASK);
+
+ tegra_dsi_stop_dc_stream(dc, dsi);
/* wait for frame_end completion.
* timeout is 2 frame duration to accomodate for
@@ -1375,9 +1423,14 @@ static void tegra_dsi_stop_dc_stream_at_frame_end(struct tegra_dc *dc,
&dc->frame_end_complete,
msecs_to_jiffies(2 * frame_period));
- /* disable frame end interrupt */
- val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
- val &= ~FRAME_END_INT;
+ /* give 2 line time to dsi HW to catch up
+ * with pixels sent by dc
+ */
+ udelay(50);
+
+ tegra_dsi_soft_reset(dsi);
+
+ /* reinstate interrupt mask */
tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
if (timeout == 0)
@@ -1419,6 +1472,9 @@ static void tegra_dsi_start_dc_stream(struct tegra_dc *dc,
tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
tegra_dc_writel(dc, GENERAL_ACT_REQ | NC_HOST_TRIG,
DC_CMD_STATE_CONTROL);
+
+ /* Unmask the MSF interrupt. */
+ tegra_dc_unmask_interrupt(dc, MSF_INT);
} else {
/* set continuous mode */
tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY,
@@ -1559,7 +1615,8 @@ static void tegra_dsi_set_control_reg_lp(struct tegra_dc_dsi_data *dsi)
dsi->status.vtype = DSI_VIDEO_TYPE_NOT_INIT;
}
-static void tegra_dsi_set_control_reg_hs(struct tegra_dc_dsi_data *dsi)
+static void tegra_dsi_set_control_reg_hs(struct tegra_dc_dsi_data *dsi,
+ u8 driven_mode)
{
u32 dsi_control;
u32 host_dsi_control;
@@ -1571,7 +1628,7 @@ static void tegra_dsi_set_control_reg_hs(struct tegra_dc_dsi_data *dsi)
max_threshold = 0;
dcs_cmd = 0;
- if (dsi->driven_mode == TEGRA_DSI_DRIVEN_BY_HOST) {
+ if (driven_mode == TEGRA_DSI_DRIVEN_BY_HOST) {
dsi_control |= DSI_CTRL_HOST_DRIVEN;
host_dsi_control |= HOST_DSI_CTRL_HOST_DRIVEN;
max_threshold =
@@ -1583,17 +1640,19 @@ static void tegra_dsi_set_control_reg_hs(struct tegra_dc_dsi_data *dsi)
max_threshold =
DSI_MAX_THRESHOLD_MAX_THRESHOLD(DSI_VIDEO_FIFO_DEPTH);
dsi->status.driven = DSI_DRIVEN_MODE_DC;
- }
- if (dsi->info.video_data_type == TEGRA_DSI_VIDEO_TYPE_COMMAND_MODE) {
- dsi_control |= DSI_CTRL_CMD_MODE;
- dcs_cmd = DSI_DCS_CMDS_LT5_DCS_CMD(DSI_WRITE_MEMORY_START)|
- DSI_DCS_CMDS_LT3_DCS_CMD(DSI_WRITE_MEMORY_CONTINUE);
- dsi->status.vtype = DSI_VIDEO_TYPE_CMD_MODE;
-
- } else {
- dsi_control |= DSI_CTRL_VIDEO_MODE;
- dsi->status.vtype = DSI_VIDEO_TYPE_VIDEO_MODE;
+ if (dsi->info.video_data_type ==
+ TEGRA_DSI_VIDEO_TYPE_COMMAND_MODE) {
+ dsi_control |= DSI_CTRL_CMD_MODE;
+ dcs_cmd = DSI_DCS_CMDS_LT5_DCS_CMD(
+ DSI_WRITE_MEMORY_START)|
+ DSI_DCS_CMDS_LT3_DCS_CMD(
+ DSI_WRITE_MEMORY_CONTINUE);
+ dsi->status.vtype = DSI_VIDEO_TYPE_CMD_MODE;
+ } else {
+ dsi_control |= DSI_CTRL_VIDEO_MODE;
+ dsi->status.vtype = DSI_VIDEO_TYPE_VIDEO_MODE;
+ }
}
tegra_dsi_writel(dsi, max_threshold, DSI_MAX_THRESHOLD);
@@ -1734,6 +1793,7 @@ static int tegra_dsi_set_to_lp_mode(struct tegra_dc *dc,
dsi->status.lphs = DSI_LPHS_IN_LP_MODE;
dsi->status.lp_op = lp_op;
+ dsi->driven_mode = TEGRA_DSI_DRIVEN_BY_HOST;
success:
err = 0;
fail:
@@ -1741,7 +1801,8 @@ fail:
}
static int tegra_dsi_set_to_hs_mode(struct tegra_dc *dc,
- struct tegra_dc_dsi_data *dsi)
+ struct tegra_dc_dsi_data *dsi,
+ u8 driven_mode)
{
int err;
@@ -1750,9 +1811,12 @@ static int tegra_dsi_set_to_hs_mode(struct tegra_dc *dc,
goto fail;
}
- if (dsi->status.lphs == DSI_LPHS_IN_HS_MODE)
+ if (dsi->status.lphs == DSI_LPHS_IN_HS_MODE &&
+ dsi->driven_mode == driven_mode)
goto success;
+ dsi->driven_mode = driven_mode;
+
if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE)
tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi);
@@ -1767,14 +1831,14 @@ static int tegra_dsi_set_to_hs_mode(struct tegra_dc *dc,
tegra_dsi_set_phy_timing(dsi, DSI_LPHS_IN_HS_MODE);
- if (dsi->driven_mode == TEGRA_DSI_DRIVEN_BY_DC) {
+ if (driven_mode == TEGRA_DSI_DRIVEN_BY_DC) {
tegra_dsi_set_pkt_seq(dc, dsi);
tegra_dsi_set_pkt_length(dc, dsi);
tegra_dsi_set_sol_delay(dc, dsi);
tegra_dsi_set_dc_clk(dc, dsi);
}
- tegra_dsi_set_control_reg_hs(dsi);
+ tegra_dsi_set_control_reg_hs(dsi, driven_mode);
if (dsi->status.clk_out == DSI_PHYCLK_OUT_DIS ||
dsi->info.enable_hs_clock_on_lp_cmd_mode)
@@ -1845,35 +1909,6 @@ fail:
return (err < 0 ? true : false);
}
-static void tegra_dsi_soft_reset(struct tegra_dc_dsi_data *dsi)
-{
- u32 trigger;
- u32 status;
-
- tegra_dsi_writel(dsi,
- DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE),
- DSI_POWER_CONTROL);
- /* stabilization delay */
- udelay(300);
-
- tegra_dsi_writel(dsi,
- DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_ENABLE),
- DSI_POWER_CONTROL);
- /* stabilization delay */
- udelay(300);
-
- /* dsi HW does not clear host trigger bit automatically
- * on dsi interface disable if host fifo is empty
- */
- trigger = tegra_dsi_readl(dsi, DSI_TRIGGER);
- status = tegra_dsi_readl(dsi, DSI_STATUS);
- if (trigger & DSI_TRIGGER_HOST_TRIGGER(0x1) &&
- status & DSI_STATUS_IDLE(0x1)) {
- trigger &= ~(DSI_TRIGGER_HOST_TRIGGER(0x1));
- tegra_dsi_writel(dsi, trigger, DSI_TRIGGER);
- }
-}
-
static void tegra_dsi_reset_read_count(struct tegra_dc_dsi_data *dsi)
{
u32 val;
@@ -1892,49 +1927,42 @@ static struct dsi_status *tegra_dsi_save_state_switch_to_host_cmd_mode(
struct tegra_dc *dc,
u8 lp_op)
{
- struct dsi_status *init_status;
+ struct dsi_status *init_status = NULL;
int err;
+ if (dsi->status.init != DSI_MODULE_INIT ||
+ dsi->status.lphs == DSI_LPHS_NOT_INIT) {
+ err = -EPERM;
+ goto fail;
+ }
+
init_status = kzalloc(sizeof(*init_status), GFP_KERNEL);
if (!init_status)
return ERR_PTR(-ENOMEM);
*init_status = dsi->status;
- if (dsi->status.lphs == DSI_LPHS_IN_HS_MODE) {
- if (dsi->status.driven == DSI_DRIVEN_MODE_DC) {
- if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE)
- tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi);
- dsi->driven_mode = TEGRA_DSI_DRIVEN_BY_HOST;
- if (dsi->info.hs_cmd_mode_supported) {
- err = tegra_dsi_set_to_hs_mode(dc, dsi);
- if (err < 0) {
- dev_err(&dc->ndev->dev,
- "Switch to HS host mode failed\n");
- goto fail;
- }
- }
- }
- if (!dsi->info.hs_cmd_mode_supported) {
- err =
- tegra_dsi_set_to_lp_mode(dc, dsi, lp_op);
- if (err < 0) {
- dev_err(&dc->ndev->dev,
- "DSI failed to go to LP mode\n");
- goto fail;
- }
- }
- } else if (dsi->status.lphs == DSI_LPHS_IN_LP_MODE) {
- if (dsi->status.lp_op != lp_op) {
- err = tegra_dsi_set_to_lp_mode(dc, dsi, lp_op);
- if (err < 0) {
- dev_err(&dc->ndev->dev,
- "DSI failed to go to LP mode\n");
- goto fail;
- }
+ if (dsi->info.hs_cmd_mode_supported) {
+ err = tegra_dsi_set_to_hs_mode(dc, dsi,
+ TEGRA_DSI_DRIVEN_BY_HOST);
+ if (err < 0) {
+ dev_err(&dc->ndev->dev,
+ "Switch to HS host mode failed\n");
+ goto fail;
}
+
+ goto success;
}
+ if (dsi->status.lp_op != lp_op) {
+ err = tegra_dsi_set_to_lp_mode(dc, dsi, lp_op);
+ if (err < 0) {
+ dev_err(&dc->ndev->dev,
+ "DSI failed to go to LP mode\n");
+ goto fail;
+ }
+ }
+success:
return init_status;
fail:
kfree(init_status);
@@ -1948,6 +1976,7 @@ static struct dsi_status *tegra_dsi_prepare_host_transmission(
{
int err = 0;
struct dsi_status *init_status;
+ bool restart_dc_stream = false;
if (dsi->status.init != DSI_MODULE_INIT ||
dsi->ulpm) {
@@ -1955,12 +1984,13 @@ static struct dsi_status *tegra_dsi_prepare_host_transmission(
goto fail;
}
+ if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE) {
+ restart_dc_stream = true;
+ tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi);
+ }
+
if (tegra_dsi_host_busy(dsi)) {
tegra_dsi_soft_reset(dsi);
-
- /* WAR to stop host write in middle */
- tegra_dsi_writel(dsi, TEGRA_DSI_DISABLE, DSI_TRIGGER);
-
if (tegra_dsi_host_busy(dsi)) {
err = -EBUSY;
dev_err(&dc->ndev->dev, "DSI host busy\n");
@@ -1987,6 +2017,9 @@ static struct dsi_status *tegra_dsi_prepare_host_transmission(
goto fail;
}
+ if (restart_dc_stream)
+ init_status->dc_stream = DSI_DC_STREAM_ENABLE;
+
return init_status;
fail:
return ERR_PTR(err);
@@ -1996,50 +2029,30 @@ static int tegra_dsi_restore_state(struct tegra_dc *dc,
struct tegra_dc_dsi_data *dsi,
struct dsi_status *init_status)
{
- bool switch_back_to_dc_mode = false;
- bool switch_back_to_hs_mode = false;
- bool restart_dc_stream;
int err = 0;
- switch_back_to_dc_mode = (dsi->status.driven ==
- DSI_DRIVEN_MODE_HOST &&
- init_status->driven ==
- DSI_DRIVEN_MODE_DC);
- switch_back_to_hs_mode = (dsi->status.lphs ==
- DSI_LPHS_IN_LP_MODE &&
- init_status->lphs ==
- DSI_LPHS_IN_HS_MODE);
- restart_dc_stream = (dsi->status.dc_stream ==
- DSI_DC_STREAM_DISABLE &&
- init_status->dc_stream ==
- DSI_DC_STREAM_ENABLE);
-
- if (dsi->status.lphs == DSI_LPHS_IN_LP_MODE &&
- init_status->lphs == DSI_LPHS_IN_LP_MODE) {
- if (dsi->status.lp_op != init_status->lp_op) {
- err =
- tegra_dsi_set_to_lp_mode(dc, dsi, init_status->lp_op);
- if (err < 0) {
- dev_err(&dc->ndev->dev,
- "Failed to config LP mode\n");
- goto fail;
- }
+ if (init_status->lphs == DSI_LPHS_IN_LP_MODE) {
+ err = tegra_dsi_set_to_lp_mode(dc, dsi, init_status->lp_op);
+ if (err < 0) {
+ dev_err(&dc->ndev->dev,
+ "Failed to config LP mode\n");
+ goto fail;
}
goto success;
}
- if (switch_back_to_dc_mode)
- dsi->driven_mode = TEGRA_DSI_DRIVEN_BY_DC;
- if (switch_back_to_dc_mode || switch_back_to_hs_mode) {
- err = tegra_dsi_set_to_hs_mode(dc, dsi);
+ if (init_status->lphs == DSI_LPHS_IN_HS_MODE) {
+ u8 driven = (init_status->driven == DSI_DRIVEN_MODE_DC) ?
+ TEGRA_DSI_DRIVEN_BY_DC : TEGRA_DSI_DRIVEN_BY_HOST;
+ err = tegra_dsi_set_to_hs_mode(dc, dsi, driven);
if (err < 0) {
dev_err(&dc->ndev->dev, "Failed to config HS mode\n");
goto fail;
}
}
- if (restart_dc_stream)
- tegra_dsi_start_dc_stream(dc, dsi);
+ if (init_status->dc_stream == DSI_DC_STREAM_ENABLE)
+ tegra_dsi_start_dc_stream(dc, dsi);
success:
fail:
kfree(init_status);
@@ -2081,7 +2094,6 @@ static int _tegra_dsi_write_data(struct tegra_dc_dsi_data *dsi,
u8 *pdata, u8 data_id, u16 data_len)
{
u8 virtual_channel;
- u8 *pval;
u32 val;
int err;
@@ -2104,10 +2116,9 @@ static int _tegra_dsi_write_data(struct tegra_dc_dsi_data *dsi,
pdata += 4;
} else {
val = 0;
- pval = (u8 *) &val;
- do
- *pval++ = *pdata++;
- while (--data_len);
+ memcpy(&val, pdata, data_len);
+ pdata += data_len;
+ data_len = 0;
}
tegra_dsi_writel(dsi, val, DSI_WR_DATA);
}
@@ -2120,6 +2131,49 @@ static int _tegra_dsi_write_data(struct tegra_dc_dsi_data *dsi,
return err;
}
+static void tegra_dc_dsi_hold_host(struct tegra_dc *dc)
+{
+ struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
+
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE) {
+ spin_lock(&dsi->host_ref_lock);
+ dsi->host_ref++;
+ spin_unlock(&dsi->host_ref_lock);
+ tegra_dsi_host_resume(dc);
+
+ /*
+ * Take an extra refrence to count for the clk_disable in
+ * tegra_dc_release_host.
+ */
+ clk_enable(dc->clk);
+ }
+}
+
+static void tegra_dc_dsi_release_host(struct tegra_dc *dc)
+{
+ struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE) {
+ clk_disable(dc->clk);
+ spin_lock(&dsi->host_ref_lock);
+ dsi->host_ref--;
+
+ if (!dsi->host_ref &&
+ (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE))
+ schedule_delayed_work(&dsi->idle_work, dsi->idle_delay);
+
+ spin_unlock(&dsi->host_ref_lock);
+ }
+}
+
+static void tegra_dc_dsi_idle_work(struct work_struct *work)
+{
+ struct tegra_dc_dsi_data *dsi = container_of(
+ to_delayed_work(work), struct tegra_dc_dsi_data, idle_work);
+
+ if (dsi->dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
+ tegra_dsi_host_suspend(dsi->dc);
+}
+
int tegra_dsi_write_data(struct tegra_dc *dc,
struct tegra_dc_dsi_data *dsi,
u8 *pdata, u8 data_id, u16 data_len)
@@ -2143,6 +2197,7 @@ fail:
if (err < 0)
dev_err(&dc->ndev->dev, "Failed to restore prev state\n");
tegra_dc_io_end(dc);
+
return err;
}
EXPORT_SYMBOL(tegra_dsi_write_data);
@@ -2174,7 +2229,7 @@ static int tegra_dsi_send_panel_cmd(struct tegra_dc *dc,
return err;
}
-static u8 get_8bit_ecc(u32 header)
+static u8 tegra_dsi_ecc(u32 header)
{
char ecc_parity[24] = {
0x07, 0x0b, 0x0d, 0x0e, 0x13, 0x15, 0x16, 0x19,
@@ -2191,75 +2246,158 @@ static u8 get_8bit_ecc(u32 header)
return ecc_byte;
}
-/* This function is written to send DCS short write (1 parameter) only.
- * This means the cmd will contain only 1 byte of index and 1 byte of value.
- * The data type ID is fixed at 0x15 and the ECC is calculated based on the
- * data in pdata.
- * The command will be sent by hardware every frame.
- * pdata should contain both the index + value for each cmd.
- * data_len will be the total number of bytes in pdata.
- */
-int tegra_dsi_send_panel_short_cmd(struct tegra_dc *dc, u8 *pdata, u8 data_len)
+static u16 tegra_dsi_cs(char *pdata, u16 data_len)
{
- u8 ecc8bits = 0, data_len_orig = 0;
- u32 val = 0, pkthdr = 0;
- int err = 0, count = 0;
- struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
+ u16 byte_cnt;
+ u8 bit_cnt;
+ char curr_byte;
+ u16 crc = 0xFFFF;
+ u16 poly = 0x8408;
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
+ if (data_len > 0) {
+ for (byte_cnt = 0; byte_cnt < data_len; byte_cnt++) {
+ curr_byte = pdata[byte_cnt];
+ for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
+ if (((crc & 0x0001 ) ^
+ (curr_byte & 0x0001)) > 0)
+ crc = ((crc >> 1) & 0x7FFF) ^ poly;
+ else
+ crc = (crc >> 1) & 0x7FFF;
- data_len_orig = data_len;
- if (pdata != NULL) {
- while (data_len) {
- if (data_len >= 2) {
- pkthdr = (CMD_SHORTW |
- (((u16 *)pdata)[0]) << 8 | 0x00 << 24);
- ecc8bits = get_8bit_ecc(pkthdr);
- val = (pkthdr | (ecc8bits << 24));
- data_len -= 2;
- pdata += 2;
- count++;
+ curr_byte = (curr_byte >> 1 ) & 0x7F;
}
- switch (count) {
- case 1:
- tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_0);
- break;
- case 2:
- tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_1);
- break;
- case 3:
- tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_2);
- break;
- case 4:
- tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_3);
- break;
- case 5:
- tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_4);
- break;
- case 6:
- tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_5);
- break;
- case 7:
- tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_6);
- break;
- case 8:
- tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_7);
- break;
- default:
- err = 1;
- break;
+ }
+ }
+ return crc;
+}
+
+static int tegra_dsi_dcs_pkt_seq_ctrl_init(struct tegra_dc_dsi_data *dsi,
+ struct tegra_dsi_cmd *cmd)
+{
+ u8 virtual_channel;
+ u32 val;
+ u16 data_len = cmd->sp_len_dly.data_len;
+ u8 seq_ctrl_reg = 0;
+
+ virtual_channel = dsi->info.virtual_channel <<
+ DSI_VIR_CHANNEL_BIT_POSITION;
+
+ val = (virtual_channel | cmd->data_id) << 0 |
+ data_len << 8;
+
+ val |= tegra_dsi_ecc(val) << 24;
+
+ tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_0 + seq_ctrl_reg++);
+
+ /* if pdata != NULL, pkt type is long pkt */
+ if (cmd->pdata != NULL) {
+ u8 *pdata;
+ u8 *pdata_mem;
+ /* allocate memory for pdata + 2 bytes checksum */
+ pdata_mem = kzalloc(sizeof(u8) * data_len + 2, GFP_KERNEL);
+ if (!pdata_mem) {
+ dev_err(&dsi->dc->ndev->dev, "dsi: memory err\n");
+ tegra_dsi_soft_reset(dsi);
+ return -ENOMEM;
+ }
+
+ memcpy(pdata_mem, cmd->pdata, data_len);
+ pdata = pdata_mem;
+ *((u16 *)(pdata + data_len)) = tegra_dsi_cs(pdata, data_len);
+
+ /* data_len = length of pdata + 2 byte checksum */
+ data_len += 2;
+
+ while (data_len) {
+ if (data_len >= 4) {
+ val = ((u32 *) pdata)[0];
+ data_len -= 4;
+ pdata += 4;
+ } else {
+ val = 0;
+ memcpy(&val, pdata, data_len);
+ pdata += data_len;
+ data_len = 0;
}
+ tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_0 +
+ seq_ctrl_reg++);
}
+ kfree(pdata_mem);
}
- val = DSI_INIT_SEQ_CONTROL_DSI_FRAME_INIT_BYTE_COUNT(data_len_orig * 2)
- | DSI_INIT_SEQ_CONTROL_DSI_SEND_INIT_SEQUENCE(1);
+ return 0;
+}
+
+int tegra_dsi_start_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi,
+ struct tegra_dsi_cmd *cmd)
+{
+#define PKT_HEADER_LEN_BYTE 4
+#define CHECKSUM_LEN_BYTE 2
+
+ int err = 0;
+ u32 val;
+ u16 tot_pkt_len = PKT_HEADER_LEN_BYTE;
+ struct tegra_dc *dc = dsi->dc;
+
+ if (cmd->cmd_type != TEGRA_DSI_PACKET_CMD)
+ return -EINVAL;
+
+ mutex_lock(&dsi->lock);
+ tegra_dc_dsi_hold_host(dc);
+
+ tegra_dc_io_start(dc);
+
+
+ err = tegra_dsi_dcs_pkt_seq_ctrl_init(dsi, cmd);
+ if (err < 0) {
+ dev_err(&dsi->dc->ndev->dev,
+ "dsi: dcs pkt seq ctrl init failed\n");
+ goto fail;
+ }
+
+ if (cmd->pdata) {
+ u16 data_len = cmd->sp_len_dly.data_len;
+ tot_pkt_len += data_len + CHECKSUM_LEN_BYTE;
+ }
+
+ val = DSI_INIT_SEQ_CONTROL_DSI_FRAME_INIT_BYTE_COUNT(tot_pkt_len) |
+ DSI_INIT_SEQ_CONTROL_DSI_SEND_INIT_SEQUENCE(
+ TEGRA_DSI_ENABLE);
tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_CONTROL);
+fail:
+ tegra_dc_io_end(dc);
+ tegra_dc_dsi_release_host(dc);
+ mutex_unlock(&dsi->lock);
return err;
+
+#undef PKT_HEADER_LEN_BYTE
+#undef CHECKSUM_LEN_BYTE
}
-EXPORT_SYMBOL(tegra_dsi_send_panel_short_cmd);
+EXPORT_SYMBOL(tegra_dsi_start_host_cmd_v_blank_dcs);
+
+void tegra_dsi_stop_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi)
+{
+ struct tegra_dc *dc = dsi->dc;
+ u32 cnt;
+
+ mutex_lock(&dsi->lock);
+ tegra_dc_dsi_hold_host(dc);
+
+ tegra_dc_io_start(dc);
+
+ tegra_dsi_writel(dsi, TEGRA_DSI_DISABLE, DSI_INIT_SEQ_CONTROL);
+
+ /* clear seq data registers */
+ for (cnt = 0; cnt < 8; cnt++)
+ tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + cnt);
+
+ tegra_dc_io_end(dc);
+
+ tegra_dc_dsi_release_host(dc);
+ mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(tegra_dsi_stop_host_cmd_v_blank_dcs);
static int tegra_dsi_bta(struct tegra_dc_dsi_data *dsi)
{
@@ -2429,6 +2567,7 @@ int tegra_dsi_read_data(struct tegra_dc *dc,
int err = 0;
struct dsi_status *init_status;
+ mutex_lock(&dsi->lock);
tegra_dc_io_start(dc);
init_status = tegra_dsi_prepare_host_transmission(
@@ -2487,6 +2626,7 @@ fail:
if (err < 0)
dev_err(&dc->ndev->dev, "Failed to restore prev state\n");
tegra_dc_io_end(dc);
+ mutex_unlock(&dsi->lock);
return err;
}
EXPORT_SYMBOL(tegra_dsi_read_data);
@@ -2625,7 +2765,8 @@ static void tegra_dsi_send_dc_frames(struct tegra_dc *dc,
bool switch_to_lp = (dsi->status.lphs == DSI_LPHS_IN_LP_MODE);
if (dsi->status.lphs != DSI_LPHS_IN_HS_MODE) {
- err = tegra_dsi_set_to_hs_mode(dc, dsi);
+ err = tegra_dsi_set_to_hs_mode(dc, dsi,
+ TEGRA_DSI_DRIVEN_BY_DC);
if (err < 0) {
dev_err(&dc->ndev->dev,
"Switch to HS host mode failed\n");
@@ -2668,11 +2809,10 @@ static void tegra_dc_dsi_enable(struct tegra_dc *dc)
int err;
u32 val;
- tegra_dc_io_start(dc);
mutex_lock(&dsi->lock);
+ tegra_dc_dsi_hold_host(dc);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
+ tegra_dc_io_start(dc);
/* Stop DC stream before configuring DSI registers
* to avoid visible glitches on panel during transition
* from bootloader to kernel driver
@@ -2771,7 +2911,8 @@ static void tegra_dc_dsi_enable(struct tegra_dc *dc)
goto fail;
}
- err = tegra_dsi_set_to_hs_mode(dc, dsi);
+ err = tegra_dsi_set_to_hs_mode(dc, dsi,
+ TEGRA_DSI_DRIVEN_BY_DC);
if (err < 0) {
dev_err(&dc->ndev->dev,
"dsi: not able to set to hs mode\n");
@@ -2784,8 +2925,9 @@ static void tegra_dc_dsi_enable(struct tegra_dc *dc)
if (dsi->status.driven == DSI_DRIVEN_MODE_DC)
tegra_dsi_start_dc_stream(dc, dsi);
fail:
- mutex_unlock(&dsi->lock);
tegra_dc_io_end(dc);
+ tegra_dc_dsi_release_host(dc);
+ mutex_unlock(&dsi->lock);
}
static void _tegra_dc_dsi_init(struct tegra_dc *dc)
@@ -3179,8 +3321,7 @@ fail:
return err;
}
-
-int tegra_dsi_host_suspend(struct tegra_dc *dc)
+static int tegra_dsi_host_suspend(struct tegra_dc *dc)
{
int err = 0;
struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
@@ -3188,6 +3329,10 @@ int tegra_dsi_host_suspend(struct tegra_dc *dc)
if (dsi->host_suspended)
return 0;
+ BUG_ON(!tegra_is_clk_enabled(dc->clk));
+ tegra_dc_io_start(dc);
+ dsi->host_suspended = true;
+
tegra_dsi_stop_dc_stream(dc, dsi);
err = tegra_dsi_deep_sleep(dc, dsi, dsi->info.suspend_aggr);
@@ -3195,21 +3340,26 @@ int tegra_dsi_host_suspend(struct tegra_dc *dc)
dev_err(&dc->ndev->dev,
"DSI failed to enter deep sleep\n");
- dsi->host_suspended = true;
+ tegra_dc_clk_disable(dc);
+ tegra_dc_io_end(dc);
return err;
}
-
-int tegra_dsi_host_resume(struct tegra_dc *dc)
+static int tegra_dsi_host_resume(struct tegra_dc *dc)
{
int val = 0;
int err = 0;
struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
- if (!dsi->host_suspended)
+ mutex_lock(&dsi->host_resume_lock);
+ cancel_delayed_work_sync(&dsi->idle_work);
+ if (!dsi->host_suspended) {
+ mutex_unlock(&dsi->host_resume_lock);
return 0;
+ }
+ tegra_dc_clk_enable(dc);
switch (dsi->info.suspend_aggr) {
case DSI_HOST_SUSPEND_LV0:
tegra_dsi_clk_enable(dsi);
@@ -3254,9 +3404,11 @@ int tegra_dsi_host_resume(struct tegra_dc *dc)
"is not supported.\n");
}
+ tegra_dsi_start_dc_stream(dc, dsi);
+
dsi->enabled = true;
dsi->host_suspended = false;
- tegra_dsi_start_dc_stream(dc, dsi);
+ mutex_unlock(&dsi->host_resume_lock);
fail:
return err;
}
@@ -3298,7 +3450,6 @@ static void tegra_dc_dsi_disable(struct tegra_dc *dc)
}
}
}
-
fail:
mutex_unlock(&dsi->lock);
tegra_dc_io_end(dc);
@@ -3350,6 +3501,8 @@ struct tegra_dc_out_ops tegra_dc_dsi_ops = {
.destroy = tegra_dc_dsi_destroy,
.enable = tegra_dc_dsi_enable,
.disable = tegra_dc_dsi_disable,
+ .hold = tegra_dc_dsi_hold_host,
+ .release = tegra_dc_dsi_release_host,
#ifdef CONFIG_PM
.suspend = tegra_dc_dsi_suspend,
.resume = tegra_dc_dsi_resume,
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index f9c76f8f0d0d..88273e26c51c 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -56,6 +56,7 @@ struct tegra_dc_ext_flip_data {
struct tegra_dc_ext *ext;
struct work_struct work;
struct tegra_dc_ext_flip_win win[DC_N_WINDOWS];
+ struct list_head timestamp_node;
};
int tegra_dc_ext_get_num_outputs(void)
@@ -207,6 +208,7 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
{
int err = 0;
struct tegra_dc_ext_win *ext_win = &ext->win[win->idx];
+ s64 timestamp_ns;
if (flip_win->handle[TEGRA_DC_Y] == NULL) {
win->flags = 0;
@@ -270,9 +272,56 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
msecs_to_jiffies(500), NULL);
}
+#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
+ timestamp_ns = timespec_to_ns(&flip_win->attr.timestamp);
+
+ if (timestamp_ns) {
+ /* XXX: Should timestamping be overridden by "no_vsync" flag */
+ tegra_dc_config_frame_end_intr(win->dc, true);
+ trace_printk("%s:Before timestamp wait\n", win->dc->ndev->name);
+ err = wait_event_interruptible(win->dc->timestamp_wq,
+ tegra_dc_is_within_n_vsync(win->dc, timestamp_ns));
+ trace_printk("%s:After timestamp wait\n", win->dc->ndev->name);
+ tegra_dc_config_frame_end_intr(win->dc, false);
+ }
+#endif
+ return err;
+}
+
+static void (*flip_callback)(void);
+static spinlock_t flip_callback_lock;
+static bool init_tegra_dc_flip_callback_called;
+
+static int __init init_tegra_dc_flip_callback(void)
+{
+ spin_lock_init(&flip_callback_lock);
+ init_tegra_dc_flip_callback_called = true;
+ return 0;
+}
+
+pure_initcall(init_tegra_dc_flip_callback);
+
+int tegra_dc_set_flip_callback(void (*callback)(void))
+{
+ WARN_ON(!init_tegra_dc_flip_callback_called);
+
+ spin_lock(&flip_callback_lock);
+ flip_callback = callback;
+ spin_unlock(&flip_callback_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(tegra_dc_set_flip_callback);
+
+int tegra_dc_unset_flip_callback()
+{
+ spin_lock(&flip_callback_lock);
+ flip_callback = NULL;
+ spin_unlock(&flip_callback_lock);
return 0;
}
+EXPORT_SYMBOL(tegra_dc_unset_flip_callback);
static void tegra_dc_ext_flip_worker(struct work_struct *work)
{
@@ -288,9 +337,11 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
for (i = 0; i < DC_N_WINDOWS; i++) {
struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
- int index = flip_win->attr.index;
+ int j = 0, index = flip_win->attr.index;
struct tegra_dc_win *win;
struct tegra_dc_ext_win *ext_win;
+ struct tegra_dc_ext_flip_data *temp = NULL;
+ s64 head_timestamp = 0;
if (index < 0)
continue;
@@ -302,6 +353,31 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
(flip_win->attr.flags & TEGRA_DC_EXT_FLIP_FLAG_CURSOR))
skip_flip = true;
+ mutex_lock(&ext_win->queue_lock);
+ list_for_each_entry(temp, &ext_win->timestamp_queue,
+ timestamp_node) {
+ if (j == 0) {
+ if (unlikely(temp != data))
+ dev_err(&win->dc->ndev->dev,
+ "work queue did NOT dequeue head!!!");
+ else
+ head_timestamp =
+ timespec_to_ns(&flip_win->attr.timestamp);
+ } else {
+ s64 timestamp =
+ timespec_to_ns(&temp->win[i].attr.timestamp);
+
+ skip_flip = !tegra_dc_does_vsync_separate(ext->dc,
+ timestamp, head_timestamp);
+ /* Look ahead only one flip */
+ break;
+ }
+ j++;
+ }
+ if (!list_empty(&ext_win->timestamp_queue))
+ list_del(&data->timestamp_node);
+ mutex_unlock(&ext_win->queue_lock);
+
if (win->flags & TEGRA_WIN_FLAG_ENABLED) {
int j;
for (j = 0; j < TEGRA_DC_NUM_PLANES; j++) {
@@ -327,17 +403,23 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
tegra_dc_update_windows(wins, nr_win);
/* TODO: implement swapinterval here */
tegra_dc_sync_windows(wins, nr_win);
- }
+ if (!tegra_dc_has_multiple_dc()) {
+ spin_lock(&flip_callback_lock);
+ if (flip_callback)
+ flip_callback();
+ spin_unlock(&flip_callback_lock);
+ }
- for (i = 0; i < DC_N_WINDOWS; i++) {
- struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
- int index = flip_win->attr.index;
+ for (i = 0; i < DC_N_WINDOWS; i++) {
+ struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
+ int index = flip_win->attr.index;
- if (index < 0)
- continue;
+ if (index < 0)
+ continue;
- tegra_dc_incr_syncpt_min(ext->dc, index,
- flip_win->syncpt_max);
+ tegra_dc_incr_syncpt_min(ext->dc, index,
+ flip_win->syncpt_max);
+ }
}
/* unpin and deref previous front buffers */
@@ -449,6 +531,7 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
struct tegra_dc_ext_flip_data *data;
int work_index = -1;
int i, ret = 0;
+ bool has_timestamp = false;
#ifdef CONFIG_ANDROID
int index_check[DC_N_WINDOWS] = {0, };
@@ -489,6 +572,8 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
int index = args->win[i].index;
memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr));
+ if (timespec_to_ns(&flip_win->attr.timestamp))
+ has_timestamp = true;
if (index < 0)
continue;
@@ -563,6 +648,11 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
ret = -EINVAL;
goto unlock;
}
+ if (has_timestamp) {
+ mutex_lock(&ext->win[work_index].queue_lock);
+ list_add_tail(&data->timestamp_node, &ext->win[work_index].timestamp_queue);
+ mutex_unlock(&ext->win[work_index].queue_lock);
+ }
queue_work(ext->win[work_index].flip_wq, &data->work);
unlock_windows_for_flip(user, args);
@@ -903,6 +993,8 @@ static int tegra_dc_ext_setup_windows(struct tegra_dc_ext *ext)
}
mutex_init(&win->lock);
+ mutex_init(&win->queue_lock);
+ INIT_LIST_HEAD(&win->timestamp_queue);
}
return 0;
diff --git a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
index f68c7d5c93c2..ef7361d1d933 100644
--- a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
+++ b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
@@ -58,6 +58,10 @@ struct tegra_dc_ext_win {
struct workqueue_struct *flip_wq;
atomic_t nr_pending_flips;
+
+ struct mutex queue_lock;
+
+ struct list_head timestamp_queue;
};
struct tegra_dc_ext {
diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c
index 79478ea48f83..55d9163d4faf 100644
--- a/drivers/video/tegra/dc/hdmi.c
+++ b/drivers/video/tegra/dc/hdmi.c
@@ -1370,18 +1370,31 @@ bool tegra_dc_hdmi_detect_test(struct tegra_dc *dc, unsigned char *edid_ptr)
err = tegra_edid_get_monspecs_test(hdmi->edid, &specs, edid_ptr);
if (err < 0) {
- dev_err(&dc->ndev->dev, "error reading edid\n");
- goto fail;
- }
+ /* Check if there's a hard-wired mode, if so, enable it */
+ if (dc->out->n_modes)
+ tegra_dc_enable(dc);
+ else {
+ dev_err(&dc->ndev->dev, "error reading edid\n");
+ goto fail;
+ }
+#ifdef CONFIG_SWITCH
+ hdmi->hpd_switch.state = 0;
+ switch_set_state(&hdmi->hpd_switch, 1);
+#endif
+ dev_info(&dc->ndev->dev, "display detected\n");
- err = tegra_edid_get_eld(hdmi->edid, &hdmi->eld);
- if (err < 0) {
- dev_err(&dc->ndev->dev, "error populating eld\n");
- goto fail;
- }
- hdmi->eld_retrieved = true;
+ dc->connected = true;
+ tegra_dc_ext_process_hotplug(dc->ndev->id);
+ } else {
+ err = tegra_edid_get_eld(hdmi->edid, &hdmi->eld);
+ if (err < 0) {
+ dev_err(&dc->ndev->dev, "error populating eld\n");
+ goto fail;
+ }
+ hdmi->eld_retrieved = true;
- tegra_dc_hdmi_detect_config(dc, &specs);
+ tegra_dc_hdmi_detect_config(dc, &specs);
+ }
return true;
@@ -1406,18 +1419,30 @@ static bool tegra_dc_hdmi_detect(struct tegra_dc *dc)
err = tegra_edid_get_monspecs(hdmi->edid, &specs);
if (err < 0) {
- dev_err(&dc->ndev->dev, "error reading edid\n");
- goto fail;
- }
+ if (dc->out->n_modes)
+ tegra_dc_enable(dc);
+ else {
+ dev_err(&dc->ndev->dev, "error reading edid\n");
+ goto fail;
+ }
+#ifdef CONFIG_SWITCH
+ hdmi->hpd_switch.state = 0;
+ switch_set_state(&hdmi->hpd_switch, 1);
+#endif
+ dev_info(&dc->ndev->dev, "display detected\n");
- err = tegra_edid_get_eld(hdmi->edid, &hdmi->eld);
- if (err < 0) {
- dev_err(&dc->ndev->dev, "error populating eld\n");
- goto fail;
- }
- hdmi->eld_retrieved = true;
+ dc->connected = true;
+ tegra_dc_ext_process_hotplug(dc->ndev->id);
+ } else {
+ err = tegra_edid_get_eld(hdmi->edid, &hdmi->eld);
+ if (err < 0) {
+ dev_err(&dc->ndev->dev, "error populating eld\n");
+ goto fail;
+ }
+ hdmi->eld_retrieved = true;
- tegra_dc_hdmi_detect_config(dc, &specs);
+ tegra_dc_hdmi_detect_config(dc, &specs);
+ }
return true;
diff --git a/drivers/video/tegra/dc/mode.c b/drivers/video/tegra/dc/mode.c
index 49cc5f5abd53..3a95f2e7ab0e 100644
--- a/drivers/video/tegra/dc/mode.c
+++ b/drivers/video/tegra/dc/mode.c
@@ -137,6 +137,17 @@ static bool check_ref_to_sync(struct tegra_dc_mode *mode)
return true;
}
+static s64 calc_frametime_ns(const struct tegra_dc_mode *m)
+{
+ long h_total, v_total;
+ h_total = m->h_active + m->h_front_porch + m->h_back_porch +
+ m->h_sync_width;
+ v_total = m->v_active + m->v_front_porch + m->v_back_porch +
+ m->v_sync_width;
+ return (!m->pclk) ? 0 : (s64)(div_s64(((s64)h_total * v_total *
+ 1000000000ULL), m->pclk));
+}
+
/* return in 1000ths of a Hertz */
int tegra_dc_calc_refresh(const struct tegra_dc_mode *m)
{
@@ -247,11 +258,25 @@ int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode)
return 0;
}
+static int panel_sync_rate;
+
+int tegra_dc_get_panel_sync_rate(void)
+{
+ return panel_sync_rate;
+}
+EXPORT_SYMBOL(tegra_dc_get_panel_sync_rate);
+
int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode)
{
memcpy(&dc->mode, mode, sizeof(dc->mode));
+ if (dc->out->type == TEGRA_DC_OUT_RGB)
+ panel_sync_rate = tegra_dc_calc_refresh(mode);
+ else if (dc->out->type == TEGRA_DC_OUT_DSI)
+ panel_sync_rate = dc->out->dsi->rated_refresh_rate * 1000;
+
print_mode(dc, mode, __func__);
+ dc->frametime_ns = calc_frametime_ns(mode);
return 0;
}
diff --git a/drivers/video/tegra/dc/nvsd.c b/drivers/video/tegra/dc/nvsd.c
index e3058b596f69..6e76ee0f1702 100644
--- a/drivers/video/tegra/dc/nvsd.c
+++ b/drivers/video/tegra/dc/nvsd.c
@@ -809,9 +809,12 @@ static ssize_t nvsd_settings_store(struct kobject *kobj,
mutex_unlock(&dc->lock);
return -ENODEV;
}
- mutex_unlock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
nvsd_init(dc, sd_settings);
+ tegra_dc_release_dc_out(dc);
+
+ mutex_unlock(&dc->lock);
/* Update backlight state IFF we're disabling! */
if (!sd_settings->enable && sd_settings->bl_device) {
diff --git a/drivers/video/tegra/dc/window.c b/drivers/video/tegra/dc/window.c
index 5161dd4f7003..cd91fab428ed 100644
--- a/drivers/video/tegra/dc/window.c
+++ b/drivers/video/tegra/dc/window.c
@@ -24,6 +24,7 @@
#include "dc_priv.h"
static int no_vsync;
+static atomic_t frame_end_ref = ATOMIC_INIT(0);
module_param_named(no_vsync, no_vsync, int, S_IRUGO | S_IWUSR);
@@ -40,6 +41,17 @@ static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[],
return true;
}
+int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable)
+{
+ tegra_dc_writel(dc, FRAME_END_INT, DC_CMD_INT_STATUS);
+ if (enable) {
+ atomic_inc(&frame_end_ref);
+ tegra_dc_unmask_interrupt(dc, FRAME_END_INT);
+ } else if (!atomic_dec_return(&frame_end_ref))
+ tegra_dc_mask_interrupt(dc, FRAME_END_INT);
+ return 0;
+}
+
static int get_topmost_window(u32 *depths, unsigned long *wins)
{
int idx, best = -1;
@@ -219,8 +231,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
return -EFAULT;
}
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
+ tegra_dc_hold_dc_out(dc);
if (no_vsync)
tegra_dc_writel(dc, WRITE_MUX_ACTIVE | READ_MUX_ACTIVE,
@@ -407,8 +418,9 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
} else {
clear_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
- tegra_dc_mask_interrupt(dc,
- FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
+ tegra_dc_mask_interrupt(dc, V_BLANK_INT | ALL_UF_INT);
+ if (!atomic_read(&frame_end_ref))
+ tegra_dc_mask_interrupt(dc, FRAME_END_INT);
}
if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
@@ -424,6 +436,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
trace_printk("%s:update_mask=%#lx\n", dc->ndev->name, update_mask);
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
mutex_unlock(&dc->one_shot_lock);
@@ -456,7 +469,8 @@ void tegra_dc_trigger_windows(struct tegra_dc *dc)
}
if (!dirty) {
- if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE))
+ if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ && !atomic_read(&frame_end_ref))
tegra_dc_mask_interrupt(dc, FRAME_END_INT);
}
diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c
index cb7525e049e9..59c162bb3b4c 100644
--- a/drivers/video/tegra/fb.c
+++ b/drivers/video/tegra/fb.c
@@ -96,6 +96,7 @@ static int tegra_fb_set_par(struct fb_info *info)
{
struct tegra_fb_info *tegra_fb = info->par;
struct fb_var_screeninfo *var = &info->var;
+ struct tegra_dc *dc = tegra_fb->win->dc;
if (var->bits_per_pixel) {
/* we only support RGB ordering for now */
@@ -124,10 +125,13 @@ static int tegra_fb_set_par(struct fb_info *info)
default:
return -EINVAL;
}
- info->fix.line_length = var->xres * var->bits_per_pixel / 8;
- /* Pad the stride to 16-byte boundary. */
- info->fix.line_length = round_up(info->fix.line_length,
+ /* if line_length unset, then pad the stride */
+ if (!info->fix.line_length) {
+ info->fix.line_length = var->xres * var->bits_per_pixel
+ / 8;
+ info->fix.line_length = round_up(info->fix.line_length,
TEGRA_LINEAR_PITCH_ALIGNMENT);
+ }
tegra_fb->win->stride = info->fix.line_length;
tegra_fb->win->stride_uv = 0;
tegra_fb->win->phys_addr_u = 0;
@@ -136,17 +140,30 @@ static int tegra_fb_set_par(struct fb_info *info)
if (var->pixclock) {
bool stereo;
+ unsigned old_len = 0;
struct fb_videomode m;
+ struct fb_videomode *old_mode = NULL;
fb_var_to_videomode(&m, var);
+ /* Load framebuffer info with new mode details*/
+ old_mode = info->mode;
+ old_len = info->fix.line_length;
+
info->mode = (struct fb_videomode *)
fb_find_nearest_mode(&m, &info->modelist);
if (!info->mode) {
dev_warn(&tegra_fb->ndev->dev, "can't match video mode\n");
+ info->mode = old_mode;
return -EINVAL;
}
+ /* Update fix line_length and window stride as per new mode */
+ info->fix.line_length = var->xres * var->bits_per_pixel / 8;
+ info->fix.line_length = round_up(info->fix.line_length,
+ TEGRA_LINEAR_PITCH_ALIGNMENT);
+ tegra_fb->win->stride = info->fix.line_length;
+
/*
* only enable stereo if the mode supports it and
* client requests it
@@ -157,10 +174,22 @@ static int tegra_fb_set_par(struct fb_info *info)
#else
FB_VMODE_STEREO_LEFT_RIGHT);
#endif
- tegra_dc_set_fb_mode(tegra_fb->win->dc, info->mode, stereo);
- /* Reflect the mode change on dc */
- tegra_dc_disable(tegra_fb->win->dc);
- tegra_dc_enable(tegra_fb->win->dc);
+
+ /* Configure DC with new mode */
+ if (tegra_dc_set_fb_mode(dc, info->mode, stereo)) {
+ /* Error while configuring DC, fallback to old mode */
+ dev_warn(&tegra_fb->ndev->dev, "can't configure dc with mode %ux%u\n",
+ info->mode->xres, info->mode->yres);
+ info->mode = old_mode;
+ info->fix.line_length = old_len;
+ tegra_fb->win->stride = old_len;
+ return -EINVAL;
+ }
+
+ /* Reflect mode chnage on DC HW */
+ if (dc->enabled)
+ tegra_dc_disable(dc);
+ tegra_dc_enable(dc);
tegra_fb->win->w.full = dfixed_const(info->mode->xres);
tegra_fb->win->h.full = dfixed_const(info->mode->yres);
@@ -326,8 +355,10 @@ static void tegra_fb_imageblit(struct fb_info *info,
static int tegra_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
+ struct tegra_fb_info *tegra_fb = (struct tegra_fb_info *)info->par;
struct tegra_fb_modedb modedb;
struct fb_modelist *modelist;
+ struct fb_vblank vblank = {};
int i;
switch (cmd) {
@@ -370,6 +401,17 @@ static int tegra_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long
return -EFAULT;
break;
+ case FBIOGET_VBLANK:
+ tegra_dc_get_fbvblank(tegra_fb->win->dc, &vblank);
+
+ if (copy_to_user(
+ (void __user *)arg, &vblank, sizeof(vblank)))
+ return -EFAULT;
+ break;
+
+ case FBIO_WAITFORVSYNC:
+ return tegra_dc_wait_for_vsync(tegra_fb->win->dc);
+
default:
return -ENOTTY;
}
@@ -607,8 +649,10 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
tegra_fb->valid = true;
}
+ info->fix.line_length = fb_data->xres * fb_data->bits_per_pixel / 8;
+
stride = tegra_dc_get_stride(dc, 0);
- if (!stride) /* default to pad the stride to 16-byte boundary. */
+ if (!stride) /* default to pad the stride */
stride = round_up(info->fix.line_length,
TEGRA_LINEAR_PITCH_ALIGNMENT);
@@ -625,7 +669,6 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
info->fix.accel = FB_ACCEL_NONE;
info->fix.smem_start = fb_phys;
info->fix.smem_len = fb_size;
- info->fix.line_length = fb_data->xres * fb_data->bits_per_pixel / 8;
info->fix.line_length = stride;
info->var.xres = fb_data->xres;
@@ -683,6 +726,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
if (dc->mode.pclk > 1000) {
struct tegra_dc_mode *mode = &dc->mode;
+ struct fb_videomode vmode;
if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
info->var.pixclock = KHZ2PICOS(mode->rated_pclk / 1000);
@@ -694,6 +738,10 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
info->var.lower_margin = mode->v_front_porch;
info->var.hsync_len = mode->h_sync_width;
info->var.vsync_len = mode->v_sync_width;
+
+ /* Keep info->var consistent with info->modelist. */
+ fb_var_to_videomode(&vmode, &info->var);
+ fb_add_videomode(&vmode, &info->modelist);
}
return tegra_fb;
diff --git a/drivers/video/tegra/host/bus.c b/drivers/video/tegra/host/bus.c
index 758a5ca4ad94..f22dac288051 100644
--- a/drivers/video/tegra/host/bus.c
+++ b/drivers/video/tegra/host/bus.c
@@ -96,7 +96,7 @@ static int nvhost_bus_match(struct device *_dev, struct device_driver *drv)
if (ndrv->id_table)
return nvhost_bus_match_id(dev, ndrv->id_table) != NULL;
else /* driver does not support id_table */
- return !strncmp(dev->name, drv->name, strlen(drv->name));
+ return !strcmp(dev->name, drv->name);
}
static int nvhost_drv_probe(struct device *_dev)
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c
index 0137793b39ee..aaa038221971 100644
--- a/drivers/video/tegra/host/bus_client.c
+++ b/drivers/video/tegra/host/bus_client.c
@@ -159,7 +159,8 @@ static int nvhost_channelopen(struct inode *inode, struct file *filp)
}
filp->private_data = priv;
priv->ch = ch;
- nvhost_module_add_client(ch->dev, priv);
+ if(nvhost_module_add_client(ch->dev, priv))
+ goto fail;
if (ch->ctxhandler && ch->ctxhandler->alloc) {
priv->hwctx = ch->ctxhandler->alloc(ch->ctxhandler, ch);
diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h
index f5d2811f143f..412ce8b65466 100644
--- a/drivers/video/tegra/host/chip_support.h
+++ b/drivers/video/tegra/host/chip_support.h
@@ -125,6 +125,7 @@ struct nvhost_intr_ops {
void (*set_syncpt_threshold)(
struct nvhost_intr *, u32 id, u32 thresh);
void (*enable_syncpt_intr)(struct nvhost_intr *, u32 id);
+ void (*disable_syncpt_intr)(struct nvhost_intr *, u32 id);
void (*disable_all_syncpt_intrs)(struct nvhost_intr *);
int (*request_host_general_irq)(struct nvhost_intr *);
void (*free_host_general_irq)(struct nvhost_intr *);
diff --git a/drivers/video/tegra/host/gr3d/gr3d.c b/drivers/video/tegra/host/gr3d/gr3d.c
index 715468131d9e..775c77b0e88d 100644
--- a/drivers/video/tegra/host/gr3d/gr3d.c
+++ b/drivers/video/tegra/host/gr3d/gr3d.c
@@ -80,8 +80,10 @@ struct host1x_hwctx *nvhost_3dctx_alloc_common(struct host1x_hwctx_handler *p,
ctx->restore = mem_op().alloc(memmgr, p->restore_size * 4, 32,
map_restore ? mem_mgr_flag_write_combine
: mem_mgr_flag_uncacheable);
- if (IS_ERR_OR_NULL(ctx->restore))
+ if (IS_ERR_OR_NULL(ctx->restore)) {
+ ctx->restore = NULL;
goto fail;
+ }
if (map_restore) {
ctx->restore_virt = mem_op().mmap(ctx->restore);
diff --git a/drivers/video/tegra/host/gr3d/gr3d.h b/drivers/video/tegra/host/gr3d/gr3d.h
index 3855b237b702..61f708cea95c 100644
--- a/drivers/video/tegra/host/gr3d/gr3d.h
+++ b/drivers/video/tegra/host/gr3d/gr3d.h
@@ -29,6 +29,9 @@
#define AR3D_PSEQ_QUAD_ID 0x545
#define AR3D_DW_MEMORY_OUTPUT_ADDRESS 0x904
#define AR3D_DW_MEMORY_OUTPUT_DATA 0x905
+#define AR3D_FDC_CONTROL_0 0xa00
+#define AR3D_FDC_CONTROL_0_RESET_VAL 0xe00
+#define AR3D_FDC_CONTROL_0_INVALIDATE 1
#define AR3D_GSHIM_WRITE_MASK 0xb00
#define AR3D_GSHIM_READ_SELECT 0xb01
#define AR3D_GLOBAL_MEMORY_OUTPUT_READS 0xe40
diff --git a/drivers/video/tegra/host/gr3d/gr3d_t20.c b/drivers/video/tegra/host/gr3d/gr3d_t20.c
index b6e3896fe50c..694b00527790 100644
--- a/drivers/video/tegra/host/gr3d/gr3d_t20.c
+++ b/drivers/video/tegra/host/gr3d/gr3d_t20.c
@@ -144,7 +144,7 @@ static void save_push_v0(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma)
p->save_phys);
}
-static void __init save_begin_v0(struct host1x_hwctx_handler *h, u32 *ptr)
+static void save_begin_v0(struct host1x_hwctx_handler *h, u32 *ptr)
{
/* 3d: when done, increment syncpt to base+1 */
ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0);
@@ -162,7 +162,7 @@ static void __init save_begin_v0(struct host1x_hwctx_handler *h, u32 *ptr)
h->syncpt); /* incr 2 */
}
-static void __init save_direct_v0(u32 *ptr, u32 start_reg, u32 count)
+static void save_direct_v0(u32 *ptr, u32 start_reg, u32 count)
{
ptr[0] = nvhost_opcode_nonincr(host1x_uclass_indoff_r(), 1);
ptr[1] = nvhost_class_host_indoff_reg_read(NV_HOST_MODULE_GR3D,
@@ -170,7 +170,7 @@ static void __init save_direct_v0(u32 *ptr, u32 start_reg, u32 count)
ptr[2] = nvhost_opcode_nonincr(host1x_uclass_inddata_r(), count);
}
-static void __init save_indirect_v0(u32 *ptr, u32 offset_reg, u32 offset,
+static void save_indirect_v0(u32 *ptr, u32 offset_reg, u32 offset,
u32 data_reg, u32 count)
{
ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID,
@@ -183,7 +183,7 @@ static void __init save_indirect_v0(u32 *ptr, u32 offset_reg, u32 offset,
ptr[4] = nvhost_opcode_nonincr(host1x_uclass_inddata_r(), count);
}
-static void __init save_end_v0(struct host1x_hwctx_handler *h, u32 *ptr)
+static void save_end_v0(struct host1x_hwctx_handler *h, u32 *ptr)
{
/* Wait for context read service to finish (cpu incr 3) */
ptr[0] = nvhost_opcode_nonincr(host1x_uclass_wait_syncpt_base_r(), 1);
@@ -226,7 +226,7 @@ static u32 *save_regs_v0(u32 *ptr, unsigned int *pending,
/*** save ***/
-static void __init setup_save_regs(struct save_info *info,
+static void setup_save_regs(struct save_info *info,
const struct hwctx_reginfo *regs,
unsigned int nr_regs)
{
@@ -284,7 +284,7 @@ static void __init setup_save_regs(struct save_info *info,
info->restore_count = restore_count;
}
-static void __init setup_save(struct host1x_hwctx_handler *h, u32 *ptr)
+static void setup_save(struct host1x_hwctx_handler *h, u32 *ptr)
{
struct save_info info = {
ptr,
@@ -371,7 +371,7 @@ struct nvhost_hwctx_handler *nvhost_gr3d_t20_ctxhandler_init(
p->save_buf = mem_op().alloc(memmgr, p->save_size * sizeof(u32), 32,
mem_mgr_flag_write_combine);
- if (IS_ERR(p->save_buf)) {
+ if (IS_ERR_OR_NULL(p->save_buf)) {
p->save_buf = NULL;
return NULL;
}
diff --git a/drivers/video/tegra/host/gr3d/gr3d_t30.c b/drivers/video/tegra/host/gr3d/gr3d_t30.c
index c35fea2f3ac2..664708c7fc80 100644
--- a/drivers/video/tegra/host/gr3d/gr3d_t30.c
+++ b/drivers/video/tegra/host/gr3d/gr3d_t30.c
@@ -125,6 +125,16 @@ static void save_push_v1(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma)
nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0),
NVHOST_OPCODE_NOOP);
+ /* invalidate the FDC to prevent cache-coherency issues across GPUs
+ note that we assume FDC_CONTROL_0 is left in the reset state by all
+ contexts. the invalidate bit will clear itself, so the register
+ should be unchanged after this */
+ nvhost_cdma_push(cdma,
+ nvhost_opcode_imm(AR3D_FDC_CONTROL_0,
+ AR3D_FDC_CONTROL_0_RESET_VAL
+ | AR3D_FDC_CONTROL_0_INVALIDATE),
+ NVHOST_OPCODE_NOOP);
+
/* set register set 0 and 1 register read memory output addresses,
and send their reads to memory */
@@ -132,7 +142,7 @@ static void save_push_v1(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma)
nvhost_opcode_imm(AR3D_GSHIM_WRITE_MASK, 2),
nvhost_opcode_imm(AR3D_GLOBAL_MEMORY_OUTPUT_READS, 1));
nvhost_cdma_push(cdma,
- nvhost_opcode_nonincr(0x904, 1),
+ nvhost_opcode_nonincr(AR3D_DW_MEMORY_OUTPUT_ADDRESS, 1),
ctx->restore_phys + restore_set1_offset * 4);
nvhost_cdma_push(cdma,
@@ -150,7 +160,7 @@ static void save_push_v1(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma)
p->save_phys);
}
-static void __init save_begin_v1(struct host1x_hwctx_handler *p, u32 *ptr)
+static void save_begin_v1(struct host1x_hwctx_handler *p, u32 *ptr)
{
ptr[0] = nvhost_opcode_nonincr(AR3D_DW_MEMORY_OUTPUT_DATA,
RESTORE_BEGIN_SIZE);
@@ -158,7 +168,7 @@ static void __init save_begin_v1(struct host1x_hwctx_handler *p, u32 *ptr)
ptr += RESTORE_BEGIN_SIZE;
}
-static void __init save_direct_v1(u32 *ptr, u32 start_reg, u32 count)
+static void save_direct_v1(u32 *ptr, u32 start_reg, u32 count)
{
ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID,
AR3D_DW_MEMORY_OUTPUT_DATA, 1);
@@ -172,7 +182,7 @@ static void __init save_direct_v1(u32 *ptr, u32 start_reg, u32 count)
ptr[3] = nvhost_opcode_nonincr(host1x_uclass_inddata_r(), count);
}
-static void __init save_indirect_v1(u32 *ptr, u32 offset_reg, u32 offset,
+static void save_indirect_v1(u32 *ptr, u32 offset_reg, u32 offset,
u32 data_reg, u32 count)
{
ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0);
@@ -189,7 +199,7 @@ static void __init save_indirect_v1(u32 *ptr, u32 offset_reg, u32 offset,
ptr[5] = nvhost_opcode_nonincr(host1x_uclass_inddata_r(), count);
}
-static void __init save_end_v1(struct host1x_hwctx_handler *p, u32 *ptr)
+static void save_end_v1(struct host1x_hwctx_handler *p, u32 *ptr)
{
/* write end of restore buffer */
ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID,
@@ -224,7 +234,7 @@ static void __init save_end_v1(struct host1x_hwctx_handler *p, u32 *ptr)
-static void __init setup_save_regs(struct save_info *info,
+static void setup_save_regs(struct save_info *info,
const struct hwctx_reginfo *regs,
unsigned int nr_regs)
{
@@ -282,7 +292,7 @@ static void __init setup_save_regs(struct save_info *info,
info->restore_count = restore_count;
}
-static void __init switch_gpu(struct save_info *info,
+static void switch_gpu(struct save_info *info,
unsigned int save_src_set,
u32 save_dest_sets,
u32 restore_dest_sets)
@@ -303,7 +313,7 @@ static void __init switch_gpu(struct save_info *info,
info->restore_count += 1;
}
-static void __init setup_save(struct host1x_hwctx_handler *p, u32 *ptr)
+static void setup_save(struct host1x_hwctx_handler *p, u32 *ptr)
{
struct save_info info = {
ptr,
@@ -399,7 +409,7 @@ struct nvhost_hwctx_handler *nvhost_gr3d_t30_ctxhandler_init(
p->save_buf = mem_op().alloc(memmgr, p->save_size * 4, 32,
mem_mgr_flag_write_combine);
- if (IS_ERR(p->save_buf)) {
+ if (IS_ERR_OR_NULL(p->save_buf)) {
p->save_buf = NULL;
return NULL;
}
diff --git a/drivers/video/tegra/host/gr3d/scale3d.c b/drivers/video/tegra/host/gr3d/scale3d.c
index 5922b55a836a..49147975a9e4 100644
--- a/drivers/video/tegra/host/gr3d/scale3d.c
+++ b/drivers/video/tegra/host/gr3d/scale3d.c
@@ -1,9 +1,9 @@
/*
- * drivers/video/tegra/host/t20/scale3d.c
+ * drivers/video/tegra/host/gr3d/scale3d.c
*
* Tegra Graphics Host 3D clock scaling
*
- * Copyright (c) 2010-2012, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -23,12 +23,11 @@
*
* module3d_notify_busy() is called upon submit, module3d_notify_idle() is
* called when all outstanding submits are completed. Idle times are measured
- * over a fixed time period (scale3d.p_period). If the 3d module idle time
- * percentage goes over the limit (set in scale3d.p_idle_max), 3d clocks are
- * scaled down. If the percentage goes under the minimum limit (set in
- * scale3d.p_idle_min), 3d clocks are scaled up. An additional test is made
- * over the time frame given in scale3d.p_fast_response for clocking up
- * quickly in response to load peaks.
+ * over a fixed time period (scale3d.p_estimation_window). If the 3d module
+ * idle time percentage goes over the limit (set in scale3d.p_idle_max), 3d
+ * clocks are scaled down. If the percentage goes under the minimum limit (set
+ * in scale3d.p_idle_min), 3d clocks are scaled up. An additional test is made
+ * for clocking up quickly in response to load peaks.
*
* 3d.emc clock is scaled proportionately to 3d clock, with a quadratic-
* bezier-like factor added to pull 3d.emc rate a bit lower.
@@ -37,10 +36,31 @@
#include <linux/debugfs.h>
#include <linux/types.h>
#include <linux/clk.h>
+#include <linux/slab.h>
#include <mach/clk.h>
#include <mach/hardware.h>
#include "scale3d.h"
#include "dev.h"
+#include <media/tegra_camera.h>
+
+#define GR3D_PRINT_STATS BIT(1)
+#define GR3D_PRINT_BUSY BIT(2)
+#define GR3D_PRINT_IDLE BIT(3)
+#define GR3D_PRINT_HINT BIT(4)
+#define GR3D_PRINT_TARGET BIT(5)
+
+/* time frame for load and hint tracking - when events come in at a larger
+ * interval, this probably indicates the current estimates are stale
+ */
+#define GR3D_TIMEFRAME 1000000 /* 1 sec */
+
+/* the number of frames to use in the running average of load estimates and
+ * throughput hints. Choosing 6 frames targets a window of about 100 msec.
+ * Large flucutuations in frame times require a window that's large enough to
+ * prevent spiky scaling behavior, which in turn exacerbates frame rate
+ * instability.
+ */
+#define GR3D_FRAME_SPAN 6
static int scale3d_is_enabled(void);
static void scale3d_enable(int enable);
@@ -48,54 +68,73 @@ static void scale3d_enable(int enable);
#define POW2(x) ((x) * (x))
/*
+ * 3D clock scaling should be treated differently when camera is on in AP37.
+ * 3D in AP37 requires 1.3V and combining it with MPE reaches to EDP limit.
+ * 3D clock really needs to be set to lower frequency which requires 1.0V.
+ * The same thing applies to 3D EMC clock.
+ */
+#define CAMERA_3D_CLK 300000000
+#define CAMERA_3D_EMC_CLK 437000000
+
+/*
* debugfs parameters to control 3d clock scaling test
*
- * period - time period for clock rate evaluation
- * fast_response - time period for evaluation of 'busy' spikes
- * idle_min - if less than [idle_min] percent idle over [fast_response]
- * microseconds, clock up.
- * idle_max - if over [idle_max] percent idle over [period] microseconds,
- * clock down.
+ * estimation_window - time period for clock rate evaluation
+ * idle_min - if less than [idle_min / 10] percent idle over
+ * [estimation_window] microseconds, clock up.
+ * idle_max - if over [idle_max] percent idle over [estimation_window]
+ * microseconds, clock down.
* max_scale - limits rate changes to no less than (100 - max_scale)% or
* (100 + 2 * max_scale)% of current clock rate
- * verbosity - set above 5 for debug printouts
+ * verbosity - bit flag to control debug printouts:
+ * 1 - stats
+ * 2 - busy
+ * 3 - idle
+ * 4 - hints
+ * 5 - target frequencies
*/
struct scale3d_info_rec {
struct mutex lock; /* lock for timestamps etc */
int enable;
int init;
- ktime_t idle_frame;
- ktime_t fast_frame;
- ktime_t last_idle;
- ktime_t last_short_term_idle;
+ ktime_t last_scale;
int is_idle;
- ktime_t last_tweak;
- ktime_t last_down;
+ ktime_t last_adjust;
int fast_up_count;
int slow_down_count;
int is_scaled;
- int fast_responses;
- unsigned long idle_total;
- unsigned long idle_short_term_total;
- unsigned long max_rate_3d;
long emc_slope;
long emc_offset;
long emc_dip_slope;
long emc_dip_offset;
long emc_xmid;
+ unsigned long max_rate_3d;
unsigned long min_rate_3d;
+ ktime_t last_throughput_hint;
+
struct work_struct work;
struct delayed_work idle_timer;
+
+ ktime_t last_estimation_window;
+ long last_total_idle;
+ long total_idle;
+ ktime_t estimation_window;
+ ktime_t last_notification;
+ long idle_estimate;
+
unsigned int scale;
- unsigned int p_period;
- unsigned int period;
+ unsigned int p_busy_cutoff;
+ unsigned int p_estimation_window;
+ unsigned int p_use_throughput_hint;
+ unsigned int p_throughput_lo_limit;
+ unsigned int p_throughput_lower_limit;
+ unsigned int p_throughput_hi_limit;
+ unsigned int p_scale_step;
unsigned int p_idle_min;
unsigned int idle_min;
unsigned int p_idle_max;
unsigned int idle_max;
- unsigned int p_fast_response;
- unsigned int fast_response;
unsigned int p_adjust;
unsigned int p_scale_emc;
unsigned int p_emc_dip;
@@ -103,13 +142,15 @@ struct scale3d_info_rec {
struct clk *clk_3d;
struct clk *clk_3d2;
struct clk *clk_3d_emc;
+ int *freqlist;
+ int freq_count;
};
static struct scale3d_info_rec scale3d;
-static void scale3d_clocks(unsigned long percent)
+static void scale_to_freq(unsigned long hz)
{
- unsigned long hz, curr;
+ unsigned long curr;
if (!tegra_is_clk_enabled(scale3d.clk_3d))
return;
@@ -119,7 +160,8 @@ static void scale3d_clocks(unsigned long percent)
return;
curr = clk_get_rate(scale3d.clk_3d);
- hz = percent * (curr / 100);
+ if (hz == curr)
+ return;
if (!(hz >= scale3d.max_rate_3d && curr == scale3d.max_rate_3d)) {
if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3)
@@ -139,6 +181,16 @@ static void scale3d_clocks(unsigned long percent)
}
}
+static void scale3d_clocks(unsigned long percent)
+{
+ unsigned long hz, curr;
+
+ curr = clk_get_rate(scale3d.clk_3d);
+ hz = percent * (curr / 100);
+
+ scale_to_freq(hz);
+}
+
static void scale3d_clocks_handler(struct work_struct *work)
{
unsigned int scale;
@@ -164,12 +216,26 @@ void nvhost_scale3d_suspend(struct nvhost_device *dev)
static void reset_3d_clocks(void)
{
if (clk_get_rate(scale3d.clk_3d) != scale3d.max_rate_3d) {
- clk_set_rate(scale3d.clk_3d, scale3d.max_rate_3d);
- if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3)
- clk_set_rate(scale3d.clk_3d2, scale3d.max_rate_3d);
- if (scale3d.p_scale_emc)
- clk_set_rate(scale3d.clk_3d_emc,
- clk_round_rate(scale3d.clk_3d_emc, UINT_MAX));
+ if (is_tegra_camera_on())
+ clk_set_rate(scale3d.clk_3d, CAMERA_3D_CLK);
+ else
+ clk_set_rate(scale3d.clk_3d, scale3d.max_rate_3d);
+ if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3) {
+ if (is_tegra_camera_on())
+ clk_set_rate(scale3d.clk_3d2, CAMERA_3D_CLK);
+ else
+ clk_set_rate(scale3d.clk_3d2,
+ scale3d.max_rate_3d);
+ }
+ if (scale3d.p_scale_emc) {
+ if (is_tegra_camera_on())
+ clk_set_rate(scale3d.clk_3d_emc,
+ CAMERA_3D_EMC_CLK);
+ else
+ clk_set_rate(scale3d.clk_3d_emc,
+ clk_round_rate(scale3d.clk_3d_emc,
+ UINT_MAX));
+ }
}
}
@@ -207,15 +273,6 @@ static void scale3d_enable(int enable)
reset_3d_clocks();
}
-static void reset_scaling_counters(ktime_t time)
-{
- scale3d.idle_total = 0;
- scale3d.idle_short_term_total = 0;
- scale3d.last_idle = time;
- scale3d.last_short_term_idle = time;
- scale3d.idle_frame = time;
-}
-
/* scaling_adjust - use scale up / scale down hint counts to adjust scaling
* parameters.
*
@@ -228,8 +285,6 @@ static void reset_scaling_counters(ktime_t time)
*
* the parameters adjusted are
*
- * * fast_response time
- * * period - time for scaling down estimate
* * idle_min percentage
* * idle_max percentage
*/
@@ -242,13 +297,11 @@ static void reset_scaling_counters(ktime_t time)
static void scaling_adjust(ktime_t time)
{
long hint_ratio;
- long fast_response_adjustment;
- long period_adjustment;
int idle_min_adjustment;
int idle_max_adjustment;
unsigned long dt;
- dt = (unsigned long) ktime_us_delta(time, scale3d.last_tweak);
+ dt = (unsigned long) ktime_us_delta(time, scale3d.last_adjust);
if (dt < SCALING_ADJUST_PERIOD)
return;
@@ -256,13 +309,9 @@ static void scaling_adjust(ktime_t time)
(scale3d.slow_down_count + 1);
if (hint_ratio > HINT_RATIO_MAX) {
- fast_response_adjustment = -((int) scale3d.p_fast_response) / 4;
- period_adjustment = scale3d.p_period / 2;
idle_min_adjustment = scale3d.p_idle_min;
idle_max_adjustment = scale3d.p_idle_max;
} else if (hint_ratio < HINT_RATIO_MIN) {
- fast_response_adjustment = scale3d.p_fast_response / 2;
- period_adjustment = -((int) scale3d.p_period) / 4;
idle_min_adjustment = -((int) scale3d.p_idle_min) / 2;
idle_max_adjustment = -((int) scale3d.p_idle_max) / 2;
} else {
@@ -277,33 +326,23 @@ static void scaling_adjust(ktime_t time)
diff *= 2;
}
- fast_response_adjustment = diff *
- (scale3d.p_fast_response / (HINT_RATIO_DIFF * 2));
- period_adjustment =
- diff * (scale3d.p_period / HINT_RATIO_DIFF);
idle_min_adjustment =
(factor * (int) scale3d.p_idle_min) / HINT_RATIO_DIFF;
idle_max_adjustment =
(factor * (int) scale3d.p_idle_max) / HINT_RATIO_DIFF;
}
- scale3d.fast_response =
- scale3d.p_fast_response + fast_response_adjustment;
- scale3d.period = scale3d.p_period + period_adjustment;
- scale3d.idle_min = scale3d.p_idle_min + idle_min_adjustment;
+ scale3d.idle_min = scale3d.p_idle_min + idle_min_adjustment;
scale3d.idle_max = scale3d.p_idle_max + idle_max_adjustment;
- if (scale3d.p_verbosity >= 10)
- pr_info("scale3d stats: + %d - %d (/ %d) f %u p %u min %u max %u\n",
+ if (scale3d.p_verbosity & GR3D_PRINT_STATS)
+ pr_info("scale3d stats: + %d - %d min %u max %u\n",
scale3d.fast_up_count, scale3d.slow_down_count,
- scale3d.fast_responses, scale3d.fast_response,
- scale3d.period, scale3d.idle_min, scale3d.idle_max);
+ scale3d.idle_min, scale3d.idle_max);
scale3d.fast_up_count = 0;
scale3d.slow_down_count = 0;
- scale3d.fast_responses = 0;
- scale3d.last_down = time;
- scale3d.last_tweak = time;
+ scale3d.last_adjust = time;
}
#undef SCALING_ADJUST_PERIOD
@@ -316,61 +355,101 @@ static void scaling_state_check(ktime_t time)
{
unsigned long dt;
- /* adjustment: set scale parameters (fast_response, period) +/- 25%
+ /* adjustment: set scale parameters (idle_min, idle_max) +/- 25%
* based on ratio of scale up to scale down hints
*/
if (scale3d.p_adjust)
scaling_adjust(time);
else {
- scale3d.fast_response = scale3d.p_fast_response;
- scale3d.period = scale3d.p_period;
scale3d.idle_min = scale3d.p_idle_min;
scale3d.idle_max = scale3d.p_idle_max;
}
- /* check for load peaks */
- dt = (unsigned long) ktime_us_delta(time, scale3d.fast_frame);
- if (dt > scale3d.fast_response) {
- unsigned long idleness =
- (scale3d.idle_short_term_total * 100) / dt;
- scale3d.fast_responses++;
- scale3d.fast_frame = time;
- /* if too busy, scale up */
- if (idleness < scale3d.idle_min) {
- scale3d.is_scaled = 0;
- scale3d.fast_up_count++;
- if (scale3d.p_verbosity >= 5)
- pr_info("scale3d: %ld%% busy\n",
- 100 - idleness);
-
- reset_3d_clocks();
- reset_scaling_counters(time);
- return;
- }
- scale3d.idle_short_term_total = 0;
- scale3d.last_short_term_idle = time;
+ dt = (unsigned long) ktime_us_delta(time, scale3d.last_scale);
+ if (dt < scale3d.p_estimation_window)
+ return;
+
+ scale3d.last_scale = time;
+
+ /* if too busy, scale up */
+ if (scale3d.idle_estimate < scale3d.idle_min) {
+ scale3d.is_scaled = 0;
+ scale3d.fast_up_count++;
+ if (scale3d.p_verbosity & GR3D_PRINT_BUSY)
+ pr_info("scale3d: %ld/1000 busy\n",
+ 1000 - scale3d.idle_estimate);
+
+ reset_3d_clocks();
+ return;
}
- dt = (unsigned long) ktime_us_delta(time, scale3d.idle_frame);
- if (dt > scale3d.period) {
- unsigned long idleness = (scale3d.idle_total * 100) / dt;
+ if (scale3d.p_verbosity & GR3D_PRINT_IDLE)
+ pr_info("scale3d: idle %lu/1000\n",
+ scale3d.idle_estimate);
- if (scale3d.p_verbosity >= 5)
- pr_info("scale3d: idle %lu, ~%lu%%\n",
- scale3d.idle_total, idleness);
+ if (scale3d.idle_estimate > scale3d.idle_max) {
+ if (!scale3d.is_scaled)
+ scale3d.is_scaled = 1;
- if (idleness > scale3d.idle_max) {
- if (!scale3d.is_scaled) {
- scale3d.is_scaled = 1;
- scale3d.last_down = time;
- }
- scale3d.slow_down_count++;
- /* if idle time is high, clock down */
- scale3d.scale = 100 - (idleness - scale3d.idle_min);
- schedule_work(&scale3d.work);
- }
+ scale3d.slow_down_count++;
+ /* if idle time is high, clock down */
+ scale3d.scale =
+ 100 - (scale3d.idle_estimate - scale3d.idle_min) / 10;
+ schedule_work(&scale3d.work);
+ }
+}
+
+/* the idle estimate is done by keeping 2 time stamps, initially set to the
+ * same time. Once the estimation_window time has been exceeded, one time
+ * stamp is moved up to the current time. The idle estimate is calculated
+ * based on the idle time percentage from the earlier estimate. The next time
+ * an estimation_window time is exceeded, the previous idle time and estimates
+ * are moved up - this is intended to prevent abrupt changes to the idle
+ * estimate.
+ */
+static void update_load_estimate(int idle)
+{
+ unsigned long window;
+ unsigned long t;
+
+ ktime_t now = ktime_get();
+ t = ktime_us_delta(now, scale3d.last_notification);
- reset_scaling_counters(time);
+ /* if the last event was over GR3D_TIMEFRAME usec ago (1 sec), the
+ * current load tracking data is probably stale
+ */
+ if (t > GR3D_TIMEFRAME) {
+ scale3d.is_idle = idle;
+ scale3d.last_notification = now;
+ scale3d.estimation_window = now;
+ scale3d.last_estimation_window = now;
+ scale3d.total_idle = 0;
+ scale3d.last_total_idle = 0;
+ scale3d.idle_estimate = idle ? 1000 : 0;
+ return;
+ }
+
+ if (scale3d.is_idle) {
+ scale3d.total_idle += t;
+ scale3d.last_total_idle += t;
+ }
+
+ scale3d.is_idle = idle;
+ scale3d.last_notification = now;
+
+ window = ktime_us_delta(now, scale3d.last_estimation_window);
+ /* prevent division by 0 if events come in less than 1 usec apart */
+ if (window > 0)
+ scale3d.idle_estimate =
+ (1000 * scale3d.last_total_idle) / window;
+
+ /* move up to the last estimation window */
+ if (ktime_us_delta(now, scale3d.estimation_window) >
+ scale3d.p_estimation_window) {
+ scale3d.last_estimation_window = scale3d.estimation_window;
+ scale3d.last_total_idle = scale3d.total_idle;
+ scale3d.total_idle = 0;
+ scale3d.estimation_window = now;
}
}
@@ -378,65 +457,226 @@ void nvhost_scale3d_notify_idle(struct nvhost_device *dev)
{
ktime_t t;
unsigned long dt;
+ int delay;
if (!scale3d.enable)
return;
- mutex_lock(&scale3d.lock);
+ update_load_estimate(1);
t = ktime_get();
- if (scale3d.is_idle) {
- dt = ktime_us_delta(t, scale3d.last_idle);
- scale3d.idle_total += dt;
- dt = ktime_us_delta(t, scale3d.last_short_term_idle);
- scale3d.idle_short_term_total += dt;
- } else
- scale3d.is_idle = 1;
+ /* if throughput hint enabled, and last hint is recent enough, return */
+ if (scale3d.p_use_throughput_hint) {
+ dt = ktime_us_delta(t, scale3d.last_throughput_hint);
+ if (dt < GR3D_TIMEFRAME)
+ return;
+ }
- scale3d.last_idle = t;
- scale3d.last_short_term_idle = t;
+ mutex_lock(&scale3d.lock);
- scaling_state_check(scale3d.last_idle);
+ scaling_state_check(t);
- /* delay idle_max % of 2 * fast_response time (given in microseconds) */
- schedule_delayed_work(&scale3d.idle_timer,
- msecs_to_jiffies((scale3d.idle_max * scale3d.fast_response)
- / 50000));
+ /* delay idle_max % of 2 * estimation_window (given in microseconds) */
+ delay = (scale3d.idle_max * scale3d.p_estimation_window) / 500000;
+ schedule_delayed_work(&scale3d.idle_timer, msecs_to_jiffies(delay));
mutex_unlock(&scale3d.lock);
}
void nvhost_scale3d_notify_busy(struct nvhost_device *dev)
{
- unsigned long idle;
- unsigned long short_term_idle;
ktime_t t;
if (!scale3d.enable)
return;
- mutex_lock(&scale3d.lock);
-
- cancel_delayed_work(&scale3d.idle_timer);
+ update_load_estimate(0);
t = ktime_get();
- if (scale3d.is_idle) {
- idle = (unsigned long)
- ktime_us_delta(t, scale3d.last_idle);
- scale3d.idle_total += idle;
- short_term_idle =
- ktime_us_delta(t, scale3d.last_short_term_idle);
- scale3d.idle_short_term_total += short_term_idle;
- scale3d.is_idle = 0;
+ /* if throughput hint enabled, and last hint is recent enough, return */
+ if (scale3d.p_use_throughput_hint) {
+ unsigned long dt;
+ dt = ktime_us_delta(t, scale3d.last_throughput_hint);
+ if (dt < GR3D_TIMEFRAME)
+ return;
}
+ mutex_lock(&scale3d.lock);
+
+ cancel_delayed_work(&scale3d.idle_timer);
scaling_state_check(t);
mutex_unlock(&scale3d.lock);
}
+struct score {
+ int size; /* number of elements */
+ int pos; /* position in ring buffer */
+ int count; /* actual item count */
+ unsigned int sum; /* running sum */
+ unsigned int prev; /* previous score after 'reset' operation */
+ unsigned int list[]; /* ring buffer */
+};
+
+static struct score *score_init(int capacity)
+{
+ struct score *s;
+
+ s = kzalloc(sizeof(struct score) + capacity * sizeof(int), GFP_KERNEL);
+ if (s == NULL)
+ return NULL;
+
+ s->size = capacity;
+
+ return s;
+}
+
+static void score_delete(struct score *s)
+{
+ kfree(s);
+}
+
+#define score_get_average(s) ((s)->count ? (s)->sum / (s)->count : 0)
+
+static void score_add(struct score *s, unsigned int reading)
+{
+ if (s->count < s->size) {
+ s->sum += reading;
+ s->count++;
+ } else
+ s->sum = s->sum - s->list[s->pos] + reading;
+
+ s->list[s->pos] = reading;
+ s->pos = (s->pos + 1) % s->size;
+}
+
+
+static unsigned int score_reset(struct score *s)
+{
+ s->prev = s->sum;
+
+ s->count = 0;
+ s->pos = 0;
+ s->sum = 0;
+
+ return s->prev;
+}
+
+int freqlist_up(long target, int steps)
+{
+ int i, pos;
+
+ for (i = 0; i < scale3d.freq_count; i++)
+ if (scale3d.freqlist[i] >= target)
+ break;
+
+ pos = min(scale3d.freq_count - 1, i + steps);
+ return scale3d.freqlist[pos];
+}
+
+int freqlist_down(long target, int steps)
+{
+ int i, pos;
+
+ for (i = scale3d.freq_count - 1; i >= 0; i--)
+ if (scale3d.freqlist[i] <= target)
+ break;
+
+ pos = max(0, i - steps);
+ return scale3d.freqlist[pos];
+}
+
+static struct score *busy_history;
+static struct score *hint_history;
+
+/* When a throughput hint is given, perform scaling based on the hint and on
+ * the current idle estimation. This is done as follows:
+ *
+ * 1. On moderate loads force min frequency if the throughput hint is not too
+ * low.
+ * 2. Otherwise, calculate target-rate = max-rate * load-percentage
+ * 3. Unless the current or average throughput hint is below the minimum
+ * limit, in which case, choose a higher rate
+ * 4. Or the average throughput hint is above the maximum limit, in which case,
+ * choose a lower rate.
+ */
+void nvhost_scale3d_set_throughput_hint(int hint)
+{
+ ktime_t now;
+ long busy;
+ long curr;
+ long target;
+ long dt;
+ int avg_busy, avg_hint;
+
+ if (!scale3d.enable)
+ return;
+
+ if (!scale3d.p_use_throughput_hint)
+ return;
+
+ if (scale3d.p_verbosity & GR3D_PRINT_HINT)
+ pr_info("3fds: idle %ld, hint %d\n",
+ scale3d.idle_estimate, hint);
+
+ now = ktime_get();
+ dt = ktime_us_delta(now, scale3d.last_throughput_hint);
+ if (dt > GR3D_TIMEFRAME) {
+ score_reset(busy_history);
+ score_reset(hint_history);
+ }
+
+ scale3d.last_throughput_hint = now;
+
+ busy = 1000 - scale3d.idle_estimate;
+ curr = clk_get_rate(scale3d.clk_3d);
+ target = scale3d.min_rate_3d;
+
+ score_add(busy_history, busy);
+ score_add(hint_history, hint);
+
+ avg_busy = score_get_average(busy_history);
+ avg_hint = score_get_average(hint_history);
+
+ if (busy > 0)
+ target = (curr / 1000) * busy;
+
+ /* In practice, running the gpu at min frequency is typically
+ * sufficient to keep up performance at loads up to 70% on cases,
+ * but the average hint value is tested to keep performance up if
+ * needed.
+ */
+ if (avg_busy <= scale3d.p_busy_cutoff &&
+ avg_hint >= scale3d.p_throughput_lower_limit)
+ target = scale3d.min_rate_3d;
+ else {
+ target = (scale3d.max_rate_3d / 1000) * avg_busy;
+
+ /* Scale up if either the current hint or the running average
+ * are below the target to prevent performance drop.
+ */
+ if (hint <= scale3d.p_throughput_lo_limit ||
+ avg_hint <= scale3d.p_throughput_lo_limit) {
+ if (target < curr)
+ target = curr;
+ target = freqlist_up(target, scale3d.p_scale_step);
+ } else if (avg_hint >= scale3d.p_throughput_hi_limit) {
+ if (target > curr)
+ target = curr;
+ target = freqlist_down(target, scale3d.p_scale_step);
+ }
+ }
+
+ scale_to_freq(target);
+
+ if (scale3d.p_verbosity & GR3D_PRINT_TARGET)
+ pr_info("3dfs: busy %ld <%d>, curr %ld, t %ld, hint %d <%d>\n",
+ busy, avg_busy, curr / 1000000, target, hint, avg_hint);
+}
+EXPORT_SYMBOL(nvhost_scale3d_set_throughput_hint);
+
static void scale3d_idle_handler(struct work_struct *work)
{
int notify_idle = 0;
@@ -458,19 +698,6 @@ static void scale3d_idle_handler(struct work_struct *work)
nvhost_scale3d_notify_idle(NULL);
}
-void nvhost_scale3d_reset()
-{
- ktime_t t;
-
- if (!scale3d.enable)
- return;
-
- t = ktime_get();
- mutex_lock(&scale3d.lock);
- reset_scaling_counters(t);
- mutex_unlock(&scale3d.lock);
-}
-
/*
* debugfs parameters to control 3d clock scaling
*/
@@ -495,13 +722,17 @@ void nvhost_scale3d_debug_init(struct dentry *de)
} \
} while (0)
- CREATE_SCALE3D_FILE(fast_response);
+ CREATE_SCALE3D_FILE(estimation_window);
CREATE_SCALE3D_FILE(idle_min);
CREATE_SCALE3D_FILE(idle_max);
- CREATE_SCALE3D_FILE(period);
CREATE_SCALE3D_FILE(adjust);
CREATE_SCALE3D_FILE(scale_emc);
CREATE_SCALE3D_FILE(emc_dip);
+ CREATE_SCALE3D_FILE(use_throughput_hint);
+ CREATE_SCALE3D_FILE(throughput_hi_limit);
+ CREATE_SCALE3D_FILE(throughput_lo_limit);
+ CREATE_SCALE3D_FILE(throughput_lower_limit);
+ CREATE_SCALE3D_FILE(scale_step);
CREATE_SCALE3D_FILE(verbosity);
#undef CREATE_SCALE3D_FILE
}
@@ -532,12 +763,17 @@ static ssize_t enable_3d_scaling_store(struct device *dev,
static DEVICE_ATTR(enable_3d_scaling, S_IRUGO | S_IWUSR,
enable_3d_scaling_show, enable_3d_scaling_store);
+#define MAX_FREQ_COUNT 0x40 /* 64 frequencies should be enough for anyone */
+
void nvhost_scale3d_init(struct nvhost_device *d)
{
if (!scale3d.init) {
int error;
unsigned long max_emc, min_emc;
long correction;
+ long rate;
+ int freqs[MAX_FREQ_COUNT];
+
mutex_init(&scale3d.lock);
INIT_WORK(&scale3d.work, scale3d_clocks_handler);
@@ -632,30 +868,74 @@ void nvhost_scale3d_init(struct nvhost_device *d)
POW2(scale3d.max_rate_3d - scale3d.emc_xmid);
scale3d.emc_dip_offset -= correction;
+ scale3d.is_idle = 1;
+
/* set scaling parameter defaults */
scale3d.enable = 1;
- scale3d.period = scale3d.p_period = 100000;
- scale3d.idle_min = scale3d.p_idle_min = 10;
- scale3d.idle_max = scale3d.p_idle_max = 15;
- scale3d.fast_response = scale3d.p_fast_response = 7000;
+ scale3d.idle_min = scale3d.p_idle_min = 100;
+ scale3d.idle_max = scale3d.p_idle_max = 150;
scale3d.p_scale_emc = 1;
scale3d.p_emc_dip = 1;
scale3d.p_verbosity = 0;
scale3d.p_adjust = 1;
+ scale3d.p_use_throughput_hint = 1;
+ scale3d.p_throughput_lower_limit = 940;
+ scale3d.p_throughput_lo_limit = 990;
+ scale3d.p_throughput_hi_limit = 1010;
+ scale3d.p_scale_step = 1;
+ scale3d.p_estimation_window = 8000;
+ scale3d.p_busy_cutoff = 750;
error = device_create_file(&d->dev,
&dev_attr_enable_3d_scaling);
if (error)
dev_err(&d->dev, "failed to create sysfs attributes");
+ rate = 0;
+ scale3d.freq_count = 0;
+ while (rate <= scale3d.max_rate_3d) {
+ long rounded_rate;
+ if (unlikely(scale3d.freq_count == MAX_FREQ_COUNT)) {
+ pr_err("%s: too many frequencies\n", __func__);
+ break;
+ }
+ rounded_rate =
+ clk_round_rate(scale3d.clk_3d, rate);
+ freqs[scale3d.freq_count++] = rounded_rate;
+ rate = rounded_rate + 2000;
+ }
+ scale3d.freqlist =
+ kmalloc(scale3d.freq_count * sizeof(int), GFP_KERNEL);
+ if (scale3d.freqlist == NULL)
+ pr_err("%s: can\'t allocate freq table\n", __func__);
+
+ memcpy(scale3d.freqlist, freqs,
+ scale3d.freq_count * sizeof(int));
+
+ busy_history = score_init(GR3D_FRAME_SPAN);
+ if (busy_history == NULL)
+ pr_err("%s: can\'t init load tracking array\n",
+ __func__);
+
+ hint_history = score_init(GR3D_FRAME_SPAN);
+ if (hint_history == NULL)
+ pr_err("%s: can\'t init throughput tracking array\n",
+ __func__);
+
scale3d.init = 1;
}
-
- nvhost_scale3d_reset();
}
void nvhost_scale3d_deinit(struct nvhost_device *dev)
{
device_remove_file(&dev->dev, &dev_attr_enable_3d_scaling);
scale3d.init = 0;
+ if (scale3d.freqlist != NULL) {
+ kfree(scale3d.freqlist);
+ scale3d.freq_count = 0;
+ scale3d.freqlist = NULL;
+ }
+
+ score_delete(busy_history);
+ score_delete(hint_history);
}
diff --git a/drivers/video/tegra/host/host1x/host1x.c b/drivers/video/tegra/host/host1x/host1x.c
index 33ebc1ff5d22..31899c78065b 100644
--- a/drivers/video/tegra/host/host1x/host1x.c
+++ b/drivers/video/tegra/host/host1x/host1x.c
@@ -308,6 +308,19 @@ static int power_off_host(struct nvhost_device *dev)
return 0;
}
+static void clock_on_host(struct nvhost_device *dev)
+{
+ struct nvhost_master *host = nvhost_get_drvdata(dev);
+ nvhost_intr_start(&host->intr, clk_get_rate(dev->clk[0]));
+}
+
+static int clock_off_host(struct nvhost_device *dev)
+{
+ struct nvhost_master *host = nvhost_get_drvdata(dev);
+ nvhost_intr_stop(&host->intr);
+ return 0;
+}
+
static int __devinit nvhost_user_init(struct nvhost_master *host)
{
int err, devno;
@@ -516,6 +529,8 @@ static struct nvhost_driver nvhost_driver = {
},
.finalize_poweron = power_on_host,
.prepare_poweroff = power_off_host,
+ .finalize_clockon = clock_on_host,
+ .prepare_clockoff = clock_off_host,
};
static int __init nvhost_mod_init(void)
diff --git a/drivers/video/tegra/host/host1x/host1x_cdma.c b/drivers/video/tegra/host/host1x/host1x_cdma.c
index 2e7ff5783a37..5a29ff652efe 100644
--- a/drivers/video/tegra/host/host1x/host1x_cdma.c
+++ b/drivers/video/tegra/host/host1x/host1x_cdma.c
@@ -233,12 +233,15 @@ static void cdma_timeout_cpu_incr(struct nvhost_cdma *cdma, u32 getptr,
/* after CPU incr, ensure shadow is up to date */
nvhost_syncpt_update_min(&dev->syncpt, cdma->timeout.syncpt_id);
- /* update WAITBASE_3D by same number of incrs */
- if (waitbases) {
+ /* Synchronize wait bases. 2D wait bases are synchronized with
+ * syncpoint 19. Hence wait bases are not updated when syncptid=18. */
+
+ if (cdma->timeout.syncpt_id != NVSYNCPT_2D_0 && waitbases) {
void __iomem *p;
p = dev->sync_aperture + host1x_sync_syncpt_base_0_r() +
- (ffs(waitbases) * sizeof(u32));
+ (__ffs(waitbases) * sizeof(u32));
writel(syncval, p);
+ dev->syncpt.base_val[__ffs(waitbases)] = syncval;
}
/* NOP all the PB slots */
@@ -486,7 +489,7 @@ static void cdma_timeout_handler(struct work_struct *work)
/* stop HW, resetting channel/module */
cdma_op().timeout_teardown_begin(cdma);
- nvhost_cdma_update_sync_queue(cdma, sp, dev->dev);
+ nvhost_cdma_update_sync_queue(cdma, sp, ch->dev);
mutex_unlock(&cdma->lock);
}
diff --git a/drivers/video/tegra/host/host1x/host1x_channel.c b/drivers/video/tegra/host/host1x/host1x_channel.c
index 9e9fc25dc966..0274413ff698 100644
--- a/drivers/video/tegra/host/host1x/host1x_channel.c
+++ b/drivers/video/tegra/host/host1x/host1x_channel.c
@@ -365,7 +365,7 @@ static int host1x_channel_read_3d_reg(
if (hwctx_to_save) {
syncpt_incrs += hwctx_to_save->save_incrs;
hwctx_to_save->hwctx.valid = true;
- channel->ctxhandler->get(&hwctx_to_save->hwctx);
+ nvhost_job_get_hwctx(job, &hwctx_to_save->hwctx);
}
channel->cur_ctx = hwctx;
if (channel->cur_ctx && channel->cur_ctx->valid) {
@@ -470,7 +470,8 @@ static int host1x_channel_read_3d_reg(
wait_event(wq,
nvhost_syncpt_is_expired(&nvhost_get_host(channel->dev)->syncpt,
p->syncpt, syncval - 2));
- nvhost_intr_put_ref(&nvhost_get_host(channel->dev)->intr, ref);
+ nvhost_intr_put_ref(&nvhost_get_host(channel->dev)->intr, p->syncpt,
+ ref);
/* Read the register value from FIFO */
err = host1x_drain_read_fifo(channel, value, 1, &pending);
@@ -580,7 +581,6 @@ static int host1x_save_context(struct nvhost_channel *ch)
}
hwctx_to_save->valid = true;
- ch->ctxhandler->get(hwctx_to_save);
ch->cur_ctx = NULL;
syncpt_id = to_host1x_hwctx_handler(hwctx_to_save->h)->syncpt;
@@ -623,7 +623,7 @@ static int host1x_save_context(struct nvhost_channel *ch)
nvhost_syncpt_is_expired(&nvhost_get_host(ch->dev)->syncpt,
syncpt_id, syncpt_val));
- nvhost_intr_put_ref(&nvhost_get_host(ch->dev)->intr, ref);
+ nvhost_intr_put_ref(&nvhost_get_host(ch->dev)->intr, syncpt_id, ref);
nvhost_cdma_update(&ch->cdma);
diff --git a/drivers/video/tegra/host/host1x/host1x_intr.c b/drivers/video/tegra/host/host1x/host1x_intr.c
index 62fd07cbb9ba..facb818a0c24 100644
--- a/drivers/video/tegra/host/host1x/host1x_intr.c
+++ b/drivers/video/tegra/host/host1x/host1x_intr.c
@@ -131,6 +131,16 @@ static void t20_intr_enable_syncpt_intr(struct nvhost_intr *intr, u32 id)
BIT_WORD(id) * REGISTER_STRIDE);
}
+static void t20_intr_disable_syncpt_intr(struct nvhost_intr *intr, u32 id)
+{
+ struct nvhost_master *dev = intr_to_dev(intr);
+ void __iomem *sync_regs = dev->sync_aperture;
+
+ writel(BIT_MASK(id), sync_regs +
+ host1x_sync_syncpt_thresh_int_disable_r() +
+ BIT_WORD(id) * REGISTER_STRIDE);
+}
+
static void t20_intr_disable_all_syncpt_intrs(struct nvhost_intr *intr)
{
struct nvhost_master *dev = intr_to_dev(intr);
@@ -140,7 +150,7 @@ static void t20_intr_disable_all_syncpt_intrs(struct nvhost_intr *intr)
for (reg = 0; reg <= BIT_WORD(dev->info.nb_pts) * REGISTER_STRIDE;
reg += REGISTER_STRIDE) {
/* disable interrupts for both cpu's */
- writel(0, sync_regs +
+ writel(0xffffffffu, sync_regs +
host1x_sync_syncpt_thresh_int_disable_r() +
reg);
@@ -276,6 +286,7 @@ static const struct nvhost_intr_ops host1x_intr_ops = {
.set_host_clocks_per_usec = t20_intr_set_host_clocks_per_usec,
.set_syncpt_threshold = t20_intr_set_syncpt_threshold,
.enable_syncpt_intr = t20_intr_enable_syncpt_intr,
+ .disable_syncpt_intr = t20_intr_disable_syncpt_intr,
.disable_all_syncpt_intrs = t20_intr_disable_all_syncpt_intrs,
.request_host_general_irq = t20_intr_request_host_general_irq,
.free_host_general_irq = t20_intr_free_host_general_irq,
diff --git a/drivers/video/tegra/host/mpe/mpe.c b/drivers/video/tegra/host/mpe/mpe.c
index c738700469c6..d76ee0108eef 100644
--- a/drivers/video/tegra/host/mpe/mpe.c
+++ b/drivers/video/tegra/host/mpe/mpe.c
@@ -212,7 +212,7 @@ struct save_info {
unsigned int restore_count;
};
-static void __init save_begin(struct host1x_hwctx_handler *h, u32 *ptr)
+static void save_begin(struct host1x_hwctx_handler *h, u32 *ptr)
{
/* MPE: when done, increment syncpt to base+1 */
ptr[0] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID, 0, 0);
@@ -229,7 +229,7 @@ static void __init save_begin(struct host1x_hwctx_handler *h, u32 *ptr)
}
#define SAVE_BEGIN_SIZE 5
-static void __init save_direct(u32 *ptr, u32 start_reg, u32 count)
+static void save_direct(u32 *ptr, u32 start_reg, u32 count)
{
ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
host1x_uclass_indoff_r(), 1);
@@ -239,7 +239,7 @@ static void __init save_direct(u32 *ptr, u32 start_reg, u32 count)
}
#define SAVE_DIRECT_SIZE 3
-static void __init save_set_ram_cmd(u32 *ptr, u32 cmd_reg, u32 count)
+static void save_set_ram_cmd(u32 *ptr, u32 cmd_reg, u32 count)
{
ptr[0] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID,
cmd_reg, 1);
@@ -247,7 +247,7 @@ static void __init save_set_ram_cmd(u32 *ptr, u32 cmd_reg, u32 count)
}
#define SAVE_SET_RAM_CMD_SIZE 2
-static void __init save_read_ram_data_nasty(u32 *ptr, u32 data_reg)
+static void save_read_ram_data_nasty(u32 *ptr, u32 data_reg)
{
ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
host1x_uclass_indoff_r(), 1);
@@ -261,7 +261,7 @@ static void __init save_read_ram_data_nasty(u32 *ptr, u32 data_reg)
}
#define SAVE_READ_RAM_DATA_NASTY_SIZE 5
-static void __init save_end(struct host1x_hwctx_handler *h, u32 *ptr)
+static void save_end(struct host1x_hwctx_handler *h, u32 *ptr)
{
/* Wait for context read service to finish (cpu incr 3) */
ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
@@ -275,7 +275,7 @@ static void __init save_end(struct host1x_hwctx_handler *h, u32 *ptr)
}
#define SAVE_END_SIZE 5
-static void __init setup_save_regs(struct save_info *info,
+static void setup_save_regs(struct save_info *info,
const struct hwctx_reginfo *regs,
unsigned int nr_regs)
{
@@ -304,7 +304,7 @@ static void __init setup_save_regs(struct save_info *info,
info->restore_count = restore_count;
}
-static void __init setup_save_ram_nasty(struct save_info *info, unsigned words,
+static void setup_save_ram_nasty(struct save_info *info, unsigned words,
unsigned cmd_reg, unsigned data_reg)
{
u32 *ptr = info->ptr;
@@ -330,7 +330,7 @@ static void __init setup_save_ram_nasty(struct save_info *info, unsigned words,
info->restore_count = restore_count;
}
-static void __init setup_save(struct host1x_hwctx_handler *h, u32 *ptr)
+static void setup_save(struct host1x_hwctx_handler *h, u32 *ptr)
{
struct save_info info = {
ptr,
@@ -553,7 +553,7 @@ struct nvhost_hwctx_handler *nvhost_mpe_ctxhandler_init(u32 syncpt,
p->save_buf = mem_op().alloc(memmgr, p->save_size * 4, 32,
mem_mgr_flag_write_combine);
- if (IS_ERR(p->save_buf)) {
+ if (IS_ERR_OR_NULL(p->save_buf)) {
p->save_buf = NULL;
return NULL;
}
diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c
index 06005c423a21..5bde55ad2ff5 100644
--- a/drivers/video/tegra/host/nvhost_acm.c
+++ b/drivers/video/tegra/host/nvhost_acm.c
@@ -101,8 +101,17 @@ void nvhost_module_reset(struct nvhost_device *dev)
static void to_state_clockgated_locked(struct nvhost_device *dev)
{
+ struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
+
if (dev->powerstate == NVHOST_POWER_STATE_RUNNING) {
- int i;
+ int i, err;
+ if (drv->prepare_clockoff) {
+ err = drv->prepare_clockoff(dev);
+ if (err) {
+ dev_err(&dev->dev, "error clock gating");
+ return;
+ }
+ }
for (i = 0; i < dev->num_clks; i++)
clk_disable(dev->clk[i]);
if (dev->dev.parent)
@@ -141,6 +150,14 @@ static void to_state_running_locked(struct nvhost_device *dev)
}
}
+ /* Invoke callback after enabling clock. This is used for
+ * re-enabling host1x interrupts. */
+ if (prev_state == NVHOST_POWER_STATE_CLOCKGATED
+ && drv->finalize_clockon)
+ drv->finalize_clockon(dev);
+
+ /* Invoke callback after power un-gating. This is used for
+ * restoring context. */
if (prev_state == NVHOST_POWER_STATE_POWERGATED
&& drv->finalize_poweron)
drv->finalize_poweron(dev);
@@ -343,15 +360,17 @@ void nvhost_module_remove_client(struct nvhost_device *dev, void *priv)
{
int i;
struct nvhost_module_client *m;
+ int found = 0;
mutex_lock(&client_list_lock);
list_for_each_entry(m, &dev->client_list, node) {
if (priv == m->priv) {
list_del(&m->node);
+ found = 1;
break;
}
}
- if (m) {
+ if (found) {
kfree(m);
for (i = 0; i < dev->num_clks; i++)
nvhost_module_update_rate(dev, i);
diff --git a/drivers/video/tegra/host/nvhost_intr.c b/drivers/video/tegra/host/nvhost_intr.c
index 38a04f151e87..9788d32bd4a9 100644
--- a/drivers/video/tegra/host/nvhost_intr.c
+++ b/drivers/video/tegra/host/nvhost_intr.c
@@ -210,7 +210,9 @@ static int process_wait_list(struct nvhost_intr *intr,
remove_completed_waiters(&syncpt->wait_head, threshold, completed);
empty = list_empty(&syncpt->wait_head);
- if (!empty)
+ if (empty)
+ intr_op().disable_syncpt_intr(intr, syncpt->id);
+ else
reset_threshold_interrupt(intr, &syncpt->wait_head,
syncpt->id);
@@ -327,14 +329,20 @@ void *nvhost_intr_alloc_waiter()
GFP_KERNEL|__GFP_REPEAT);
}
-void nvhost_intr_put_ref(struct nvhost_intr *intr, void *ref)
+void nvhost_intr_put_ref(struct nvhost_intr *intr, u32 id, void *ref)
{
struct nvhost_waitlist *waiter = ref;
+ struct nvhost_intr_syncpt *syncpt;
+ struct nvhost_master *host = intr_to_dev(intr);
while (atomic_cmpxchg(&waiter->state,
WLS_PENDING, WLS_CANCELLED) == WLS_REMOVED)
schedule();
+ syncpt = intr->syncpt + id;
+ (void)process_wait_list(intr, syncpt,
+ nvhost_syncpt_update_min(&host->syncpt, id));
+
kref_put(&waiter->refcount, waiter_release);
}
diff --git a/drivers/video/tegra/host/nvhost_intr.h b/drivers/video/tegra/host/nvhost_intr.h
index cf0b6b9e8934..d4a6157eced1 100644
--- a/drivers/video/tegra/host/nvhost_intr.h
+++ b/drivers/video/tegra/host/nvhost_intr.h
@@ -104,7 +104,7 @@ void *nvhost_intr_alloc_waiter(void);
* You must call this if you passed non-NULL as ref.
* @ref the ref returned from nvhost_intr_add_action()
*/
-void nvhost_intr_put_ref(struct nvhost_intr *intr, void *ref);
+void nvhost_intr_put_ref(struct nvhost_intr *intr, u32 id, void *ref);
int nvhost_intr_init(struct nvhost_intr *intr, u32 irq_gen, u32 irq_sync);
void nvhost_intr_deinit(struct nvhost_intr *intr);
diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c
index f93d7df1a552..f0f7e64d4504 100644
--- a/drivers/video/tegra/host/nvhost_job.c
+++ b/drivers/video/tegra/host/nvhost_job.c
@@ -34,19 +34,27 @@
/* Magic to use to fill freed handle slots */
#define BAD_MAGIC 0xdeadbeef
-static int job_size(struct nvhost_submit_hdr_ext *hdr)
+static size_t job_size(struct nvhost_submit_hdr_ext *hdr)
{
- int num_relocs = hdr ? hdr->num_relocs : 0;
- int num_waitchks = hdr ? hdr->num_waitchks : 0;
- int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
- int num_unpins = num_cmdbufs + num_relocs;
+ s64 num_relocs = hdr ? (int)hdr->num_relocs : 0;
+ s64 num_waitchks = hdr ? (int)hdr->num_waitchks : 0;
+ s64 num_cmdbufs = hdr ? (int)hdr->num_cmdbufs : 0;
+ s64 num_unpins = num_cmdbufs + num_relocs;
+ s64 total;
- return sizeof(struct nvhost_job)
+ if(num_relocs < 0 || num_waitchks < 0 || num_cmdbufs < 0)
+ return 0;
+
+ total = sizeof(struct nvhost_job)
+ num_relocs * sizeof(struct nvhost_reloc)
+ num_relocs * sizeof(struct nvhost_reloc_shift)
+ num_unpins * sizeof(struct mem_handle *)
+ num_waitchks * sizeof(struct nvhost_waitchk)
+ num_cmdbufs * sizeof(struct nvhost_job_gather);
+
+ if(total > ULONG_MAX)
+ return 0;
+ return (size_t)total;
}
static void init_fields(struct nvhost_job *job,
@@ -63,7 +71,11 @@ static void init_fields(struct nvhost_job *job,
job->priority = priority;
job->clientid = clientid;
- /* Redistribute memory to the structs */
+ /*
+ * Redistribute memory to the structs.
+ * Overflows and negative conditions have
+ * already been checked in job_alloc().
+ */
mem += sizeof(struct nvhost_job);
job->relocarray = num_relocs ? mem : NULL;
mem += num_relocs * sizeof(struct nvhost_reloc);
@@ -91,8 +103,11 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
int clientid)
{
struct nvhost_job *job = NULL;
+ size_t size = job_size(hdr);
- job = vzalloc(job_size(hdr));
+ if(!size)
+ goto error;
+ job = vzalloc(size);
if (!job)
goto error;
diff --git a/drivers/video/tegra/host/nvhost_syncpt.c b/drivers/video/tegra/host/nvhost_syncpt.c
index 9fa7d0652c1f..38c28ca116e7 100644
--- a/drivers/video/tegra/host/nvhost_syncpt.c
+++ b/drivers/video/tegra/host/nvhost_syncpt.c
@@ -235,7 +235,7 @@ int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id,
check_count++;
}
}
- nvhost_intr_put_ref(&(syncpt_to_dev(sp)->intr), ref);
+ nvhost_intr_put_ref(&(syncpt_to_dev(sp)->intr), id, ref);
done:
nvhost_module_idle(syncpt_to_dev(sp)->dev);
@@ -344,7 +344,7 @@ static ssize_t syncpt_min_show(struct kobject *kobj,
struct nvhost_syncpt_attr *syncpt_attr =
container_of(attr, struct nvhost_syncpt_attr, attr);
- return snprintf(buf, PAGE_SIZE, "%d",
+ return snprintf(buf, PAGE_SIZE, "%u",
nvhost_syncpt_read(&syncpt_attr->host->syncpt,
syncpt_attr->id));
}
@@ -355,7 +355,7 @@ static ssize_t syncpt_max_show(struct kobject *kobj,
struct nvhost_syncpt_attr *syncpt_attr =
container_of(attr, struct nvhost_syncpt_attr, attr);
- return snprintf(buf, PAGE_SIZE, "%d",
+ return snprintf(buf, PAGE_SIZE, "%u",
nvhost_syncpt_read_max(&syncpt_attr->host->syncpt,
syncpt_attr->id));
}
diff --git a/drivers/video/tegra/host/t30/t30.c b/drivers/video/tegra/host/t30/t30.c
index 0c8d626a4d67..334d598d5c0b 100644
--- a/drivers/video/tegra/host/t30/t30.c
+++ b/drivers/video/tegra/host/t30/t30.c
@@ -142,7 +142,7 @@ static struct nvhost_device tegra_gr2d02_device = {
.waitbases = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1),
.modulemutexes = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) |
BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B),
- .clocks = { {"gr2d", UINT_MAX},
+ .clocks = { {"gr2d", 0},
{"epp", 0},
{"emc", 300000000} },
NVHOST_MODULE_NO_POWERGATE_IDS,
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c
index b7fd695d04ee..a0dcf26337f8 100644
--- a/drivers/video/tegra/nvmap/nvmap.c
+++ b/drivers/video/tegra/nvmap/nvmap.c
@@ -3,7 +3,7 @@
*
* Memory manager for Tegra GPU
*
- * Copyright (c) 2009-2011, NVIDIA Corporation.
+ * Copyright (c) 2009-2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -271,7 +271,7 @@ int nvmap_pin_ids(struct nvmap_client *client,
* if the caller crashes after pinning a global handle, the handle
* will be permanently leaked. */
nvmap_ref_lock(client);
- for (i = 0; i < nr && !ret; i++) {
+ for (i = 0; i < nr; i++) {
ref = _nvmap_validate_id_locked(client, ids[i]);
if (ref) {
atomic_inc(&ref->pin);
@@ -280,19 +280,19 @@ int nvmap_pin_ids(struct nvmap_client *client,
struct nvmap_handle *verify;
nvmap_ref_unlock(client);
verify = nvmap_validate_get(client, ids[i]);
- if (verify)
+ if (verify) {
nvmap_warn(client, "%s pinning unreferenced "
"handle %p\n",
current->group_leader->comm, h[i]);
- else
+ } else {
+ h[i] = NULL;
ret = -EPERM;
+ }
nvmap_ref_lock(client);
}
}
nvmap_ref_unlock(client);
- nr = i;
-
if (ret)
goto out;
@@ -317,6 +317,9 @@ out:
if (ret) {
nvmap_ref_lock(client);
for (i = 0; i < nr; i++) {
+ if(!ids[i])
+ continue;
+
ref = _nvmap_validate_id_locked(client, ids[i]);
if (!ref) {
nvmap_warn(client, "%s freed handle %p "
@@ -330,7 +333,8 @@ out:
nvmap_ref_unlock(client);
for (i = 0; i < nr; i++)
- nvmap_handle_put(h[i]);
+ if(h[i])
+ nvmap_handle_put(h[i]);
}
return ret;
diff --git a/drivers/video/tegra/nvmap/nvmap_common.h b/drivers/video/tegra/nvmap/nvmap_common.h
index 6da010720bb2..2a1e2b4b3c4b 100644
--- a/drivers/video/tegra/nvmap/nvmap_common.h
+++ b/drivers/video/tegra/nvmap/nvmap_common.h
@@ -23,7 +23,8 @@
extern void v7_flush_kern_cache_all(void *);
extern void v7_clean_kern_cache_all(void *);
-#define FLUSH_CLEAN_BY_SET_WAY_THRESHOLD (8 * PAGE_SIZE)
+#define FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_INNER (8 * PAGE_SIZE)
+#define FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_OUTER (1024 * 1024)
static inline void inner_flush_cache_all(void)
{
diff --git a/drivers/video/tegra/nvmap/nvmap_dev.c b/drivers/video/tegra/nvmap/nvmap_dev.c
index 98b0bcc18ba5..0c12348db88e 100644
--- a/drivers/video/tegra/nvmap/nvmap_dev.c
+++ b/drivers/video/tegra/nvmap/nvmap_dev.c
@@ -290,7 +290,7 @@ int nvmap_flush_heap_block(struct nvmap_client *client,
if (prot == NVMAP_HANDLE_UNCACHEABLE || prot == NVMAP_HANDLE_WRITE_COMBINE)
goto out;
- if (len >= FLUSH_CLEAN_BY_SET_WAY_THRESHOLD) {
+ if (len >= FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_INNER) {
inner_flush_cache_all();
if (prot != NVMAP_HANDLE_INNER_CACHEABLE)
outer_flush_range(block->base, block->base + len);
@@ -886,10 +886,11 @@ static void nvmap_vma_open(struct vm_area_struct *vma)
struct nvmap_vma_priv *priv;
priv = vma->vm_private_data;
-
BUG_ON(!priv);
atomic_inc(&priv->count);
+ if(priv->handle)
+ nvmap_usecount_inc(priv->handle);
}
static void nvmap_vma_close(struct vm_area_struct *vma)
@@ -898,8 +899,8 @@ static void nvmap_vma_close(struct vm_area_struct *vma)
if (priv) {
if (priv->handle) {
+ BUG_ON(priv->handle->usecount == 0);
nvmap_usecount_dec(priv->handle);
- BUG_ON(priv->handle->usecount < 0);
}
if (!atomic_dec_return(&priv->count)) {
if (priv->handle)
diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c
index 05046ed8ba79..4b7760b22190 100644
--- a/drivers/video/tegra/nvmap/nvmap_handle.c
+++ b/drivers/video/tegra/nvmap/nvmap_handle.c
@@ -3,7 +3,7 @@
*
* Handle allocation and freeing routines for nvmap
*
- * Copyright (c) 2009-2012, NVIDIA Corporation.
+ * Copyright (c) 2009-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,6 +36,7 @@
#include <asm/cacheflush.h>
#include <asm/outercache.h>
+#include <asm/tlbflush.h>
#include <asm/pgtable.h>
#include <mach/iovmm.h>
@@ -56,7 +57,7 @@
* the kernel (i.e., not a carveout handle) includes its array of pages. to
* preserve kmalloc space, if the array of pages exceeds PAGELIST_VMALLOC_MIN,
* the array is allocated using vmalloc. */
-#define PAGELIST_VMALLOC_MIN (PAGE_SIZE * 2)
+#define PAGELIST_VMALLOC_MIN (PAGE_SIZE)
#ifdef CONFIG_NVMAP_PAGE_POOLS
@@ -85,8 +86,11 @@ static struct page *nvmap_page_pool_alloc_locked(struct nvmap_page_pool *pool)
{
struct page *page = NULL;
- if (pool->npages > 0)
+ if (pool->npages > 0) {
page = pool->page_array[--pool->npages];
+ atomic_dec(&page->_count);
+ BUG_ON(atomic_read(&page->_count) != 1);
+ }
return page;
}
@@ -107,7 +111,9 @@ static bool nvmap_page_pool_release_locked(struct nvmap_page_pool *pool,
{
int ret = false;
+ BUG_ON(atomic_read(&page->_count) != 1);
if (enable_pp && pool->npages < pool->max_pages) {
+ atomic_inc(&page->_count);
pool->page_array[pool->npages++] = page;
ret = true;
}
@@ -134,6 +140,7 @@ static int nvmap_page_pool_get_available_count(struct nvmap_page_pool *pool)
static int nvmap_page_pool_free(struct nvmap_page_pool *pool, int nr_free)
{
+ int err;
int i = nr_free;
int idx = 0;
struct page *page;
@@ -149,8 +156,12 @@ static int nvmap_page_pool_free(struct nvmap_page_pool *pool, int nr_free)
i--;
}
- if (idx)
- set_pages_array_wb(pool->shrink_array, idx);
+ if (idx) {
+ /* This op should never fail. */
+ err = set_pages_array_wb(pool->shrink_array, idx);
+ BUG_ON(err);
+ }
+
while (idx--)
__free_page(pool->shrink_array[idx]);
nvmap_page_pool_unlock(pool);
@@ -367,8 +378,9 @@ POOL_SIZE_MOUDLE_PARAM_CB(wb, NVMAP_HANDLE_CACHEABLE);
int nvmap_page_pool_init(struct nvmap_page_pool *pool, int flags)
{
- struct page *page;
int i;
+ int err;
+ struct page *page;
static int reg = 1;
struct sysinfo info;
int highmem_pages = 0;
@@ -431,7 +443,8 @@ int nvmap_page_pool_init(struct nvmap_page_pool *pool, int flags)
s_memtype_str[flags], highmem_pages, pool->max_pages,
info.totalram, info.freeram, info.totalhigh, info.freehigh);
do_cpa:
- (*s_cpa[flags])(pool->page_array, pool->npages);
+ err = (*s_cpa[flags])(pool->page_array, pool->npages);
+ BUG_ON(err);
nvmap_page_pool_unlock(pool);
return 0;
fail:
@@ -444,7 +457,7 @@ fail:
static inline void *altalloc(size_t len)
{
- if (len >= PAGELIST_VMALLOC_MIN)
+ if (len > PAGELIST_VMALLOC_MIN)
return vmalloc(len);
else
return kmalloc(len, GFP_KERNEL);
@@ -455,7 +468,7 @@ static inline void altfree(void *ptr, size_t len)
if (!ptr)
return;
- if (len >= PAGELIST_VMALLOC_MIN)
+ if (len > PAGELIST_VMALLOC_MIN)
vfree(ptr);
else
kfree(ptr);
@@ -463,6 +476,7 @@ static inline void altfree(void *ptr, size_t len)
void _nvmap_handle_free(struct nvmap_handle *h)
{
+ int err;
struct nvmap_share *share = nvmap_get_share_from_dev(h->dev);
unsigned int i, nr_page, page_index = 0;
#ifdef CONFIG_NVMAP_PAGE_POOLS
@@ -506,9 +520,12 @@ void _nvmap_handle_free(struct nvmap_handle *h)
/* Restore page attributes. */
if (h->flags == NVMAP_HANDLE_WRITE_COMBINE ||
h->flags == NVMAP_HANDLE_UNCACHEABLE ||
- h->flags == NVMAP_HANDLE_INNER_CACHEABLE)
- set_pages_array_wb(&h->pgalloc.pages[page_index],
+ h->flags == NVMAP_HANDLE_INNER_CACHEABLE) {
+ /* This op should never fail. */
+ err = set_pages_array_wb(&h->pgalloc.pages[page_index],
nr_page - page_index);
+ BUG_ON(err);
+ }
skip_attr_restore:
if (h->pgalloc.area)
@@ -546,6 +563,7 @@ static struct page *nvmap_alloc_pages_exact(gfp_t gfp, size_t size)
static int handle_page_alloc(struct nvmap_client *client,
struct nvmap_handle *h, bool contiguous)
{
+ int err = 0;
size_t size = PAGE_ALIGN(h->size);
unsigned int nr_page = size >> PAGE_SHIFT;
pgprot_t prot;
@@ -555,6 +573,17 @@ static int handle_page_alloc(struct nvmap_client *client,
struct nvmap_page_pool *pool = NULL;
struct nvmap_share *share = nvmap_get_share_from_dev(h->dev);
#endif
+ gfp_t gfp = GFP_NVMAP;
+ unsigned long kaddr, paddr;
+ pte_t **pte = NULL;
+
+ if (h->userflags & NVMAP_HANDLE_ZEROED_PAGES) {
+ gfp |= __GFP_ZERO;
+ prot = nvmap_pgprot(h, pgprot_kernel);
+ pte = nvmap_alloc_pte(client->dev, (void **)&kaddr);
+ if (IS_ERR(pte))
+ return -ENOMEM;
+ }
pages = altalloc(nr_page * sizeof(*pages));
if (!pages)
@@ -565,7 +594,7 @@ static int handle_page_alloc(struct nvmap_client *client,
h->pgalloc.area = NULL;
if (contiguous) {
struct page *page;
- page = nvmap_alloc_pages_exact(GFP_NVMAP, size);
+ page = nvmap_alloc_pages_exact(gfp, size);
if (!page)
goto fail;
@@ -582,12 +611,29 @@ static int handle_page_alloc(struct nvmap_client *client,
pages[i] = nvmap_page_pool_alloc(pool);
if (!pages[i])
break;
+ if (h->userflags & NVMAP_HANDLE_ZEROED_PAGES) {
+ /*
+ * Just memset low mem pages; they will for
+ * sure have a virtual address. Otherwise, build
+ * a mapping for the page in the kernel.
+ */
+ if (!PageHighMem(pages[i])) {
+ memset(page_address(pages[i]), 0,
+ PAGE_SIZE);
+ } else {
+ paddr = page_to_phys(pages[i]);
+ set_pte_at(&init_mm, kaddr, *pte,
+ pfn_pte(__phys_to_pfn(paddr),
+ prot));
+ flush_tlb_kernel_page(kaddr);
+ memset((char *)kaddr, 0, PAGE_SIZE);
+ }
+ }
page_index++;
}
#endif
for (; i < nr_page; i++) {
- pages[i] = nvmap_alloc_pages_exact(GFP_NVMAP,
- PAGE_SIZE);
+ pages[i] = nvmap_alloc_pages_exact(gfp, PAGE_SIZE);
if (!pages[i])
goto fail;
}
@@ -608,16 +654,21 @@ static int handle_page_alloc(struct nvmap_client *client,
/* Update the pages mapping in kernel page table. */
if (h->flags == NVMAP_HANDLE_WRITE_COMBINE)
- set_pages_array_wc(&pages[page_index],
- nr_page - page_index);
+ err = set_pages_array_wc(&pages[page_index],
+ nr_page - page_index);
else if (h->flags == NVMAP_HANDLE_UNCACHEABLE)
- set_pages_array_uc(&pages[page_index],
- nr_page - page_index);
+ err = set_pages_array_uc(&pages[page_index],
+ nr_page - page_index);
else if (h->flags == NVMAP_HANDLE_INNER_CACHEABLE)
- set_pages_array_iwb(&pages[page_index],
- nr_page - page_index);
+ err = set_pages_array_iwb(&pages[page_index],
+ nr_page - page_index);
+
+ if (err)
+ goto fail;
skip_attr_change:
+ if (h->userflags & NVMAP_HANDLE_ZEROED_PAGES)
+ nvmap_free_pte(client->dev, pte);
h->size = size;
h->pgalloc.pages = pages;
h->pgalloc.contig = contiguous;
@@ -625,10 +676,12 @@ skip_attr_change:
return 0;
fail:
- while (i--) {
- set_pages_array_wb(&pages[i], 1);
+ if (h->userflags & NVMAP_HANDLE_ZEROED_PAGES)
+ nvmap_free_pte(client->dev, pte);
+ err = set_pages_array_wb(pages, i);
+ BUG_ON(err);
+ while (i--)
__free_page(pages[i]);
- }
altfree(pages, nr_page * sizeof(*pages));
wmb();
return -ENOMEM;
diff --git a/drivers/video/tegra/nvmap/nvmap_heap.c b/drivers/video/tegra/nvmap/nvmap_heap.c
index a6fe78c42f87..738ba26232d3 100644
--- a/drivers/video/tegra/nvmap/nvmap_heap.c
+++ b/drivers/video/tegra/nvmap/nvmap_heap.c
@@ -3,7 +3,7 @@
*
* GPU heap allocator.
*
- * Copyright (c) 2011, NVIDIA Corporation.
+ * Copyright (c) 2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -420,6 +420,9 @@ static struct nvmap_heap_block *do_heap_alloc(struct nvmap_heap *heap,
list_for_each_entry(i, &heap->free_list, free_list) {
size_t fix_size;
fix_base = ALIGN(i->block.base, align);
+ if(!fix_base || fix_base >= i->block.base + i->size)
+ continue;
+
fix_size = i->size - (fix_base - i->block.base);
/* needed for compaction. relocated chunk
diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c
index 44f00d2951a0..da974b2c6846 100644
--- a/drivers/video/tegra/nvmap/nvmap_ioctl.c
+++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c
@@ -3,7 +3,7 @@
*
* User-space interface to nvmap
*
- * Copyright (c) 2011, NVIDIA Corporation.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -65,10 +65,10 @@ int nvmap_ioctl_pinop(struct file *filp, bool is_pin, void __user *arg)
return -EINVAL;
if (op.count > 1) {
- size_t bytes = op.count * sizeof(unsigned long *);
+ size_t bytes = op.count * sizeof(*refs); /* kcalloc below will catch overflow. */
if (op.count > ARRAY_SIZE(on_stack))
- refs = kmalloc(op.count * sizeof(*refs), GFP_KERNEL);
+ refs = kcalloc(op.count, sizeof(*refs), GFP_KERNEL);
else
refs = on_stack;
@@ -175,6 +175,9 @@ int nvmap_ioctl_alloc(struct file *filp, void __user *arg)
/* user-space handles are aligned to page boundaries, to prevent
* data leakage. */
op.align = max_t(size_t, op.align, PAGE_SIZE);
+#if defined(CONFIG_NVMAP_FORCE_ZEROED_USER_PAGES)
+ op.flags |= NVMAP_HANDLE_ZEROED_PAGES;
+#endif
return nvmap_alloc_handle_id(client, op.handle, op.heap_mask,
op.align, op.flags);
@@ -236,6 +239,11 @@ int nvmap_map_into_caller_ptr(struct file *filp, void __user *arg)
if (!h)
return -EPERM;
+ if(!h->alloc) {
+ nvmap_handle_put(h);
+ return -EFAULT;
+ }
+
trace_nvmap_map_into_caller_ptr(client, h, op.offset,
op.length, op.flags);
down_read(&current->mm->mmap_sem);
@@ -251,7 +259,7 @@ int nvmap_map_into_caller_ptr(struct file *filp, void __user *arg)
goto out;
}
- if ((op.offset + op.length) > h->size) {
+ if (op.offset > h->size || (op.offset + op.length) > h->size) {
err = -EADDRNOTAVAIL;
goto out;
}
@@ -542,14 +550,32 @@ static void heap_page_cache_maint(struct nvmap_client *client,
}
}
+static bool fast_cache_maint_outer(unsigned long start,
+ unsigned long end, unsigned int op)
+{
+ bool result = false;
+#if defined(CONFIG_NVMAP_OUTER_CACHE_MAINT_BY_SET_WAYS)
+ if (end - start >= FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_OUTER) {
+ if (op == NVMAP_CACHE_OP_WB_INV) {
+ outer_flush_all();
+ result = true;
+ }
+ if (op == NVMAP_CACHE_OP_WB) {
+ outer_clean_all();
+ result = true;
+ }
+ }
+#endif
+ return result;
+}
+
static bool fast_cache_maint(struct nvmap_client *client, struct nvmap_handle *h,
unsigned long start, unsigned long end, unsigned int op)
{
int ret = false;
-
#if defined(CONFIG_NVMAP_CACHE_MAINT_BY_SET_WAYS)
if ((op == NVMAP_CACHE_OP_INV) ||
- ((end - start) < FLUSH_CLEAN_BY_SET_WAY_THRESHOLD))
+ ((end - start) < FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_INNER))
goto out;
if (op == NVMAP_CACHE_OP_WB_INV)
@@ -557,13 +583,19 @@ static bool fast_cache_maint(struct nvmap_client *client, struct nvmap_handle *h
else if (op == NVMAP_CACHE_OP_WB)
inner_clean_cache_all();
- if (h->heap_pgalloc && (h->flags != NVMAP_HANDLE_INNER_CACHEABLE)) {
- heap_page_cache_maint(client, h, start, end, op,
- false, true, NULL, 0, 0);
- } else if (h->flags != NVMAP_HANDLE_INNER_CACHEABLE) {
- start += h->carveout->base;
- end += h->carveout->base;
- outer_cache_maint(op, start, end - start);
+ /* outer maintenance */
+ if (h->flags != NVMAP_HANDLE_INNER_CACHEABLE ) {
+ if(!fast_cache_maint_outer(start, end, op))
+ {
+ if (h->heap_pgalloc) {
+ heap_page_cache_maint(client, h, start,
+ end, op, false, true, NULL, 0, 0);
+ } else {
+ start += h->carveout->base;
+ end += h->carveout->base;
+ outer_cache_maint(op, start, end - start);
+ }
+ }
}
ret = true;
out:
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile
index 96499dce0b94..1f05328a7013 100644
--- a/drivers/w1/masters/Makefile
+++ b/drivers/w1/masters/Makefile
@@ -11,4 +11,5 @@ obj-$(CONFIG_W1_MASTER_MXC) += mxc_w1.o
obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o
obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o
obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o
+CFLAGS_tegra_w1.o = -Werror
obj-$(CONFIG_W1_MASTER_TEGRA) += tegra_w1.o
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index dd35599a2612..9c6cc30bb905 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
obj-$(CONFIG_DW_WATCHDOG) += dw_wdt.o
obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
+CFLAGS_tegra_wdt.o = -Werror
obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
diff --git a/drivers/watchdog/tegra_wdt.c b/drivers/watchdog/tegra_wdt.c
index 0d8373efd3f1..1bcd726ebbd6 100644
--- a/drivers/watchdog/tegra_wdt.c
+++ b/drivers/watchdog/tegra_wdt.c
@@ -330,11 +330,11 @@ static const struct file_operations tegra_wdt_fops = {
static int tegra_wdt_probe(struct platform_device *pdev)
{
- struct resource *res_src, *res_wdt, *res_irq, *res_int_base;
+ struct resource *res_src, *res_wdt, *res_irq;
+ struct resource *res_int_base = NULL;
struct tegra_wdt *wdt;
u32 src;
int ret = 0;
- u32 val = 0;
if (pdev->id < -1 && pdev->id > 3) {
dev_err(&pdev->dev, "only IDs 3:0 supported\n");
@@ -469,6 +469,7 @@ static int tegra_wdt_probe(struct platform_device *pdev)
#ifdef CONFIG_TEGRA_WATCHDOG_ENABLE_ON_PROBE
/* Init and enable watchdog on WDT0 with timer 8 during probe */
if (!(pdev->id)) {
+ u32 val = 0;
wdt->status = WDT_ENABLED | WDT_ENABLED_AT_PROBE;
wdt->timeout = heartbeat;
tegra_wdt_enable(wdt);