This is the initial port of OpenBSD's athn(4) driver. It supports
quite a few Atheros 802.11n devices. See the athn(4) manpage for a list. This port has only been tested with a TP-LINK TL-WN722N USB adapter which has an AR9271 chipset (VENDOR: 0x0cf3, PRODUCT: 0x9271). The BSS, Monitor, and HostAP modes all seem to work on that adapter, though the later has not been tested much. The driver also supports PCI and CardBUS devices, but those interfaces are completely untested and probably won't work at this point. If someone can provide me with other adapters that should be supported, particularly PCI or CardBUS adapters, or tell me where I can get one cheaply, I would be happy to try to get the driver working on those devices as well.
This commit is contained in:
parent
5aab19183e
commit
64f896110c
257
share/man/man4/athn.4
Normal file
257
share/man/man4/athn.4
Normal file
@ -0,0 +1,257 @@
|
||||
.\" $NetBSD: athn.4,v 1.1 2013/03/30 02:53:00 christos Exp $
|
||||
.\" $OpenBSD: athn.4,v 1.21 2012/09/17 11:04:24 sthen Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>.
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and 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.
|
||||
.\"
|
||||
.Dd $Mdocdate: August 25 2012 $
|
||||
.Dt ATHN 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm athn
|
||||
.Nd Atheros IEEE 802.11a/g/n wireless network device
|
||||
.Sh SYNOPSIS
|
||||
.Cd "athn* at cardbus?"
|
||||
.Cd "athn* at pci?"
|
||||
.Cd "athn* at uhub? port ?"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
driver provides support for a wide variety of
|
||||
Atheros 802.11n devices, ranging from the AR5008 up to the AR9287.
|
||||
.Pp
|
||||
The AR5008 (codenamed Owl) is the first generation of
|
||||
Atheros 802.11n solutions.
|
||||
It consists of two chips, a MAC/Baseband Processor and a Radio-on-a-Chip.
|
||||
The MAC/Baseband Processor can be an AR5416 (PCI and CardBus form factors)
|
||||
or an AR5418 (PCIe Mini Card form factor).
|
||||
The radio can be an AR2122, AR2133, AR5122 or an AR5133 chip.
|
||||
The AR2122 chip operates in the 2GHz spectrum and supports up to 2
|
||||
transmit paths and 2 receiver paths (2T2R).
|
||||
The AR2133 chip operates in the 2GHz spectrum and supports up to 3
|
||||
transmit paths and 3 receiver paths (3T3R).
|
||||
The AR5122 chip operates in the 2GHz and 5GHz spectra and supports
|
||||
up to 2 transmit paths and 2 receiver paths (2T2R).
|
||||
The AR5133 chip operates in the 2GHz and 5GHz spectra and supports
|
||||
up to 3 transmit paths and 3 receiver paths (3T3R).
|
||||
.Pp
|
||||
The AR9001 (codenamed Sowl) is a Mini-PCI 802.11n solution.
|
||||
It consists of two chips, an AR9160 MAC/Baseband Processor and an
|
||||
AR9103 or AR9106 Radio-on-a-Chip.
|
||||
The AR9103 chip operates in the 2GHz spectrum and supports up to 3
|
||||
transmit paths and 3 receiver paths (3T3R).
|
||||
The AR9106 chip operates in the 2GHz and 5GHz spectra and supports
|
||||
up to 3 transmit paths and 3 receiver paths (3T3R).
|
||||
.Pp
|
||||
The AR9220, AR9223 and AR9280 (codenamed Merlin) are the
|
||||
first generation of
|
||||
Atheros single-chip 802.11n solutions.
|
||||
The AR9220 and AR9223 exist in PCI and Mini-PCI form factors.
|
||||
The AR9280 exists in PCIe Mini Card (XB92), half Mini Card (HB92)
|
||||
and USB 2.0 (AR9280+AR7010) form factors.
|
||||
The AR9220 and AR9280 operate in the 2GHz and 5GHz spectra and
|
||||
support 2 transmit paths and 2 receiver paths (2T2R).
|
||||
The AR9223 operates in the 2GHz spectrum and supports 2
|
||||
transmit paths and 2 receiver paths (2T2R).
|
||||
.Pp
|
||||
The AR9281 is a single-chip PCIe 802.11n solution.
|
||||
It exists in PCIe Mini Card (XB91) and half Mini Card (HB91) form
|
||||
factors.
|
||||
It operates in the 2GHz spectrum and supports 1 transmit path and
|
||||
2 receiver paths (1T2R).
|
||||
.Pp
|
||||
The AR9285 (codenamed Kite) is a single-chip PCIe 802.11n solution that
|
||||
targets the value PC market.
|
||||
It exists in PCIe half Mini Card (HB95) form factor only.
|
||||
It operates in the 2GHz spectrum and supports a single stream (1T1R).
|
||||
It can be combined with the AR3011 chip to form a combo WiFi/Bluetooth
|
||||
device (WB195).
|
||||
.Pp
|
||||
The AR9271 is a single-chip USB 2.0 802.11n solution.
|
||||
It operates in the 2GHz spectrum and supports a single stream (1T1R).
|
||||
.Pp
|
||||
The AR2427 is a single-chip PCIe 802.11b/g solution similar to the other
|
||||
AR9280 solutions but with 802.11n capabilities removed.
|
||||
It exists in PCIe Mini Card form factor only.
|
||||
It operates in the 2GHz spectrum.
|
||||
.Pp
|
||||
The AR9227 and AR9287 are single-chip 802.11n solutions that
|
||||
target mid-tier PCs.
|
||||
The AR9227 exists in PCI and Mini-PCI form factors.
|
||||
The AR9287 exists in PCIe half Mini Card (HB97)
|
||||
and USB 2.0 (AR9287+AR7010) form factors.
|
||||
They operate in the 2GHz spectrum and support 2 transmit paths and 2
|
||||
receiver paths (2T2R).
|
||||
.Pp
|
||||
The following table summarizes the supported chips and their capabilities.
|
||||
.Bl -column "AR9001-3NX2 (AR9160+AR9106)" "2GHz/5GHz" "3x3:3" "PCI/CardBus" -offset 6n
|
||||
.It Em Chipset Ta Em Spectrum Ta Em TxR:S Ta Em Bus
|
||||
.It "AR5008-2NG (AR5416+AR2122)" Ta 2GHz Ta 2x2:2 Ta PCI/CardBus
|
||||
.It "AR5008-3NG (AR5416+AR2133)" Ta 2GHz Ta 3x3:2 Ta PCI/CardBus
|
||||
.It "AR5008-2NX (AR5416+AR5122)" Ta 2GHz/5GHz Ta 2x2:2 Ta PCI/CardBus
|
||||
.It "AR5008-3NX (AR5416+AR5133)" Ta 2GHz/5GHz Ta 3x3:2 Ta PCI/CardBus
|
||||
.It "AR5008E-2NG (AR5418+AR2122)" Ta 2GHz Ta 2x2:2 Ta PCIe
|
||||
.It "AR5008E-3NG (AR5418+AR2133)" Ta 2GHz Ta 3x3:2 Ta PCIe
|
||||
.It "AR5008E-2NX (AR5418+AR5122)" Ta 2GHz/5GHz Ta 2x2:2 Ta PCIe
|
||||
.It "AR5008E-3NX (AR5418+AR5133)" Ta 2GHz/5GHz Ta 3x3:2 Ta PCIe
|
||||
.It "AR9001-2NG (AR9160+AR9103)" Ta 2GHz Ta 2x2:2 Ta PCI
|
||||
.It "AR9001-3NG (AR9160+AR9103)" Ta 2GHz Ta 3x3:2 Ta PCI
|
||||
.It "AR9001-3NX2 (AR9160+AR9106)" Ta 2GHz/5GHz Ta 3x3:2 Ta PCI
|
||||
.It "AR9220" Ta 2GHz/5GHz Ta 2x2:2 Ta PCI
|
||||
.It "AR9223" Ta 2GHz Ta 2x2:2 Ta PCI
|
||||
.It "AR9280" Ta 2GHz/5GHz Ta 2x2:2 Ta PCIe
|
||||
.It "AR9280+AR7010" Ta 2GHz/5GHz Ta 2x2:2 Ta USB 2.0
|
||||
.It "AR9281" Ta 2GHz Ta 1x2:2 Ta PCIe
|
||||
.It "AR9285" Ta 2GHz Ta 1x1:1 Ta PCIe
|
||||
.It "AR9271" Ta 2GHz Ta 1x1:1 Ta USB 2.0
|
||||
.It "AR2427" Ta 2GHz Ta 1x1:1 Ta PCIe
|
||||
.It "AR9227" Ta 2GHz Ta 2x2:2 Ta PCI
|
||||
.It "AR9287" Ta 2GHz Ta 2x2:2 Ta PCIe
|
||||
.It "AR9287+AR7010" Ta 2GHz Ta 2x2:2 Ta USB 2.0
|
||||
.El
|
||||
.Pp
|
||||
These are the modes the
|
||||
.Nm
|
||||
driver can operate in:
|
||||
.Bl -tag -width "IBSS-masterXX"
|
||||
.It BSS mode
|
||||
Also known as
|
||||
.Em infrastructure
|
||||
mode, this is used when associating with an access point, through
|
||||
which all traffic passes.
|
||||
This mode is the default.
|
||||
.It Host AP
|
||||
In this mode the driver acts as an access point (base station)
|
||||
for other cards.
|
||||
.It monitor mode
|
||||
In this mode the driver is able to receive packets without
|
||||
associating with an access point.
|
||||
This disables the internal receive filter and enables the card to
|
||||
capture packets from networks which it wouldn't normally have access to,
|
||||
or to scan for access points.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
driver can be configured to use
|
||||
Wired Equivalent Privacy (WEP) or
|
||||
Wi-Fi Protected Access (WPA-PSK and WPA2-PSK).
|
||||
WPA is the de facto encryption standard for wireless networks.
|
||||
It is strongly recommended that WEP
|
||||
not be used as the sole mechanism
|
||||
to secure wireless communication,
|
||||
due to serious weaknesses in it.
|
||||
The
|
||||
.Nm
|
||||
driver relies on the software 802.11 stack for both encryption and decryption
|
||||
of data frames.
|
||||
.\" driver offloads encryption and decryption to the hardware for the WEP40,
|
||||
.\" WEP104, TKIP(+MIC) and CCMP ciphers.
|
||||
.Pp
|
||||
The transmit speed is user-selectable or can be adapted automatically by the
|
||||
driver depending on the number of hardware transmission retries.
|
||||
.Sh FILES
|
||||
For USB devices, the driver needs at least version 1.1 of the following
|
||||
firmware files, which are loaded when an interface is attached:
|
||||
.Pp
|
||||
.Bl -tag -width Ds -offset indent -compact
|
||||
.It /etc/firmware/athn-ar7010
|
||||
.It /etc/firmware/athn-ar7010-11
|
||||
.It /etc/firmware/athn-ar9271
|
||||
.El
|
||||
.Pp
|
||||
A prepackaged version of the firmware can be installed using
|
||||
.Xr fw_update 1 .
|
||||
.Sh EXAMPLES
|
||||
The following
|
||||
.Xr hostname.if 5
|
||||
example configures athn0 to join whatever network is available on boot,
|
||||
using WEP key
|
||||
.Dq 0x1deadbeef1 ,
|
||||
channel 11, obtaining an IP address using DHCP:
|
||||
.Bd -literal -offset indent
|
||||
dhcp NONE NONE NONE nwkey 0x1deadbeef1 chan 11
|
||||
.Ed
|
||||
.Pp
|
||||
The following
|
||||
.Xr hostname.if 5
|
||||
example creates a host-based access point on boot:
|
||||
.Bd -literal -offset indent
|
||||
inet 192.168.1.1 255.255.255.0 NONE media autoselect \e
|
||||
mediaopt hostap nwid my_net chan 11
|
||||
.Ed
|
||||
.Pp
|
||||
Configure athn0 to join network
|
||||
.Dq my_net
|
||||
using WPA with passphrase
|
||||
.Dq my_passphrase :
|
||||
.Bd -literal -offset indent
|
||||
# ifconfig athn0 nwid my_net wpakey my_passphrase
|
||||
.Ed
|
||||
.Pp
|
||||
Join an existing BSS network,
|
||||
.Dq my_net :
|
||||
.Bd -literal -offset indent
|
||||
# ifconfig athn0 192.168.1.1 netmask 0xffffff00 nwid my_net
|
||||
.Ed
|
||||
.Sh DIAGNOSTICS
|
||||
.Bl -diag
|
||||
.It "athn%d: device timeout"
|
||||
A frame dispatched to the hardware for transmission did not complete in time.
|
||||
The driver will reset the hardware.
|
||||
This should not happen.
|
||||
.It "athn%d: radio is disabled by hardware switch"
|
||||
The radio transmitter is off and thus no packet can go out.
|
||||
The driver will reset the hardware.
|
||||
Make sure the laptop radio switch is on.
|
||||
.It "athn%d: radio switch turned off"
|
||||
The radio switch has been turned off while the interface was up and running.
|
||||
The driver will turn the interface down.
|
||||
.It "athn%d: error %d, could not read firmware %s"
|
||||
For some reason, the driver was unable to read the firmware file from the
|
||||
filesystem.
|
||||
The file might be missing or corrupted.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr arp 4 ,
|
||||
.Xr cardbus 4 ,
|
||||
.Xr ifmedia 4 ,
|
||||
.Xr intro 4 ,
|
||||
.Xr netintro 4 ,
|
||||
.Xr pci 4 ,
|
||||
.Xr usb 4 ,
|
||||
.Xr hostname.if 5 ,
|
||||
.Xr ifconfig 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
driver first appeared in
|
||||
.Ox 4.7 .
|
||||
Support for USB 2.0 devices first appeared in
|
||||
.Ox 4.9 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
driver was written by
|
||||
.An Damien Bergamini Aq damien@openbsd.org
|
||||
based on source code licensed under the ISC released in 2008 by
|
||||
Atheros Communications for Linux.
|
||||
.Sh CAVEATS
|
||||
The
|
||||
.Nm
|
||||
driver does not support any of the 802.11n capabilities offered by
|
||||
the adapters.
|
||||
Additional work is required in
|
||||
.Xr ieee80211 9
|
||||
before those features can be supported.
|
366
sys/dev/cardbus/if_athn_cardbus.c
Normal file
366
sys/dev/cardbus/if_athn_cardbus.c
Normal file
@ -0,0 +1,366 @@
|
||||
/* $NetBSD: if_athn_cardbus.c,v 1.1 2013/03/30 02:53:00 christos Exp $ */
|
||||
/* $OpenBSD: if_athn_cardbus.c,v 1.13 2011/01/08 10:02:32 damien Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
|
||||
*
|
||||
* Permission to use, copy, modify, and 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* CardBus front-end for Atheros 802.11a/g/n chipsets.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_athn_cardbus.c,v 1.1 2013/03/30 02:53:00 christos Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/intr.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_amrr.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/ic/athnreg.h>
|
||||
#include <dev/ic/athnvar.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcidevs.h>
|
||||
|
||||
#include <dev/cardbus/cardbusvar.h>
|
||||
|
||||
/*
|
||||
* PCI configuration space registers
|
||||
*/
|
||||
#define ATHN_PCI_MMBA PCI_BAR(0) /* memory mapped base */
|
||||
|
||||
struct athn_cardbus_softc {
|
||||
struct athn_softc csc_sc;
|
||||
|
||||
/* CardBus specific goo. */
|
||||
cardbus_devfunc_t csc_ct;
|
||||
pcitag_t csc_tag;
|
||||
void *csc_ih;
|
||||
bus_space_tag_t csc_iot;
|
||||
bus_space_handle_t csc_ioh;
|
||||
bus_size_t csc_mapsz;
|
||||
pcireg_t csc_bar_val;
|
||||
};
|
||||
|
||||
#define Static static
|
||||
|
||||
Static int athn_cardbus_match(device_t, cfdata_t, void *);
|
||||
Static void athn_cardbus_attach(device_t, device_t, void *);
|
||||
Static int athn_cardbus_detach(device_t, int);
|
||||
|
||||
CFATTACH_DECL_NEW(athn_cardbus, sizeof(struct athn_cardbus_softc),
|
||||
athn_cardbus_match, athn_cardbus_attach, athn_cardbus_detach, NULL);
|
||||
|
||||
Static uint32_t athn_cardbus_read(struct athn_softc *, uint32_t);
|
||||
Static bool athn_cardbus_resume(device_t, const pmf_qual_t *l);
|
||||
Static void athn_cardbus_setup(struct athn_cardbus_softc *);
|
||||
Static bool athn_cardbus_suspend(device_t, const pmf_qual_t *);
|
||||
Static void athn_cardbus_write(struct athn_softc *, uint32_t, uint32_t);
|
||||
Static void athn_cardbus_write_barrier(struct athn_softc *);
|
||||
|
||||
#ifdef openbsd_power_management
|
||||
Static int athn_cardbus_enable(struct athn_softc *);
|
||||
Static void athn_cardbus_disable(struct athn_softc *);
|
||||
Static void athn_cardbus_power(struct athn_softc *, int);
|
||||
#endif /* openbsd_power_management */
|
||||
|
||||
Static int
|
||||
athn_cardbus_match(device_t parent, cfdata_t match, void *aux)
|
||||
{
|
||||
static const struct {
|
||||
pci_vendor_id_t vendor;
|
||||
pci_product_id_t product;
|
||||
} athn_cardbus_devices[] = {
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5416 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5418 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9160 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9280 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9281 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9285 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR2427 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9227 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9287 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9300 }
|
||||
};
|
||||
struct cardbus_attach_args *ca = aux;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < __arraycount(athn_cardbus_devices); i++) {
|
||||
if (PCI_VENDOR(ca->ca_id) == athn_cardbus_devices[i].vendor &&
|
||||
PCI_VENDOR(ca->ca_id) == athn_cardbus_devices[i].product)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Static void
|
||||
athn_cardbus_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct athn_cardbus_softc *csc = device_private(self);
|
||||
struct athn_softc *sc = &csc->csc_sc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct cardbus_attach_args *ca = aux;
|
||||
cardbus_devfunc_t ct = ca->ca_ct;
|
||||
bus_addr_t base;
|
||||
int error;
|
||||
|
||||
sc->sc_dmat = ca->ca_dmat;
|
||||
csc->csc_ct = ct;
|
||||
csc->csc_tag = ca->ca_tag;
|
||||
|
||||
aprint_normal("\n");
|
||||
aprint_naive("\n");
|
||||
|
||||
#ifdef openbsd_power_management
|
||||
/* Power management hooks. */
|
||||
sc->sc_enable = athn_cardbus_enable;
|
||||
sc->sc_disable = athn_cardbus_disable;
|
||||
sc->sc_power = athn_cardbus_power;
|
||||
#endif
|
||||
sc->sc_ops.read = athn_cardbus_read;
|
||||
sc->sc_ops.write = athn_cardbus_write;
|
||||
sc->sc_ops.write_barrier = athn_cardbus_write_barrier;
|
||||
|
||||
/*
|
||||
* Map control/status registers.
|
||||
*/
|
||||
error = Cardbus_mapreg_map(ct, ATHN_PCI_MMBA, PCI_MAPREG_TYPE_MEM, 0,
|
||||
&csc->csc_iot, &csc->csc_ioh, &base, &csc->csc_mapsz);
|
||||
if (error != 0) {
|
||||
aprint_error_dev(self, "unable to map device (%d)\n", error);
|
||||
return;
|
||||
}
|
||||
csc->csc_bar_val = base | PCI_MAPREG_TYPE_MEM;
|
||||
|
||||
/*
|
||||
* Set up the PCI configuration registers.
|
||||
*/
|
||||
athn_cardbus_setup(csc);
|
||||
|
||||
if (athn_attach(sc) != 0) {
|
||||
Cardbus_mapreg_unmap(ct, ATHN_PCI_MMBA, csc->csc_iot,
|
||||
csc->csc_ioh, csc->csc_mapsz);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pmf_device_register(self,
|
||||
athn_cardbus_suspend, athn_cardbus_resume)) {
|
||||
pmf_class_network_register(self, &sc->sc_if);
|
||||
pmf_device_suspend(self, &sc->sc_qual);
|
||||
} else
|
||||
aprint_error_dev(self, "couldn't establish power handler\n");
|
||||
|
||||
// Cardbus_function_disable(ct);
|
||||
|
||||
ieee80211_announce(ic);
|
||||
}
|
||||
|
||||
Static int
|
||||
athn_cardbus_detach(device_t self, int flags)
|
||||
{
|
||||
struct athn_cardbus_softc *csc = device_private(self);
|
||||
struct athn_softc *sc = &csc->csc_sc;
|
||||
cardbus_devfunc_t ct = csc->csc_ct;
|
||||
cardbus_chipset_tag_t cc = ct->ct_cc;
|
||||
cardbus_function_tag_t cf = ct->ct_cf;
|
||||
|
||||
athn_detach(sc);
|
||||
|
||||
pmf_device_deregister(self);
|
||||
|
||||
/* Unhook the interrupt handler. */
|
||||
if (csc->csc_ih != NULL)
|
||||
cardbus_intr_disestablish(cc, cf, csc->csc_ih);
|
||||
|
||||
/* Release bus space and close window. */
|
||||
Cardbus_mapreg_unmap(ct, ATHN_PCI_MMBA, csc->csc_iot, csc->csc_ioh,
|
||||
csc->csc_mapsz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Static void
|
||||
athn_cardbus_setup(struct athn_cardbus_softc *csc)
|
||||
{
|
||||
cardbus_devfunc_t ct = csc->csc_ct;
|
||||
#ifdef unneeded /* XXX */
|
||||
pci_chipset_tag_t pc = csc->csc_pc;
|
||||
cardbus_chipset_tag_t cc = ct->ct_cc;
|
||||
cardbus_function_tag_t cf = ct->ct_cf;
|
||||
#endif
|
||||
pcireg_t reg;
|
||||
int rc;
|
||||
|
||||
if ((rc = cardbus_set_powerstate(ct, csc->csc_tag, PCI_PWR_D0)) != 0)
|
||||
aprint_debug("%s: cardbus_set_powerstate %d\n", __func__, rc);
|
||||
|
||||
/* Program the BAR. */
|
||||
Cardbus_conf_write(ct, csc->csc_tag, ATHN_PCI_MMBA, csc->csc_bar_val);
|
||||
|
||||
#ifdef unneeded /* XXX */
|
||||
/* Make sure the right access type is on the cardbus bridge. */
|
||||
(*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
|
||||
(*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
|
||||
#endif
|
||||
/* Enable the appropriate bits in the PCI CSR. */
|
||||
reg = Cardbus_conf_read(ct, csc->csc_tag, PCI_COMMAND_STATUS_REG);
|
||||
reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE;
|
||||
Cardbus_conf_write(ct, csc->csc_tag, PCI_COMMAND_STATUS_REG, reg);
|
||||
|
||||
/*
|
||||
* Noone knows why this shit is necessary but there are claims that
|
||||
* not doing this may cause very frequent PCI FATAL interrupts from
|
||||
* the card: http://bugzilla.kernel.org/show_bug.cgi?id=13483
|
||||
*/
|
||||
reg = Cardbus_conf_read(ct, csc->csc_tag, 0x40);
|
||||
if (reg & 0xff00)
|
||||
Cardbus_conf_write(ct, csc->csc_tag, 0x40, reg & ~0xff00);
|
||||
|
||||
/* Change latency timer; default value yields poor results. */
|
||||
reg = Cardbus_conf_read(ct, csc->csc_tag, PCI_BHLC_REG);
|
||||
reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
|
||||
reg |= 168 << PCI_LATTIMER_SHIFT;
|
||||
Cardbus_conf_write(ct, csc->csc_tag, PCI_BHLC_REG, reg);
|
||||
}
|
||||
|
||||
Static uint32_t
|
||||
athn_cardbus_read(struct athn_softc *sc, uint32_t addr)
|
||||
{
|
||||
struct athn_cardbus_softc *csc = (struct athn_cardbus_softc *)sc;
|
||||
|
||||
return bus_space_read_4(csc->csc_iot, csc->csc_ioh, addr);
|
||||
}
|
||||
|
||||
Static void
|
||||
athn_cardbus_write(struct athn_softc *sc, uint32_t addr, uint32_t val)
|
||||
{
|
||||
struct athn_cardbus_softc *csc = (struct athn_cardbus_softc *)sc;
|
||||
|
||||
bus_space_write_4(csc->csc_iot, csc->csc_ioh, addr, val);
|
||||
}
|
||||
|
||||
Static void
|
||||
athn_cardbus_write_barrier(struct athn_softc *sc)
|
||||
{
|
||||
struct athn_cardbus_softc *csc = (struct athn_cardbus_softc *)sc;
|
||||
|
||||
bus_space_barrier(csc->csc_iot, csc->csc_ioh, 0, csc->csc_mapsz,
|
||||
BUS_SPACE_BARRIER_WRITE);
|
||||
}
|
||||
|
||||
Static bool
|
||||
athn_cardbus_suspend(device_t self, const pmf_qual_t *qual)
|
||||
{
|
||||
struct athn_cardbus_softc *csc = device_private(self);
|
||||
|
||||
athn_suspend(&csc->csc_sc);
|
||||
if (csc->csc_ih != NULL) {
|
||||
Cardbus_intr_disestablish(csc->csc_ct, csc->csc_ih);
|
||||
csc->csc_ih = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Static bool
|
||||
athn_cardbus_resume(device_t self, const pmf_qual_t *qual)
|
||||
{
|
||||
struct athn_cardbus_softc *csc = device_private(self);
|
||||
|
||||
csc->csc_ih = Cardbus_intr_establish(csc->csc_ct, IPL_NET, athn_intr,
|
||||
&csc->csc_sc);
|
||||
|
||||
if (csc->csc_ih == NULL) {
|
||||
aprint_error_dev(self,
|
||||
"unable to establish interrupt\n");
|
||||
return false;
|
||||
}
|
||||
return athn_resume(&csc->csc_sc);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* XXX: presumably the pmf_* stuff handles this.
|
||||
*/
|
||||
#ifdef openbsd_power_management
|
||||
Static int
|
||||
athn_cardbus_enable(struct athn_softc *sc)
|
||||
{
|
||||
struct athn_cardbus_softc *csc = (struct athn_cardbus_softc *)sc;
|
||||
cardbus_devfunc_t ct = csc->csc_ct;
|
||||
cardbus_chipset_tag_t cc = ct->ct_cc;
|
||||
cardbus_function_tag_t cf = ct->ct_cf;
|
||||
|
||||
/* Power on the socket. */
|
||||
Cardbus_function_enable(ct);
|
||||
|
||||
/* Setup the PCI configuration registers. */
|
||||
athn_cardbus_setup(csc);
|
||||
|
||||
/* Map and establish the interrupt handler. */
|
||||
csc->csc_ih = cardbus_intr_establish(cc, cf, IPL_NET, athn_intr, sc);
|
||||
if (csc->csc_ih == NULL) {
|
||||
printf("%s: could not establish interrupt at %d\n",
|
||||
device_xname(sc->sc_dev), csc->csc_intrline);
|
||||
Cardbus_function_disable(ct);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Static void
|
||||
athn_cardbus_disable(struct athn_softc *sc)
|
||||
{
|
||||
struct athn_cardbus_softc *csc = (struct athn_cardbus_softc *)sc;
|
||||
cardbus_devfunc_t ct = csc->csc_ct;
|
||||
cardbus_chipset_tag_t cc = ct->ct_cc;
|
||||
cardbus_function_tag_t cf = ct->ct_cf;
|
||||
|
||||
/* Unhook the interrupt handler. */
|
||||
cardbus_intr_disestablish(cc, cf, csc->csc_ih);
|
||||
csc->csc_ih = NULL;
|
||||
|
||||
/* Power down the socket. */
|
||||
Cardbus_function_disable(ct);
|
||||
}
|
||||
|
||||
Static void
|
||||
athn_cardbus_power(struct athn_softc *sc, int why)
|
||||
{
|
||||
struct athn_cardbus_softc *csc = (struct athn_cardbus_softc *)sc;
|
||||
|
||||
if (why == DVACT_RESUME) {
|
||||
/* Restore the PCI configuration registers. */
|
||||
athn_cardbus_setup(csc);
|
||||
}
|
||||
}
|
||||
#endif /* openbsd_power_management */
|
2780
sys/dev/ic/arn5008.c
Normal file
2780
sys/dev/ic/arn5008.c
Normal file
File diff suppressed because it is too large
Load Diff
45
sys/dev/ic/arn5008.h
Normal file
45
sys/dev/ic/arn5008.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* $NetBSD: arn5008.h,v 1.1 2013/03/30 02:53:00 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _IF_ARN5008_H_
|
||||
#define _IF_ARN5008_H_
|
||||
|
||||
#include <dev/ic/arn5008reg.h>
|
||||
|
||||
int ar5008_attach(struct athn_softc *);
|
||||
void ar5008_write_txpower(struct athn_softc *, int16_t power[]);
|
||||
void ar5008_set_viterbi_mask(struct athn_softc *, int);
|
||||
void ar5008_get_pdadcs(struct athn_softc *, uint8_t, struct athn_pier *,
|
||||
struct athn_pier *, int, int, uint8_t, uint8_t *, uint8_t *);
|
||||
|
||||
void ar5008_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *,
|
||||
uint8_t, const struct ar_cal_target_power_ht *, int, uint8_t[]);
|
||||
void ar5008_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *,
|
||||
uint8_t, const struct ar_cal_target_power_leg *, int, uint8_t[]);
|
||||
|
||||
|
||||
#endif /* _IF_ARN5008_H_ */
|
1028
sys/dev/ic/arn5008reg.h
Normal file
1028
sys/dev/ic/arn5008reg.h
Normal file
File diff suppressed because it is too large
Load Diff
963
sys/dev/ic/arn5416.c
Normal file
963
sys/dev/ic/arn5416.c
Normal file
@ -0,0 +1,963 @@
|
||||
/* $NetBSD: arn5416.c,v 1.1 2013/03/30 02:53:00 christos Exp $ */
|
||||
/* $OpenBSD: ar5416.c,v 1.12 2012/06/10 21:23:36 kettenis Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Driver for Atheros 802.11a/g/n chipsets.
|
||||
* Routines for AR5416, AR5418 and AR9160 chipsets.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: arn5416.c,v 1.1 2013/03/30 02:53:00 christos Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/intr.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_amrr.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/ic/athnreg.h>
|
||||
#include <dev/ic/athnvar.h>
|
||||
|
||||
#include <dev/ic/arn5008reg.h>
|
||||
#include <dev/ic/arn5008.h>
|
||||
#include <dev/ic/arn5416reg.h>
|
||||
#include <dev/ic/arn5416.h>
|
||||
#include <dev/ic/arn9280.h>
|
||||
|
||||
#define Static static
|
||||
|
||||
Static void ar5416_force_bias(struct athn_softc *,
|
||||
struct ieee80211_channel *);
|
||||
Static void ar5416_get_pdadcs(struct athn_softc *,
|
||||
struct ieee80211_channel *, int, int, uint8_t, uint8_t *,
|
||||
uint8_t *);
|
||||
Static void ar5416_init_from_rom(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static uint8_t ar5416_reverse_bits(uint8_t, int);
|
||||
Static void ar5416_rw_bank6tpc(struct athn_softc *,
|
||||
struct ieee80211_channel *, uint32_t *);
|
||||
Static void ar5416_rw_rfbits(uint32_t *, int, int, uint32_t, int);
|
||||
Static void ar5416_set_power_calib(struct athn_softc *,
|
||||
struct ieee80211_channel *);
|
||||
Static int ar5416_set_synth(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar5416_setup(struct athn_softc *);
|
||||
Static void ar5416_spur_mitigate(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9160_rw_addac(struct athn_softc *,
|
||||
struct ieee80211_channel *, uint32_t *);
|
||||
|
||||
PUBLIC int
|
||||
ar5416_attach(struct athn_softc *sc)
|
||||
{
|
||||
sc->sc_eep_base = AR5416_EEP_START_LOC;
|
||||
sc->sc_eep_size = sizeof(struct ar5416_eeprom);
|
||||
sc->sc_def_nf = AR5416_PHY_CCA_MAX_GOOD_VALUE;
|
||||
sc->sc_ngpiopins = 14;
|
||||
sc->sc_led_pin = 1;
|
||||
sc->sc_workaround = AR5416_WA_DEFAULT;
|
||||
sc->sc_ops.setup = ar5416_setup;
|
||||
sc->sc_ops.swap_rom = ar5416_swap_rom;
|
||||
sc->sc_ops.init_from_rom = ar5416_init_from_rom;
|
||||
sc->sc_ops.set_txpower = ar5416_set_txpower;
|
||||
sc->sc_ops.set_synth = ar5416_set_synth;
|
||||
sc->sc_ops.spur_mitigate = ar5416_spur_mitigate;
|
||||
sc->sc_ops.get_spur_chans = ar5416_get_spur_chans;
|
||||
if (AR_SREV_9160_10_OR_LATER(sc))
|
||||
sc->sc_ini = &ar9160_ini;
|
||||
else
|
||||
sc->sc_ini = &ar5416_ini;
|
||||
sc->sc_serdes = &ar5416_serdes;
|
||||
|
||||
return ar5008_attach(sc);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar5416_setup(struct athn_softc *sc)
|
||||
{
|
||||
/* Select ADDAC programming. */
|
||||
if (AR_SREV_9160_11(sc))
|
||||
sc->sc_addac = &ar9160_1_1_addac;
|
||||
else if (AR_SREV_9160_10_OR_LATER(sc))
|
||||
sc->sc_addac = &ar9160_1_0_addac;
|
||||
else if (AR_SREV_5416_22_OR_LATER(sc))
|
||||
sc->sc_addac = &ar5416_2_2_addac;
|
||||
else
|
||||
sc->sc_addac = &ar5416_2_1_addac;
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar5416_swap_rom(struct athn_softc *sc)
|
||||
{
|
||||
struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
struct ar5416_modal_eep_header *modal;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 2; i++) { /* Dual-band. */
|
||||
modal = &eep->modalHeader[i];
|
||||
|
||||
modal->antCtrlCommon = bswap32(modal->antCtrlCommon);
|
||||
for (j = 0; j < AR5416_MAX_CHAINS; j++) {
|
||||
modal->antCtrlChain[j] =
|
||||
bswap32(modal->antCtrlChain[j]);
|
||||
}
|
||||
for (j = 0; j < AR_EEPROM_MODAL_SPURS; j++) {
|
||||
modal->spurChans[j].spurChan =
|
||||
bswap16(modal->spurChans[j].spurChan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PUBLIC const struct ar_spur_chan *
|
||||
ar5416_get_spur_chans(struct athn_softc *sc, int is2ghz)
|
||||
{
|
||||
const struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
|
||||
return eep->modalHeader[is2ghz].spurChans;
|
||||
}
|
||||
|
||||
Static int
|
||||
ar5416_set_synth(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
uint32_t phy, reg;
|
||||
uint32_t freq = c->ic_freq;
|
||||
uint8_t chansel;
|
||||
|
||||
phy = 0;
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
if (((freq - 2192) % 5) == 0) {
|
||||
chansel = ((freq - 672) * 2 - 3040) / 10;
|
||||
}
|
||||
else if (((freq - 2224) % 5) == 0) {
|
||||
chansel = ((freq - 704) * 2 - 3040) / 10;
|
||||
phy |= AR5416_BMODE_SYNTH;
|
||||
}
|
||||
else
|
||||
return EINVAL;
|
||||
chansel <<= 2;
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_CCK_TX_CTRL);
|
||||
if (freq == 2484) /* Channel 14. */
|
||||
reg |= AR_PHY_CCK_TX_CTRL_JAPAN;
|
||||
else
|
||||
reg &= ~AR_PHY_CCK_TX_CTRL_JAPAN;
|
||||
AR_WRITE(sc, AR_PHY_CCK_TX_CTRL, reg);
|
||||
|
||||
/* Fix for orientation sensitivity issue. */
|
||||
if (AR_SREV_5416(sc))
|
||||
ar5416_force_bias(sc, c);
|
||||
}
|
||||
else {
|
||||
if (freq >= 5120 && (freq % 20) == 0) {
|
||||
chansel = (freq - 4800) / 20;
|
||||
chansel <<= 2;
|
||||
phy |= SM(AR5416_AMODE_REFSEL, 2);
|
||||
}
|
||||
else if ((freq % 10) == 0) {
|
||||
chansel = (freq - 4800) / 10;
|
||||
chansel <<= 1;
|
||||
if (AR_SREV_9160_10_OR_LATER(sc))
|
||||
phy |= SM(AR5416_AMODE_REFSEL, 1);
|
||||
else
|
||||
phy |= SM(AR5416_AMODE_REFSEL, 2);
|
||||
}
|
||||
else if ((freq % 5) == 0) {
|
||||
chansel = (freq - 4800) / 5;
|
||||
phy |= SM(AR5416_AMODE_REFSEL, 2);
|
||||
}
|
||||
else
|
||||
return EINVAL;
|
||||
}
|
||||
chansel = ar5416_reverse_bits(chansel, 8);
|
||||
phy |= chansel << 8 | 1 << 5 | 1;
|
||||
DPRINTFN(DBG_RF, sc, "AR_PHY(0x37)=0x%08x\n", phy);
|
||||
AR_WRITE(sc, AR_PHY(0x37), phy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Static void
|
||||
ar5416_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
|
||||
const struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
const struct ar5416_modal_eep_header *modal;
|
||||
uint32_t reg, offset;
|
||||
uint8_t txRxAtten;
|
||||
int i;
|
||||
|
||||
modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
|
||||
|
||||
AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon);
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
if (AR_SREV_5416_20_OR_LATER(sc) &&
|
||||
(sc->sc_rxchainmask == 0x5 || sc->sc_txchainmask == 0x5))
|
||||
offset = chainoffset[i];
|
||||
else
|
||||
offset = i * 0x1000;
|
||||
|
||||
AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0 + offset,
|
||||
modal->antCtrlChain[i]);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0 + offset);
|
||||
reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
|
||||
modal->iqCalICh[i]);
|
||||
reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
|
||||
modal->iqCalQCh[i]);
|
||||
AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0 + offset, reg);
|
||||
|
||||
if (i > 0 && !AR_SREV_5416_20_OR_LATER(sc))
|
||||
continue;
|
||||
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3) {
|
||||
reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_BSW_MARGIN,
|
||||
modal->bswMargin[i]);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_BSW_ATTEN,
|
||||
modal->bswAtten[i]);
|
||||
AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
|
||||
}
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3)
|
||||
txRxAtten = modal->txRxAttenCh[i];
|
||||
else /* Workaround for ROM versions < 14.3. */
|
||||
txRxAtten = IEEE80211_IS_CHAN_2GHZ(c) ? 23 : 44;
|
||||
reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
|
||||
reg = RW(reg, AR_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
|
||||
AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_RXTX_MARGIN,
|
||||
modal->rxTxMarginCh[i]);
|
||||
AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
|
||||
}
|
||||
reg = AR_READ(sc, AR_PHY_SETTLING);
|
||||
reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
|
||||
AR_WRITE(sc, AR_PHY_SETTLING, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
|
||||
reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
|
||||
reg = RW(reg, AR_PHY_DESIRED_SZ_PGA, modal->pgaDesiredSize);
|
||||
AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
|
||||
|
||||
reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
|
||||
reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
|
||||
reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
|
||||
reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_RF_CTL3);
|
||||
reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_CCA(0));
|
||||
reg = RW(reg, AR_PHY_CCA_THRESH62, modal->thresh62);
|
||||
AR_WRITE(sc, AR_PHY_CCA(0), reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_EXT_CCA(0));
|
||||
reg = RW(reg, AR_PHY_EXT_CCA_THRESH62, modal->thresh62);
|
||||
AR_WRITE(sc, AR_PHY_EXT_CCA(0), reg);
|
||||
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2) {
|
||||
reg = AR_READ(sc, AR_PHY_RF_CTL2);
|
||||
reg = RW(reg, AR_PHY_TX_END_DATA_START,
|
||||
modal->txFrameToDataStart);
|
||||
reg = RW(reg, AR_PHY_TX_END_PA_ON, modal->txFrameToPaOn);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
|
||||
}
|
||||
#ifndef IEEE80211_NO_HT
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
|
||||
/* Overwrite switch settling with HT-40 value. */
|
||||
reg = AR_READ(sc, AR_PHY_SETTLING);
|
||||
reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
|
||||
AR_WRITE(sc, AR_PHY_SETTLING, reg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PUBLIC int
|
||||
ar5416_init_calib(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
int ntries;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(sc)) {
|
||||
/* XXX Linux tests AR9287?! */
|
||||
AR_CLRBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
|
||||
AR_SETBITS(sc, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_FLTR_CAL);
|
||||
}
|
||||
/* Calibrate the AGC. */
|
||||
AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
|
||||
/* Poll for offset calibration completion. */
|
||||
for (ntries = 0; ntries < 10000; ntries++) {
|
||||
if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) &
|
||||
AR_PHY_AGC_CONTROL_CAL))
|
||||
break;
|
||||
DELAY(10);
|
||||
}
|
||||
if (ntries == 10000)
|
||||
return ETIMEDOUT;
|
||||
if (AR_SREV_9280_10_OR_LATER(sc)) {
|
||||
AR_SETBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
|
||||
AR_CLRBITS(sc, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_FLTR_CAL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Static void
|
||||
ar5416_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
int chain, int nxpdgains, uint8_t overlap, uint8_t *boundaries,
|
||||
uint8_t *pdadcs)
|
||||
{
|
||||
const struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
const struct ar5416_cal_data_per_freq *pierdata;
|
||||
const uint8_t *pierfreq;
|
||||
struct athn_pier lopier, hipier;
|
||||
int16_t delta;
|
||||
uint8_t fbin, pwroff;
|
||||
int i, lo, hi, npiers;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
pierfreq = eep->calFreqPier2G;
|
||||
pierdata = eep->calPierData2G[chain];
|
||||
npiers = AR5416_NUM_2G_CAL_PIERS;
|
||||
}
|
||||
else {
|
||||
pierfreq = eep->calFreqPier5G;
|
||||
pierdata = eep->calPierData5G[chain];
|
||||
npiers = AR5416_NUM_5G_CAL_PIERS;
|
||||
}
|
||||
/* Find channel in ROM pier table. */
|
||||
fbin = athn_chan2fbin(c);
|
||||
athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
|
||||
|
||||
lopier.fbin = pierfreq[lo];
|
||||
hipier.fbin = pierfreq[hi];
|
||||
for (i = 0; i < nxpdgains; i++) {
|
||||
lopier.pwr[i] = pierdata[lo].pwrPdg[i];
|
||||
lopier.vpd[i] = pierdata[lo].vpdPdg[i];
|
||||
hipier.pwr[i] = pierdata[lo].pwrPdg[i];
|
||||
hipier.vpd[i] = pierdata[lo].vpdPdg[i];
|
||||
}
|
||||
ar5008_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains,
|
||||
AR5416_PD_GAIN_ICEPTS, overlap, boundaries, pdadcs);
|
||||
|
||||
if (!AR_SREV_9280_20_OR_LATER(sc))
|
||||
return;
|
||||
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_21)
|
||||
pwroff = eep->baseEepHeader.pwrTableOffset;
|
||||
else
|
||||
pwroff = AR_PWR_TABLE_OFFSET_DB;
|
||||
delta = (pwroff - AR_PWR_TABLE_OFFSET_DB) * 2; /* In half dB. */
|
||||
|
||||
/* Change the original gain boundaries setting. */
|
||||
for (i = 0; i < nxpdgains; i++) {
|
||||
/* XXX Possible overflows? */
|
||||
boundaries[i] -= delta;
|
||||
if (boundaries[i] > AR_MAX_RATE_POWER - overlap)
|
||||
boundaries[i] = AR_MAX_RATE_POWER - overlap;
|
||||
}
|
||||
if (delta != 0) {
|
||||
/* Shift the PDADC table to start at the new offset. */
|
||||
for (i = 0; i < AR_NUM_PDADC_VALUES; i++)
|
||||
pdadcs[i] = pdadcs[MIN(i + delta,
|
||||
AR_NUM_PDADC_VALUES - 1)];
|
||||
}
|
||||
}
|
||||
|
||||
Static void
|
||||
ar5416_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
|
||||
const struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
const struct ar5416_modal_eep_header *modal;
|
||||
uint8_t boundaries[AR_PD_GAINS_IN_MASK];
|
||||
uint8_t pdadcs[AR_NUM_PDADC_VALUES];
|
||||
uint8_t xpdgains[AR5416_NUM_PD_GAINS];
|
||||
uint8_t overlap, txgain;
|
||||
uint32_t reg, offset;
|
||||
int i, j, nxpdgains;
|
||||
|
||||
modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
|
||||
|
||||
if (sc->sc_eep_rev < AR_EEP_MINOR_VER_2) {
|
||||
overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),
|
||||
AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
|
||||
}
|
||||
else
|
||||
overlap = modal->pdGainOverlap;
|
||||
|
||||
if ((sc->sc_flags & ATHN_FLAG_OLPC) && IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
/* XXX not here. */
|
||||
sc->sc_pdadc =
|
||||
((const struct ar_cal_data_per_freq_olpc *)
|
||||
eep->calPierData2G[0])->vpdPdg[0][0];
|
||||
}
|
||||
|
||||
nxpdgains = 0;
|
||||
memset(xpdgains, 0, sizeof(xpdgains));
|
||||
for (i = AR5416_PD_GAINS_IN_MASK - 1; i >= 0; i--) {
|
||||
if (nxpdgains >= AR5416_NUM_PD_GAINS)
|
||||
break; /* Can't happen. */
|
||||
if (modal->xpdGain & (1 << i))
|
||||
xpdgains[nxpdgains++] = i;
|
||||
}
|
||||
reg = AR_READ(sc, AR_PHY_TPCRG1);
|
||||
reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1);
|
||||
reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0]);
|
||||
reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1]);
|
||||
reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_3, xpdgains[2]);
|
||||
AR_WRITE(sc, AR_PHY_TPCRG1, reg);
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
if (!(sc->sc_txchainmask & (1 << i)))
|
||||
continue;
|
||||
|
||||
if (AR_SREV_5416_20_OR_LATER(sc) &&
|
||||
(sc->sc_rxchainmask == 0x5 || sc->sc_txchainmask == 0x5))
|
||||
offset = chainoffset[i];
|
||||
else
|
||||
offset = i * 0x1000;
|
||||
|
||||
if (sc->sc_flags & ATHN_FLAG_OLPC) {
|
||||
ar9280_olpc_get_pdadcs(sc, c, i, boundaries,
|
||||
pdadcs, &txgain);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_0);
|
||||
reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
|
||||
AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_0, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_1);
|
||||
reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
|
||||
AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_1, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TX_PWRCTRL7);
|
||||
reg = RW(reg, AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, txgain);
|
||||
AR_WRITE(sc, AR_PHY_TX_PWRCTRL7, reg);
|
||||
|
||||
overlap = 6;
|
||||
}
|
||||
else {
|
||||
ar5416_get_pdadcs(sc, c, i, nxpdgains, overlap,
|
||||
boundaries, pdadcs);
|
||||
}
|
||||
/* Write boundaries. */
|
||||
if (i == 0 || AR_SREV_5416_20_OR_LATER(sc)) {
|
||||
reg = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP,
|
||||
overlap);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1,
|
||||
boundaries[0]);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2,
|
||||
boundaries[1]);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3,
|
||||
boundaries[2]);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4,
|
||||
boundaries[3]);
|
||||
AR_WRITE(sc, AR_PHY_TPCRG5 + offset, reg);
|
||||
}
|
||||
/* Write PDADC values. */
|
||||
for (j = 0; j < AR_NUM_PDADC_VALUES; j += 4) {
|
||||
AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + offset + j,
|
||||
pdadcs[j + 0] << 0 |
|
||||
pdadcs[j + 1] << 8 |
|
||||
pdadcs[j + 2] << 16 |
|
||||
pdadcs[j + 3] << 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar5416_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
const struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
const struct ar5416_modal_eep_header *modal;
|
||||
uint8_t tpow_cck[4], tpow_ofdm[4];
|
||||
#ifndef IEEE80211_NO_HT
|
||||
uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4];
|
||||
uint8_t tpow_ht20[8], tpow_ht40[8];
|
||||
uint8_t ht40inc;
|
||||
#endif
|
||||
int16_t pwr = 0, pwroff, max_ant_gain, power[ATHN_POWER_COUNT];
|
||||
uint8_t cckinc;
|
||||
int i;
|
||||
|
||||
ar5416_set_power_calib(sc, c);
|
||||
|
||||
modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
|
||||
|
||||
/* Compute transmit power reduction due to antenna gain. */
|
||||
max_ant_gain = MAX(modal->antennaGainCh[0], modal->antennaGainCh[1]);
|
||||
max_ant_gain = MAX(modal->antennaGainCh[2], max_ant_gain);
|
||||
/* XXX */
|
||||
|
||||
/*
|
||||
* Reduce scaled power by number of active chains to get per-chain
|
||||
* transmit power level.
|
||||
*/
|
||||
if (sc->sc_ntxchains == 2)
|
||||
pwr -= AR_PWR_DECREASE_FOR_2_CHAIN;
|
||||
else if (sc->sc_ntxchains == 3)
|
||||
pwr -= AR_PWR_DECREASE_FOR_3_CHAIN;
|
||||
if (pwr < 0)
|
||||
pwr = 0;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
/* Get CCK target powers. */
|
||||
ar5008_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck,
|
||||
AR5416_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
|
||||
|
||||
/* Get OFDM target powers. */
|
||||
ar5008_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G,
|
||||
AR5416_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
|
||||
|
||||
#ifndef IEEE80211_NO_HT
|
||||
/* Get HT-20 target powers. */
|
||||
ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT20,
|
||||
eep->calTargetPower2GHT20, AR5416_NUM_2G_20_TARGET_POWERS,
|
||||
tpow_ht20);
|
||||
|
||||
if (extc != NULL) {
|
||||
/* Get HT-40 target powers. */
|
||||
ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT40,
|
||||
eep->calTargetPower2GHT40,
|
||||
AR5416_NUM_2G_40_TARGET_POWERS, tpow_ht40);
|
||||
|
||||
/* Get secondary channel CCK target powers. */
|
||||
ar5008_get_lg_tpow(sc, extc, AR_CTL_11B,
|
||||
eep->calTargetPowerCck,
|
||||
AR5416_NUM_2G_CCK_TARGET_POWERS, tpow_cck_ext);
|
||||
|
||||
/* Get secondary channel OFDM target powers. */
|
||||
ar5008_get_lg_tpow(sc, extc, AR_CTL_11G,
|
||||
eep->calTargetPower2G,
|
||||
AR5416_NUM_2G_20_TARGET_POWERS, tpow_ofdm_ext);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* Get OFDM target powers. */
|
||||
ar5008_get_lg_tpow(sc, c, AR_CTL_11A, eep->calTargetPower5G,
|
||||
AR5416_NUM_5G_20_TARGET_POWERS, tpow_ofdm);
|
||||
|
||||
#ifndef IEEE80211_NO_HT
|
||||
/* Get HT-20 target powers. */
|
||||
ar5008_get_ht_tpow(sc, c, AR_CTL_5GHT20,
|
||||
eep->calTargetPower5GHT20, AR5416_NUM_5G_20_TARGET_POWERS,
|
||||
tpow_ht20);
|
||||
|
||||
if (extc != NULL) {
|
||||
/* Get HT-40 target powers. */
|
||||
ar5008_get_ht_tpow(sc, c, AR_CTL_5GHT40,
|
||||
eep->calTargetPower5GHT40,
|
||||
AR5416_NUM_5G_40_TARGET_POWERS, tpow_ht40);
|
||||
|
||||
/* Get secondary channel OFDM target powers. */
|
||||
ar5008_get_lg_tpow(sc, extc, AR_CTL_11A,
|
||||
eep->calTargetPower5G,
|
||||
AR5416_NUM_5G_20_TARGET_POWERS, tpow_ofdm_ext);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Compute CCK/OFDM delta. */
|
||||
cckinc = (sc->sc_flags & ATHN_FLAG_OLPC) ? -2 : 0;
|
||||
|
||||
memset(power, 0, sizeof(power));
|
||||
/* Shuffle target powers accross transmit rates. */
|
||||
power[ATHN_POWER_OFDM6 ] =
|
||||
power[ATHN_POWER_OFDM9 ] =
|
||||
power[ATHN_POWER_OFDM12] =
|
||||
power[ATHN_POWER_OFDM18] =
|
||||
power[ATHN_POWER_OFDM24] = tpow_ofdm[0];
|
||||
power[ATHN_POWER_OFDM36] = tpow_ofdm[1];
|
||||
power[ATHN_POWER_OFDM48] = tpow_ofdm[2];
|
||||
power[ATHN_POWER_OFDM54] = tpow_ofdm[3];
|
||||
power[ATHN_POWER_XR ] = tpow_ofdm[0];
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
power[ATHN_POWER_CCK1_LP ] = tpow_cck[0] + cckinc;
|
||||
power[ATHN_POWER_CCK2_LP ] =
|
||||
power[ATHN_POWER_CCK2_SP ] = tpow_cck[1] + cckinc;
|
||||
power[ATHN_POWER_CCK55_LP] =
|
||||
power[ATHN_POWER_CCK55_SP] = tpow_cck[2] + cckinc;
|
||||
power[ATHN_POWER_CCK11_LP] =
|
||||
power[ATHN_POWER_CCK11_SP] = tpow_cck[3] + cckinc;
|
||||
}
|
||||
#ifndef IEEE80211_NO_HT
|
||||
for (i = 0; i < nitems(tpow_ht20); i++)
|
||||
power[ATHN_POWER_HT20(i)] = tpow_ht20[i];
|
||||
if (extc != NULL) {
|
||||
/* Correct PAR difference between HT40 and HT20/Legacy. */
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2)
|
||||
ht40inc = modal->ht40PowerIncForPdadc;
|
||||
else
|
||||
ht40inc = AR_HT40_POWER_INC_FOR_PDADC;
|
||||
for (i = 0; i < nitems(tpow_ht40); i++)
|
||||
power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc;
|
||||
power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0];
|
||||
power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0] + cckinc;
|
||||
power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0];
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
power[ATHN_POWER_CCK_EXT] = tpow_cck_ext[0] + cckinc;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(sc)) {
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_21)
|
||||
pwroff = eep->baseEepHeader.pwrTableOffset;
|
||||
else
|
||||
pwroff = AR_PWR_TABLE_OFFSET_DB;
|
||||
for (i = 0; i < ATHN_POWER_COUNT; i++)
|
||||
power[i] -= pwroff * 2; /* In half dB. */
|
||||
}
|
||||
for (i = 0; i < ATHN_POWER_COUNT; i++) {
|
||||
if (power[i] > AR_MAX_RATE_POWER)
|
||||
power[i] = AR_MAX_RATE_POWER;
|
||||
}
|
||||
|
||||
/* Write transmit power values to hardware. */
|
||||
ar5008_write_txpower(sc, power);
|
||||
|
||||
/*
|
||||
* Write transmit power substraction for dynamic chain changing
|
||||
* and per-packet transmit power.
|
||||
*/
|
||||
AR_WRITE(sc, AR_PHY_POWER_TX_SUB,
|
||||
(modal->pwrDecreaseFor3Chain & 0x3f) << 6 |
|
||||
(modal->pwrDecreaseFor2Chain & 0x3f));
|
||||
}
|
||||
|
||||
Static void
|
||||
ar5416_spur_mitigate(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
const struct ar_spur_chan *spurchans;
|
||||
int i, spur, bin, spur_delta_phase, spur_freq_sd;
|
||||
|
||||
spurchans = sc->sc_ops.get_spur_chans(sc, IEEE80211_IS_CHAN_2GHZ(c));
|
||||
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
|
||||
spur = spurchans[i].spurChan;
|
||||
if (spur == AR_NO_SPUR)
|
||||
return; /* XXX disable if it was enabled! */
|
||||
spur -= c->ic_freq * 10;
|
||||
/* Verify range +/-9.5MHz */
|
||||
if (abs(spur) < 95)
|
||||
break;
|
||||
}
|
||||
if (i == AR_EEPROM_MODAL_SPURS)
|
||||
return; /* XXX disable if it was enabled! */
|
||||
DPRINTFN(DBG_RF, sc, "enabling spur mitigation\n");
|
||||
|
||||
AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0,
|
||||
AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
|
||||
AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
|
||||
AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
|
||||
AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
|
||||
|
||||
AR_WRITE(sc, AR_PHY_SPUR_REG,
|
||||
AR_PHY_SPUR_REG_MASK_RATE_CNTL |
|
||||
AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
|
||||
AR_PHY_SPUR_REG_MASK_RATE_SELECT |
|
||||
AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
|
||||
SM(AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, AR_SPUR_RSSI_THRESH));
|
||||
|
||||
spur_delta_phase = (spur * 524288) / 100;
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
spur_freq_sd = (spur * 2048) / 440;
|
||||
else
|
||||
spur_freq_sd = (spur * 2048) / 400;
|
||||
|
||||
AR_WRITE(sc, AR_PHY_TIMING11,
|
||||
AR_PHY_TIMING11_USE_SPUR_IN_AGC |
|
||||
SM(AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd) |
|
||||
SM(AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase));
|
||||
|
||||
bin = spur * 32;
|
||||
ar5008_set_viterbi_mask(sc, bin);
|
||||
}
|
||||
|
||||
Static uint8_t
|
||||
ar5416_reverse_bits(uint8_t v, int nbits)
|
||||
{
|
||||
KASSERT(nbits <= 8);
|
||||
v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
|
||||
v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
|
||||
v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
|
||||
return v >> (8 - nbits);
|
||||
}
|
||||
|
||||
PUBLIC uint8_t
|
||||
ar5416_get_rf_rev(struct athn_softc *sc)
|
||||
{
|
||||
uint8_t rev, reg;
|
||||
int i;
|
||||
|
||||
/* Allow access to analog chips. */
|
||||
AR_WRITE(sc, AR_PHY(0), 0x00000007);
|
||||
|
||||
AR_WRITE(sc, AR_PHY(0x36), 0x00007058);
|
||||
for (i = 0; i < 8; i++)
|
||||
AR_WRITE(sc, AR_PHY(0x20), 0x00010000);
|
||||
reg = (AR_READ(sc, AR_PHY(256)) >> 24) & 0xff;
|
||||
reg = (reg & 0xf0) >> 4 | (reg & 0x0f) << 4;
|
||||
|
||||
rev = ar5416_reverse_bits(reg, 8);
|
||||
if ((rev & AR_RADIO_SREV_MAJOR) == 0)
|
||||
rev = AR_RAD5133_SREV_MAJOR;
|
||||
return rev;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace bits "off" to "off+nbits-1" in column "col" with the specified
|
||||
* value.
|
||||
*/
|
||||
Static void
|
||||
ar5416_rw_rfbits(uint32_t *buf, int col, int off, uint32_t val, int nbits)
|
||||
{
|
||||
int idx, bit;
|
||||
|
||||
KASSERT(off >= 1 && col < 4 && nbits <= 32);
|
||||
|
||||
off--; /* Starts at 1. */
|
||||
while (nbits-- > 0) {
|
||||
idx = off / 8;
|
||||
bit = off % 8;
|
||||
buf[idx] &= ~(1 << (bit + col * 8));
|
||||
buf[idx] |= ((val >> nbits) & 1) << (bit + col * 8);
|
||||
off++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Overwrite db and ob based on ROM settings.
|
||||
*/
|
||||
Static void
|
||||
ar5416_rw_bank6tpc(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
uint32_t *rwbank6tpc)
|
||||
{
|
||||
const struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
const struct ar5416_modal_eep_header *modal;
|
||||
|
||||
if (IEEE80211_IS_CHAN_5GHZ(c)) {
|
||||
modal = &eep->modalHeader[0];
|
||||
/* 5GHz db in column 0, bits [200-202]. */
|
||||
ar5416_rw_rfbits(rwbank6tpc, 0, 200, modal->db, 3);
|
||||
/* 5GHz ob in column 0, bits [203-205]. */
|
||||
ar5416_rw_rfbits(rwbank6tpc, 0, 203, modal->ob, 3);
|
||||
}
|
||||
else {
|
||||
modal = &eep->modalHeader[1];
|
||||
/* 2GHz db in column 0, bits [194-196]. */
|
||||
ar5416_rw_rfbits(rwbank6tpc, 0, 194, modal->db, 3);
|
||||
/* 2GHz ob in column 0, bits [197-199]. */
|
||||
ar5416_rw_rfbits(rwbank6tpc, 0, 197, modal->ob, 3);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Program analog RF.
|
||||
*/
|
||||
PUBLIC void
|
||||
ar5416_rf_reset(struct athn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
const uint32_t *bank6tpc;
|
||||
int i;
|
||||
|
||||
/* Bank 0. */
|
||||
AR_WRITE(sc, 0x98b0, 0x1e5795e5);
|
||||
AR_WRITE(sc, 0x98e0, 0x02008020);
|
||||
|
||||
/* Bank 1. */
|
||||
AR_WRITE(sc, 0x98b0, 0x02108421);
|
||||
AR_WRITE(sc, 0x98ec, 0x00000008);
|
||||
|
||||
/* Bank 2. */
|
||||
AR_WRITE(sc, 0x98b0, 0x0e73ff17);
|
||||
AR_WRITE(sc, 0x98e0, 0x00000420);
|
||||
|
||||
/* Bank 3. */
|
||||
if (IEEE80211_IS_CHAN_5GHZ(c))
|
||||
AR_WRITE(sc, 0x98f0, 0x01400018);
|
||||
else
|
||||
AR_WRITE(sc, 0x98f0, 0x01c00018);
|
||||
|
||||
/* Select the Bank 6 TPC values to use. */
|
||||
if (AR_SREV_9160_10_OR_LATER(sc))
|
||||
bank6tpc = ar9160_bank6tpc_vals;
|
||||
else
|
||||
bank6tpc = ar5416_bank6tpc_vals;
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2) {
|
||||
uint32_t *rwbank6tpc = sc->sc_rwbuf;
|
||||
|
||||
/* Copy values from .rodata to writable buffer. */
|
||||
memcpy(rwbank6tpc, bank6tpc, 32 * sizeof(uint32_t));
|
||||
ar5416_rw_bank6tpc(sc, c, rwbank6tpc);
|
||||
bank6tpc = rwbank6tpc;
|
||||
}
|
||||
/* Bank 6 TPC. */
|
||||
for (i = 0; i < 32; i++)
|
||||
AR_WRITE(sc, 0x989c, bank6tpc[i]);
|
||||
if (IEEE80211_IS_CHAN_5GHZ(c))
|
||||
AR_WRITE(sc, 0x98d0, 0x0000000f);
|
||||
else
|
||||
AR_WRITE(sc, 0x98d0, 0x0010000f);
|
||||
|
||||
/* Bank 7. */
|
||||
AR_WRITE(sc, 0x989c, 0x00000500);
|
||||
AR_WRITE(sc, 0x989c, 0x00000800);
|
||||
AR_WRITE(sc, 0x98cc, 0x0000000e);
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar5416_reset_bb_gain(struct athn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
const uint32_t *pvals;
|
||||
int i;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
pvals = ar5416_bb_rfgain_vals_2g;
|
||||
else
|
||||
pvals = ar5416_bb_rfgain_vals_5g;
|
||||
for (i = 0; i < 64; i++)
|
||||
AR_WRITE(sc, AR_PHY_BB_RFGAIN(i), pvals[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix orientation sensitivity issue on AR5416/2GHz by increasing
|
||||
* rf_pwd_icsyndiv.
|
||||
*/
|
||||
Static void
|
||||
ar5416_force_bias(struct athn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
uint32_t *rwbank6 = sc->sc_rwbuf;
|
||||
uint8_t bias;
|
||||
int i;
|
||||
|
||||
KASSERT(IEEE80211_IS_CHAN_2GHZ(c));
|
||||
|
||||
/* Copy values from .rodata to writable buffer. */
|
||||
memcpy(rwbank6, ar5416_bank6_vals, sizeof(ar5416_bank6_vals));
|
||||
|
||||
if (c->ic_freq < 2412)
|
||||
bias = 0;
|
||||
else if (c->ic_freq < 2422)
|
||||
bias = 1;
|
||||
else
|
||||
bias = 2;
|
||||
ar5416_reverse_bits(bias, 3);
|
||||
|
||||
/* Overwrite "rf_pwd_icsyndiv" (column 3, bits [181-183].) */
|
||||
ar5416_rw_rfbits(rwbank6, 3, 181, bias, 3);
|
||||
|
||||
/* Write Bank 6. */
|
||||
for (i = 0; i < 32; i++)
|
||||
AR_WRITE(sc, 0x989c, rwbank6[i]);
|
||||
AR_WRITE(sc, 0x98d0, 0x0010000f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Overwrite XPA bias level based on ROM setting.
|
||||
*/
|
||||
Static void
|
||||
ar9160_rw_addac(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
uint32_t *addac)
|
||||
{
|
||||
struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
struct ar5416_modal_eep_header *modal;
|
||||
uint8_t fbin, bias;
|
||||
int i;
|
||||
|
||||
/* XXX xpaBiasLvlFreq values have not been endian-swapped? */
|
||||
|
||||
/* Get the XPA bias level to use for the specified channel. */
|
||||
modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
|
||||
if (modal->xpaBiasLvl == 0xff) {
|
||||
bias = modal->xpaBiasLvlFreq[0] >> 14;
|
||||
fbin = athn_chan2fbin(c);
|
||||
for (i = 1; i < 3; i++) {
|
||||
if (modal->xpaBiasLvlFreq[i] == 0)
|
||||
break;
|
||||
if ((modal->xpaBiasLvlFreq[i] & 0xff) < fbin)
|
||||
break;
|
||||
bias = modal->xpaBiasLvlFreq[i] >> 14;
|
||||
}
|
||||
}
|
||||
else
|
||||
bias = modal->xpaBiasLvl & 0x3;
|
||||
|
||||
bias = ar5416_reverse_bits(bias, 2); /* Put in host bit-order. */
|
||||
DPRINTFN(DBG_RF, sc, "bias level=%d\n", bias);
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
ar5416_rw_rfbits(addac, 0, 60, bias, 2);
|
||||
else
|
||||
ar5416_rw_rfbits(addac, 0, 55, bias, 2);
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar5416_reset_addac(struct athn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
const struct athn_addac *addac = sc->sc_addac;
|
||||
const uint32_t *pvals;
|
||||
int i;
|
||||
|
||||
if (AR_SREV_9160(sc) && sc->sc_eep_rev >= AR_EEP_MINOR_VER_7) {
|
||||
uint32_t *rwaddac = sc->sc_rwbuf;
|
||||
|
||||
/* Copy values from .rodata to writable buffer. */
|
||||
memcpy(rwaddac, addac->vals, addac->nvals * sizeof(uint32_t));
|
||||
ar9160_rw_addac(sc, c, rwaddac);
|
||||
pvals = rwaddac;
|
||||
}
|
||||
else
|
||||
pvals = addac->vals;
|
||||
for (i = 0; i < addac->nvals; i++)
|
||||
AR_WRITE(sc, 0x989c, pvals[i]);
|
||||
AR_WRITE(sc, 0x98cc, 0); /* Finalize. */
|
||||
}
|
44
sys/dev/ic/arn5416.h
Normal file
44
sys/dev/ic/arn5416.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* $NetBSD: arn5416.h,v 1.1 2013/03/30 02:53:01 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _IF_ARN5416_H_
|
||||
#define _IF_ARN5416_H_
|
||||
|
||||
int ar5416_attach(struct athn_softc *);
|
||||
int ar5416_init_calib(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
uint8_t ar5416_get_rf_rev(struct athn_softc *);
|
||||
void ar5416_reset_addac(struct athn_softc *, struct ieee80211_channel *);
|
||||
void ar5416_rf_reset(struct athn_softc *, struct ieee80211_channel *);
|
||||
void ar5416_reset_bb_gain(struct athn_softc *, struct ieee80211_channel *);
|
||||
void ar5416_swap_rom(struct athn_softc *);
|
||||
void ar5416_set_txpower(struct athn_softc *, struct ieee80211_channel *,
|
||||
struct ieee80211_channel *);
|
||||
const struct ar_spur_chan *
|
||||
ar5416_get_spur_chans(struct athn_softc *, int);
|
||||
|
||||
#endif /* _IF_ARN5416_H_ */
|
852
sys/dev/ic/arn5416reg.h
Normal file
852
sys/dev/ic/arn5416reg.h
Normal file
@ -0,0 +1,852 @@
|
||||
/* $NetBSD: arn5416reg.h,v 1.1 2013/03/30 02:53:01 christos Exp $ */
|
||||
/* $OpenBSD: ar5416reg.h,v 1.5 2012/10/20 09:54:20 stsp Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _ARN5416REG_H_
|
||||
#define _ARN5416REG_H_
|
||||
|
||||
#define AR5416_MAX_CHAINS 3
|
||||
|
||||
#define AR5416_PHY_CCA_MAX_GOOD_VALUE ( -85)
|
||||
|
||||
/*
|
||||
* ROM layout used by AR5416, AR9160 and AR9280.
|
||||
*/
|
||||
#define AR5416_EEP_START_LOC 256
|
||||
#define AR5416_NUM_5G_CAL_PIERS 8
|
||||
#define AR5416_NUM_2G_CAL_PIERS 4
|
||||
#define AR5416_NUM_5G_20_TARGET_POWERS 8
|
||||
#define AR5416_NUM_5G_40_TARGET_POWERS 8
|
||||
#define AR5416_NUM_2G_CCK_TARGET_POWERS 3
|
||||
#define AR5416_NUM_2G_20_TARGET_POWERS 4
|
||||
#define AR5416_NUM_2G_40_TARGET_POWERS 4
|
||||
#define AR5416_NUM_CTLS 24
|
||||
#define AR5416_NUM_BAND_EDGES 8
|
||||
#define AR5416_NUM_PD_GAINS 4
|
||||
#define AR5416_PD_GAINS_IN_MASK 4
|
||||
#define AR5416_PD_GAIN_ICEPTS 5
|
||||
|
||||
struct ar5416_base_eep_header {
|
||||
uint16_t length;
|
||||
uint16_t checksum;
|
||||
uint16_t version;
|
||||
uint8_t opCapFlags;
|
||||
uint8_t eepMisc;
|
||||
uint16_t regDmn[2];
|
||||
uint8_t macAddr[6];
|
||||
uint8_t rxMask;
|
||||
uint8_t txMask;
|
||||
uint16_t rfSilent;
|
||||
uint16_t blueToothOptions;
|
||||
uint16_t deviceCap;
|
||||
uint32_t binBuildNumber;
|
||||
uint8_t deviceType;
|
||||
/* End of common header. */
|
||||
uint8_t pwdclkind;
|
||||
uint8_t fastClk5g;
|
||||
uint8_t divChain;
|
||||
uint8_t rxGainType;
|
||||
#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0
|
||||
#define AR5416_EEP_RXGAIN_13DB_BACKOFF 1
|
||||
#define AR5416_EEP_RXGAIN_ORIG 2
|
||||
|
||||
uint8_t dacHiPwrMode_5G;
|
||||
uint8_t openLoopPwrCntl;
|
||||
uint8_t dacLpMode;
|
||||
uint8_t txGainType;
|
||||
uint8_t rcChainMask;
|
||||
uint8_t desiredScaleCCK;
|
||||
uint8_t pwrTableOffset;
|
||||
uint8_t frac_n_5g;
|
||||
uint8_t futureBase[21];
|
||||
} __packed;
|
||||
|
||||
struct ar5416_modal_eep_header {
|
||||
uint32_t antCtrlChain[AR5416_MAX_CHAINS];
|
||||
uint32_t antCtrlCommon;
|
||||
uint8_t antennaGainCh[AR5416_MAX_CHAINS];
|
||||
uint8_t switchSettling;
|
||||
uint8_t txRxAttenCh[AR5416_MAX_CHAINS];
|
||||
uint8_t rxTxMarginCh[AR5416_MAX_CHAINS];
|
||||
uint8_t adcDesiredSize;
|
||||
uint8_t pgaDesiredSize;
|
||||
uint8_t xlnaGainCh[AR5416_MAX_CHAINS];
|
||||
uint8_t txEndToXpaOff;
|
||||
uint8_t txEndToRxOn;
|
||||
uint8_t txFrameToXpaOn;
|
||||
uint8_t thresh62;
|
||||
uint8_t noiseFloorThreshCh[AR5416_MAX_CHAINS];
|
||||
uint8_t xpdGain;
|
||||
uint8_t xpd;
|
||||
uint8_t iqCalICh[AR5416_MAX_CHAINS];
|
||||
uint8_t iqCalQCh[AR5416_MAX_CHAINS];
|
||||
uint8_t pdGainOverlap;
|
||||
uint8_t ob;
|
||||
uint8_t db;
|
||||
uint8_t xpaBiasLvl;
|
||||
uint8_t pwrDecreaseFor2Chain;
|
||||
uint8_t pwrDecreaseFor3Chain;
|
||||
uint8_t txFrameToDataStart;
|
||||
uint8_t txFrameToPaOn;
|
||||
uint8_t ht40PowerIncForPdadc;
|
||||
uint8_t bswAtten[AR5416_MAX_CHAINS];
|
||||
uint8_t bswMargin[AR5416_MAX_CHAINS];
|
||||
uint8_t swSettleHt40;
|
||||
uint8_t xatten2Db[AR5416_MAX_CHAINS];
|
||||
uint8_t xatten2Margin[AR5416_MAX_CHAINS];
|
||||
uint8_t ob_ch1;
|
||||
uint8_t db_ch1;
|
||||
uint8_t flagBits;
|
||||
#define AR5416_EEP_FLAG_USEANT1 0x01
|
||||
#define AR5416_EEP_FLAG_FORCEXPAON 0x02
|
||||
#define AR5416_EEP_FLAG_LOCALBIAS 0x04
|
||||
#define AR5416_EEP_FLAG_FEMBANDSELECT 0x08
|
||||
#define AR5416_EEP_FLAG_XLNABUFIN 0x10
|
||||
#define AR5416_EEP_FLAG_XLNAISEL_M 0x60
|
||||
#define AR5416_EEP_FLAG_XLNAISEL_S 5
|
||||
#define AR5416_EEP_FLAG_XLNABUFMODE 0x80
|
||||
|
||||
uint8_t miscBits;
|
||||
#define AR5416_EEP_MISC_TX_DAC_SCALE_CCK_M 0x03
|
||||
#define AR5416_EEP_MISC_TX_DAC_SCALE_CCK_S 0
|
||||
#define AR5416_EEP_MISC_TX_CLIP_M 0xfc
|
||||
#define AR5416_EEP_MISC_TX_CLIP_S 2
|
||||
|
||||
uint16_t xpaBiasLvlFreq[3];
|
||||
uint8_t futureModal[6];
|
||||
struct ar_spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
|
||||
} __packed;
|
||||
|
||||
struct ar5416_cal_data_per_freq {
|
||||
uint8_t pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
|
||||
uint8_t vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
|
||||
} __packed;
|
||||
|
||||
struct ar5416_cal_ctl_data {
|
||||
struct ar_cal_ctl_edges
|
||||
ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
|
||||
} __packed;
|
||||
|
||||
struct ar5416_eeprom {
|
||||
struct ar5416_base_eep_header baseEepHeader;
|
||||
uint8_t custData[64];
|
||||
struct ar5416_modal_eep_header modalHeader[2];
|
||||
uint8_t calFreqPier5G[AR5416_NUM_5G_CAL_PIERS];
|
||||
uint8_t calFreqPier2G[AR5416_NUM_2G_CAL_PIERS];
|
||||
struct ar5416_cal_data_per_freq
|
||||
calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS];
|
||||
struct ar5416_cal_data_per_freq
|
||||
calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
|
||||
struct ar_cal_target_power_leg
|
||||
calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS];
|
||||
struct ar_cal_target_power_ht
|
||||
calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS];
|
||||
struct ar_cal_target_power_ht
|
||||
calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS];
|
||||
struct ar_cal_target_power_leg
|
||||
calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS];
|
||||
struct ar_cal_target_power_leg
|
||||
calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS];
|
||||
struct ar_cal_target_power_ht
|
||||
calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS];
|
||||
struct ar_cal_target_power_ht
|
||||
calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS];
|
||||
uint8_t ctlIndex[AR5416_NUM_CTLS];
|
||||
struct ar5416_cal_ctl_data ctlData[AR5416_NUM_CTLS];
|
||||
uint8_t padding;
|
||||
} __packed;
|
||||
|
||||
/* Macro to "pack" registers to 16-bit to save some .rodata space. */
|
||||
#define P(x) (x)
|
||||
|
||||
/*
|
||||
* AR5416 initialization values.
|
||||
*/
|
||||
static const uint16_t ar5416_regs[] = {
|
||||
P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
|
||||
P(0x0801c), P(0x08120), P(0x081d0), P(0x09804), P(0x09820),
|
||||
P(0x09824), P(0x09828), P(0x09834), P(0x09838), P(0x09844),
|
||||
P(0x09848), P(0x0a848), P(0x0b848), P(0x09850), P(0x09858),
|
||||
P(0x0985c), P(0x09860), P(0x09864), P(0x09868), P(0x0986c),
|
||||
P(0x09914), P(0x09918), P(0x09924), P(0x09944), P(0x09960),
|
||||
P(0x0a960), P(0x0b960), P(0x09964), P(0x099bc), P(0x099c0),
|
||||
P(0x099c4), P(0x099c8), P(0x099cc), P(0x099d0), P(0x099d4),
|
||||
P(0x099d8), P(0x0a204), P(0x0a208), P(0x0a20c), P(0x0b20c),
|
||||
P(0x0c20c), P(0x0a21c), P(0x0a230), P(0x0a274), P(0x0a300),
|
||||
P(0x0a304), P(0x0a308), P(0x0a30c), P(0x0a310), P(0x0a314),
|
||||
P(0x0a318), P(0x0a31c), P(0x0a320), P(0x0a324), P(0x0a328),
|
||||
P(0x0a32c), P(0x0a330), P(0x0a334)
|
||||
};
|
||||
|
||||
static const uint32_t ar5416_vals_5g20[] = {
|
||||
0x00000230, 0x00000168, 0x00000e60, 0x0000a000, 0x03e803e8,
|
||||
0x128d93a7, 0x08f04800, 0x00003210, 0x00000300, 0x02020200,
|
||||
0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x1372161e,
|
||||
0x001a6a65, 0x001a6a65, 0x001a6a65, 0x6c48b4e0, 0x7ec82d2e,
|
||||
0x31395d5e, 0x00049d18, 0x0001ce00, 0x409a4190, 0x050cb081,
|
||||
0x000007d0, 0x000001b8, 0xd0058a0b, 0xffb81020, 0x00000900,
|
||||
0x00000900, 0x00000900, 0x00000000, 0x001a0a00, 0x038919be,
|
||||
0x06336f77, 0x6af6532c, 0x08f186c8, 0x00046384, 0x00000000,
|
||||
0x00000000, 0x00000880, 0xd6be4788, 0x002ec1e0, 0x002ec1e0,
|
||||
0x002ec1e0, 0x1883800a, 0x00000000, 0x0a1a9caa, 0x18010000,
|
||||
0x30032602, 0x48073e06, 0x560b4c0a, 0x641a600f, 0x7a4f6e1b,
|
||||
0x8c5b7e5a, 0x9d0f96cf, 0xb51fa69f, 0xcb3fbd07, 0x0000d7bf,
|
||||
0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
#ifndef IEEE80211_NO_HT
|
||||
static const uint32_t ar5416_vals_5g40[] = {
|
||||
0x00000460, 0x000002d0, 0x00001cc0, 0x00014000, 0x07d007d0,
|
||||
0x128d93cf, 0x08f04800, 0x00003210, 0x000003c4, 0x02020200,
|
||||
0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x1372161e,
|
||||
0x001a6a65, 0x001a6a65, 0x001a6a65, 0x6d48b4e0, 0x7ec82d2e,
|
||||
0x3139605e, 0x00049d18, 0x0001ce00, 0x409a4190, 0x050cb081,
|
||||
0x00000fa0, 0x00000370, 0xd0058a0b, 0xffb81020, 0x00000900,
|
||||
0x00000900, 0x00000900, 0x00000000, 0x001a0a00, 0x038919be,
|
||||
0x06336f77, 0x6af6532c, 0x08f186c8, 0x00046384, 0x00000000,
|
||||
0x00000000, 0x00000880, 0xd6be4788, 0x002ec1e0, 0x002ec1e0,
|
||||
0x002ec1e0, 0x1883800a, 0x00000000, 0x0a1a9caa, 0x18010000,
|
||||
0x30032602, 0x48073e06, 0x560b4c0a, 0x641a600f, 0x7a4f6e1b,
|
||||
0x8c5b7e5a, 0x9d0f96cf, 0xb51fa69f, 0xcb3fbcbf, 0x0000d7bf,
|
||||
0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t ar5416_vals_2g40[] = {
|
||||
0x000002c0, 0x00000318, 0x00007c70, 0x00016000, 0x10801600,
|
||||
0x12e013d7, 0x08f04810, 0x0000320a, 0x000003c4, 0x02020200,
|
||||
0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x137216a0,
|
||||
0x00197a68, 0x00197a68, 0x00197a68, 0x6d48b0de, 0x7ec82d2e,
|
||||
0x3139605e, 0x00049d18, 0x0001ce00, 0x409a4190, 0x050cb081,
|
||||
0x00001130, 0x00000268, 0xd0058a0b, 0xffb81020, 0x00012d80,
|
||||
0x00012d80, 0x00012d80, 0x00001120, 0x001a0a00, 0x038919be,
|
||||
0x06336f77, 0x6af6532c, 0x08f186c8, 0x00046384, 0x00000000,
|
||||
0x00000000, 0x00000880, 0xd03e4788, 0x002ac120, 0x002ac120,
|
||||
0x002ac120, 0x1883800a, 0x00000210, 0x0a1a7caa, 0x18010000,
|
||||
0x2e032402, 0x4a0a3c06, 0x621a540b, 0x764f6c1b, 0x845b7a5a,
|
||||
0x950f8ccf, 0xa5cf9b4f, 0xbddfaf1f, 0xd1ffc93f, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
#endif
|
||||
|
||||
static const uint32_t ar5416_vals_2g20[] = {
|
||||
0x00000160, 0x0000018c, 0x00003e38, 0x0000b000, 0x08400b00,
|
||||
0x12e013ab, 0x08f04810, 0x0000320a, 0x00000300, 0x02020200,
|
||||
0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x137216a0,
|
||||
0x00197a68, 0x00197a68, 0x00197a68, 0x6c48b0de, 0x7ec82d2e,
|
||||
0x31395d5e, 0x00049d18, 0x0001ce00, 0x409a4190, 0x050cb081,
|
||||
0x00000898, 0x00000134, 0xd0058a0b, 0xffb81020, 0x00012d80,
|
||||
0x00012d80, 0x00012d80, 0x00001120, 0x001a0a00, 0x038919be,
|
||||
0x06336f77, 0x6af6532c, 0x08f186c8, 0x00046384, 0x00000000,
|
||||
0x00000000, 0x00000880, 0xd03e4788, 0x002ac120, 0x002ac120,
|
||||
0x002ac120, 0x1883800a, 0x00000108, 0x0a1a7caa, 0x18010000,
|
||||
0x2e032402, 0x4a0a3c06, 0x621a540b, 0x764f6c1b, 0x845b7a5a,
|
||||
0x950f8ccf, 0xa5cf9b4f, 0xbddfaf1f, 0xd1ffc93f, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
static const uint16_t ar5416_cm_regs[] = {
|
||||
P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
|
||||
P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
|
||||
P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
|
||||
P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
|
||||
P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
|
||||
P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
|
||||
P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
|
||||
P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
|
||||
P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
|
||||
P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
|
||||
P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
|
||||
P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
|
||||
P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
|
||||
P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
|
||||
P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
|
||||
P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
|
||||
P(0x0147c), P(0x04030), P(0x0403c), P(0x07010), P(0x07038),
|
||||
P(0x08004), P(0x08008), P(0x0800c), P(0x08018), P(0x08020),
|
||||
P(0x08038), P(0x0803c), P(0x08048), P(0x08054), P(0x08058),
|
||||
P(0x0805c), P(0x08060), P(0x08064), P(0x080c0), P(0x080c4),
|
||||
P(0x080c8), P(0x080cc), P(0x080d0), P(0x080d4), P(0x080d8),
|
||||
P(0x080e0), P(0x080e4), P(0x080e8), P(0x080ec), P(0x080f0),
|
||||
P(0x080f4), P(0x080f8), P(0x080fc), P(0x08100), P(0x08104),
|
||||
P(0x08108), P(0x0810c), P(0x08110), P(0x08118), P(0x0811c),
|
||||
P(0x08124), P(0x08128), P(0x0812c), P(0x08130), P(0x08134),
|
||||
P(0x08138), P(0x0813c), P(0x08144), P(0x08168), P(0x0816c),
|
||||
P(0x08170), P(0x08174), P(0x08178), P(0x0817c), P(0x081c4),
|
||||
P(0x081ec), P(0x081f0), P(0x081f4), P(0x081f8), P(0x081fc),
|
||||
P(0x08200), P(0x08204), P(0x08208), P(0x0820c), P(0x08210),
|
||||
P(0x08214), P(0x08218), P(0x0821c), P(0x08220), P(0x08224),
|
||||
P(0x08228), P(0x0822c), P(0x08230), P(0x08234), P(0x08238),
|
||||
P(0x0823c), P(0x08240), P(0x08244), P(0x08248), P(0x0824c),
|
||||
P(0x08250), P(0x08254), P(0x08258), P(0x0825c), P(0x08260),
|
||||
P(0x08264), P(0x08270), P(0x08274), P(0x08278), P(0x0827c),
|
||||
P(0x08284), P(0x08288), P(0x0828c), P(0x08294), P(0x08298),
|
||||
P(0x08300), P(0x08304), P(0x08308), P(0x0830c), P(0x08310),
|
||||
P(0x08314), P(0x08318), P(0x08328), P(0x0832c), P(0x08330),
|
||||
P(0x08334), P(0x08338), P(0x0833c), P(0x08340), P(0x09808),
|
||||
P(0x0980c), P(0x09810), P(0x09814), P(0x0981c), P(0x0982c),
|
||||
P(0x09830), P(0x0983c), P(0x09840), P(0x0984c), P(0x09854),
|
||||
P(0x09900), P(0x09904), P(0x09908), P(0x0990c), P(0x0991c),
|
||||
P(0x09920), P(0x0a920), P(0x0b920), P(0x09928), P(0x0992c),
|
||||
P(0x09934), P(0x09938), P(0x0993c), P(0x09948), P(0x0994c),
|
||||
P(0x09954), P(0x09958), P(0x0c95c), P(0x0c968), P(0x09970),
|
||||
P(0x09974), P(0x09978), P(0x0997c), P(0x09980), P(0x09984),
|
||||
P(0x09988), P(0x0998c), P(0x09990), P(0x09994), P(0x09998),
|
||||
P(0x0999c), P(0x099a0), P(0x099a4), P(0x099a8), P(0x099ac),
|
||||
P(0x099b0), P(0x099dc), P(0x099e0), P(0x099e4), P(0x099e8),
|
||||
P(0x099ec), P(0x099fc), P(0x09b00), P(0x09b04), P(0x09b08),
|
||||
P(0x09b0c), P(0x09b10), P(0x09b14), P(0x09b18), P(0x09b1c),
|
||||
P(0x09b20), P(0x09b24), P(0x09b28), P(0x09b2c), P(0x09b30),
|
||||
P(0x09b34), P(0x09b38), P(0x09b3c), P(0x09b40), P(0x09b44),
|
||||
P(0x09b48), P(0x09b4c), P(0x09b50), P(0x09b54), P(0x09b58),
|
||||
P(0x09b5c), P(0x09b60), P(0x09b64), P(0x09b68), P(0x09b6c),
|
||||
P(0x09b70), P(0x09b74), P(0x09b78), P(0x09b7c), P(0x09b80),
|
||||
P(0x09b84), P(0x09b88), P(0x09b8c), P(0x09b90), P(0x09b94),
|
||||
P(0x09b98), P(0x09b9c), P(0x09ba0), P(0x09ba4), P(0x09ba8),
|
||||
P(0x09bac), P(0x09bb0), P(0x09bb4), P(0x09bb8), P(0x09bbc),
|
||||
P(0x09bc0), P(0x09bc4), P(0x09bc8), P(0x09bcc), P(0x09bd0),
|
||||
P(0x09bd4), P(0x09bd8), P(0x09bdc), P(0x09be0), P(0x09be4),
|
||||
P(0x09be8), P(0x09bec), P(0x09bf0), P(0x09bf4), P(0x09bf8),
|
||||
P(0x09bfc), P(0x0a210), P(0x0a214), P(0x0a218), P(0x0a220),
|
||||
P(0x0a224), P(0x0a228), P(0x0a22c), P(0x0a234), P(0x0a238),
|
||||
P(0x0a23c), P(0x0a240), P(0x0a244), P(0x0a248), P(0x0a24c),
|
||||
P(0x0a250), P(0x0a254), P(0x0a258), P(0x0a25c), P(0x0a260),
|
||||
P(0x0a268), P(0x0a26c), P(0x0b26c), P(0x0c26c), P(0x0d270),
|
||||
P(0x0a278), P(0x0a27c), P(0x0a338), P(0x0a33c), P(0x0a340),
|
||||
P(0x0a344), P(0x0a348), P(0x0a34c), P(0x0a350), P(0x0a354),
|
||||
P(0x0a358), P(0x0d35c), P(0x0d360), P(0x0d364), P(0x0d368),
|
||||
P(0x0d36c), P(0x0d370), P(0x0d374), P(0x0d378), P(0x0d37c),
|
||||
P(0x0d380), P(0x0d384), P(0x0a388), P(0x0a38c), P(0x0a390),
|
||||
P(0x0a394), P(0x0a398), P(0x0a39c), P(0x0a3a0), P(0x0a3a4),
|
||||
P(0x0a3a8), P(0x0a3ac), P(0x0a3b0), P(0x0a3b4), P(0x0a3b8),
|
||||
P(0x0a3bc), P(0x0a3c0), P(0x0a3c4), P(0x0a3c8), P(0x0a3cc),
|
||||
P(0x0a3d0), P(0x0a3d4), P(0x0a3dc), P(0x0a3e0)
|
||||
};
|
||||
|
||||
static const uint32_t ar5416_cm_vals[] = {
|
||||
0x00000000, 0x00020015, 0x00000005, 0x00000000, 0x00000008,
|
||||
0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
|
||||
0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
|
||||
0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x000004c2,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000700, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x40000000, 0x00000000, 0x00000000,
|
||||
0x000fc78f, 0x0000000f, 0x00000000, 0x2a82301a, 0x05dc01e0,
|
||||
0x1f402710, 0x01f40000, 0x00001e00, 0x00000000, 0x00400000,
|
||||
0xffffffff, 0x0000ffff, 0x003f3f3f, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00020000, 0x00020000, 0x00000001,
|
||||
0x00000052, 0x00000000, 0x00000168, 0x000100aa, 0x00003210,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000,
|
||||
0x32143320, 0xfaa4fa50, 0x00000100, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00100000, 0x0010f400, 0x00000100, 0x0001e800,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x400000ff, 0x00080922,
|
||||
0x88000010, 0x00000000, 0x40000000, 0x003e4180, 0x00000000,
|
||||
0x0000002c, 0x0000002c, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x00000302,
|
||||
0x00000e00, 0x00070000, 0x00000000, 0x000107ff, 0x00000000,
|
||||
0xad848e19, 0x7d14e000, 0x9c0a9f6b, 0x00000000, 0x0000a000,
|
||||
0x00000000, 0x00200400, 0x206a002e, 0x1284233c, 0x00000859,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10000fff,
|
||||
0x05100000, 0x05100000, 0x05100000, 0x00000001, 0x00000004,
|
||||
0x1e1f2022, 0x0a0b0c0d, 0x00000000, 0x9280b212, 0x00020028,
|
||||
0x5d50e188, 0x00081fff, 0x004b6a8e, 0x000003ce, 0x190fb515,
|
||||
0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000001, 0x001fff00, 0x00000000,
|
||||
0x03051000, 0x00000000, 0x00000200, 0xaaaaaaaa, 0x3c466478,
|
||||
0x000000aa, 0x00001042, 0x00000000, 0x00000001, 0x00000002,
|
||||
0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009,
|
||||
0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d, 0x00000010,
|
||||
0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015,
|
||||
0x00000018, 0x00000019, 0x0000001a, 0x0000001b, 0x0000001c,
|
||||
0x0000001d, 0x00000020, 0x00000021, 0x00000022, 0x00000023,
|
||||
0x00000024, 0x00000025, 0x00000028, 0x00000029, 0x0000002a,
|
||||
0x0000002b, 0x0000002c, 0x0000002d, 0x00000030, 0x00000031,
|
||||
0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000035,
|
||||
0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
|
||||
0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
|
||||
0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
|
||||
0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000010,
|
||||
0x0000001a, 0x40806333, 0x00106c10, 0x009c4060, 0x018830c6,
|
||||
0x00000400, 0x00000bb5, 0x00000011, 0x20202020, 0x20202020,
|
||||
0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc, 0x00000001,
|
||||
0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01, 0xdfa91f01,
|
||||
0x00000000, 0x0e79e5c6, 0x0e79e5c6, 0x0e79e5c6, 0x00820820,
|
||||
0x1ce739ce, 0x051701ce, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff,
|
||||
0x79a8aa1f, 0x07ffffef, 0x0fffffe7, 0x17ffffe5, 0x1fffffe4,
|
||||
0x37ffffe3, 0x3fffffe3, 0x57ffffe3, 0x5fffffe2, 0x7fffffe2,
|
||||
0x7f3c7bba, 0xf3307ff0, 0x08000000, 0x20202020, 0x20202020,
|
||||
0x1ce739ce, 0x000001ce, 0x00000001, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000246, 0x20202020,
|
||||
0x20202020, 0x20202020, 0x1ce739ce, 0x000001ce
|
||||
};
|
||||
|
||||
static const struct athn_ini ar5416_ini = {
|
||||
.nregs = __arraycount(ar5416_regs),
|
||||
.regs = ar5416_regs,
|
||||
.vals_5g20 = ar5416_vals_5g20,
|
||||
#ifndef IEEE80211_NO_HT
|
||||
.vals_5g40 = ar5416_vals_5g40,
|
||||
.vals_2g40 = ar5416_vals_2g40,
|
||||
#endif
|
||||
.vals_2g20 = ar5416_vals_2g20,
|
||||
.ncmregs = __arraycount(ar5416_cm_regs),
|
||||
.cmregs = ar5416_cm_regs,
|
||||
.cmvals = ar5416_cm_vals
|
||||
};
|
||||
|
||||
/*
|
||||
* AR9160 initialization values.
|
||||
*/
|
||||
static const uint16_t ar9160_regs[] = {
|
||||
P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
|
||||
P(0x0801c), P(0x08120), P(0x081d0), P(0x09804), P(0x09820),
|
||||
P(0x09824), P(0x09828), P(0x09834), P(0x09838), P(0x09844),
|
||||
P(0x09848), P(0x0a848), P(0x0b848), P(0x09850), P(0x09858),
|
||||
P(0x0985c), P(0x09860), P(0x09864), P(0x09868), P(0x0986c),
|
||||
P(0x09914), P(0x09918), P(0x09924), P(0x09944), P(0x09960),
|
||||
P(0x0a960), P(0x0b960), P(0x09964), P(0x0c968), P(0x099bc),
|
||||
P(0x099c0), P(0x099c4), P(0x099c8), P(0x099cc), P(0x099d0),
|
||||
P(0x099d4), P(0x099d8), P(0x0a204), P(0x0a208), P(0x0a20c),
|
||||
P(0x0b20c), P(0x0c20c), P(0x0a21c), P(0x0a230), P(0x0a274),
|
||||
P(0x0a300), P(0x0a304), P(0x0a308), P(0x0a30c), P(0x0a310),
|
||||
P(0x0a314), P(0x0a318), P(0x0a31c), P(0x0a320), P(0x0a324),
|
||||
P(0x0a328), P(0x0a32c), P(0x0a330), P(0x0a334)
|
||||
};
|
||||
|
||||
static const uint32_t ar9160_vals_5g20[] = {
|
||||
0x00000230, 0x00000168, 0x00000e60, 0x0000a000, 0x03e803e8,
|
||||
0x128d93a7, 0x08f04800, 0x00003210, 0x00000300, 0x02020200,
|
||||
0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x0372161e,
|
||||
0x001a6a65, 0x001a6a65, 0x001a6a65, 0x6c48b4e2, 0x7ec82d2e,
|
||||
0x31395d5e, 0x00048d18, 0x0001ce00, 0x409a40d0, 0x050cb081,
|
||||
0x000007d0, 0x0000000a, 0xd00a8a07, 0xffb81020, 0x00009b40,
|
||||
0x00009b40, 0x00009b40, 0x00001120, 0x000003b5, 0x001a0600,
|
||||
0x038919be, 0x06336f77, 0x6af65329, 0x08f186c8, 0x00046384,
|
||||
0x00000000, 0x00000000, 0x00000880, 0xd6be4788, 0x002fc160,
|
||||
0x002fc160, 0x002fc160, 0x1883800a, 0x00000000, 0x0a1a9caa,
|
||||
0x18010000, 0x30032602, 0x48073e06, 0x560b4c0a, 0x641a600f,
|
||||
0x7a4f6e1b, 0x8c5b7e5a, 0x9d0f96cf, 0xb51fa69f, 0xcb3fbd07,
|
||||
0x0000d7bf, 0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
#ifndef IEEE80211_NO_HT
|
||||
static const uint32_t ar9160_vals_5g40[] = {
|
||||
0x00000460, 0x000002d0, 0x00001cc0, 0x00014000, 0x07d007d0,
|
||||
0x128d93cf, 0x08f04800, 0x00003210, 0x000003c4, 0x02020200,
|
||||
0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x0372161e,
|
||||
0x001a6a65, 0x001a6a65, 0x001a6a65, 0x6d48b4e2, 0x7ec82d2e,
|
||||
0x3139605e, 0x00048d18, 0x0001ce00, 0x409a40d0, 0x050cb081,
|
||||
0x00000fa0, 0x00000014, 0xd00a8a07, 0xffb81020, 0x00009b40,
|
||||
0x00009b40, 0x00009b40, 0x00001120, 0x000003b5, 0x001a0600,
|
||||
0x038919be, 0x06336f77, 0x6af65329, 0x08f186c8, 0x00046384,
|
||||
0x00000000, 0x00000000, 0x00000880, 0xd6be4788, 0x002fc160,
|
||||
0x002fc160, 0x002fc160, 0x1883800a, 0x00000000, 0x0a1a9caa,
|
||||
0x18010000, 0x30032602, 0x48073e06, 0x560b4c0a, 0x641a600f,
|
||||
0x7a4f6e1b, 0x8c5b7e5a, 0x9d0f96cf, 0xb51fa69f, 0xcb3fbcbf,
|
||||
0x0000d7bf, 0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t ar9160_vals_2g40[] = {
|
||||
0x000002c0, 0x00000318, 0x00007c70, 0x00016000, 0x10801600,
|
||||
0x12e013d7, 0x08f04810, 0x0000320a, 0x000003c4, 0x02020200,
|
||||
0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x037216a0,
|
||||
0x00197a68, 0x00197a68, 0x00197a68, 0x6d48b0e2, 0x7ec82d2e,
|
||||
0x3139605e, 0x00048d20, 0x0001ce00, 0x409a40d0, 0x050cb081,
|
||||
0x00001130, 0x00000016, 0xd00a8a0d, 0xffb81020, 0x00009b40,
|
||||
0x00009b40, 0x00009b40, 0x00001120, 0x000003ce, 0x001a0c00,
|
||||
0x038919be, 0x06336f77, 0x6af65329, 0x08f186c8, 0x00046384,
|
||||
0x00000000, 0x00000000, 0x00000880, 0xd03e4788, 0x002ac120,
|
||||
0x002ac120, 0x002ac120, 0x1883800a, 0x00000210, 0x0a1a7caa,
|
||||
0x18010000, 0x2e032402, 0x4a0a3c06, 0x621a540b, 0x764f6c1b,
|
||||
0x845b7a5a, 0x950f8ccf, 0xa5cf9b4f, 0xbddfaf1f, 0xd1ffc93f,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
#endif
|
||||
|
||||
static const uint32_t ar9160_vals_2g20[] = {
|
||||
0x00000160, 0x0000018c, 0x00003e38, 0x0000b000, 0x08400b00,
|
||||
0x12e013ab, 0x08f04810, 0x0000320a, 0x00000300, 0x02020200,
|
||||
0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x037216a0,
|
||||
0x00197a68, 0x00197a68, 0x00197a68, 0x6c48b0e2, 0x7ec82d2e,
|
||||
0x31395d5e, 0x00048d20, 0x0001ce00, 0x409a40d0, 0x050cb081,
|
||||
0x00000898, 0x0000000b, 0xd00a8a0d, 0xffb81020, 0x00009b40,
|
||||
0x00009b40, 0x00009b40, 0x00001120, 0x000003ce, 0x001a0c00,
|
||||
0x038919be, 0x06336f77, 0x6af65329, 0x08f186c8, 0x00046384,
|
||||
0x00000000, 0x00000000, 0x00000880, 0xd03e4788, 0x002ac120,
|
||||
0x002ac120, 0x002ac120, 0x1883800a, 0x00000108, 0x0a1a7caa,
|
||||
0x18010000, 0x2e032402, 0x4a0a3c06, 0x621a540b, 0x764f6c1b,
|
||||
0x845b7a5a, 0x950f8ccf, 0xa5cf9b4f, 0xbddfaf1f, 0xd1ffc93f,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
static const uint16_t ar9160_cm_regs[] = {
|
||||
P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
|
||||
P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
|
||||
P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
|
||||
P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
|
||||
P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
|
||||
P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
|
||||
P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
|
||||
P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
|
||||
P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
|
||||
P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
|
||||
P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
|
||||
P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
|
||||
P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
|
||||
P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
|
||||
P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
|
||||
P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
|
||||
P(0x0147c), P(0x04030), P(0x0403c), P(0x07010), P(0x07038),
|
||||
P(0x08004), P(0x08008), P(0x0800c), P(0x08018), P(0x08020),
|
||||
P(0x08038), P(0x0803c), P(0x08048), P(0x08054), P(0x08058),
|
||||
P(0x0805c), P(0x08060), P(0x08064), P(0x080c0), P(0x080c4),
|
||||
P(0x080c8), P(0x080cc), P(0x080d0), P(0x080d4), P(0x080d8),
|
||||
P(0x080e0), P(0x080e4), P(0x080e8), P(0x080ec), P(0x080f0),
|
||||
P(0x080f4), P(0x080f8), P(0x080fc), P(0x08100), P(0x08104),
|
||||
P(0x08108), P(0x0810c), P(0x08110), P(0x08118), P(0x0811c),
|
||||
P(0x08124), P(0x08128), P(0x0812c), P(0x08130), P(0x08134),
|
||||
P(0x08138), P(0x0813c), P(0x08144), P(0x08168), P(0x0816c),
|
||||
P(0x08170), P(0x08174), P(0x08178), P(0x0817c), P(0x081c4),
|
||||
P(0x081ec), P(0x081f0), P(0x081f4), P(0x081f8), P(0x081fc),
|
||||
P(0x08200), P(0x08204), P(0x08208), P(0x0820c), P(0x08210),
|
||||
P(0x08214), P(0x08218), P(0x0821c), P(0x08220), P(0x08224),
|
||||
P(0x08228), P(0x0822c), P(0x08230), P(0x08234), P(0x08238),
|
||||
P(0x0823c), P(0x08240), P(0x08244), P(0x08248), P(0x0824c),
|
||||
P(0x08250), P(0x08254), P(0x08258), P(0x0825c), P(0x08260),
|
||||
P(0x08264), P(0x08270), P(0x08274), P(0x08278), P(0x0827c),
|
||||
P(0x08284), P(0x08288), P(0x0828c), P(0x08294), P(0x08298),
|
||||
P(0x08300), P(0x08304), P(0x08308), P(0x0830c), P(0x08310),
|
||||
P(0x08314), P(0x08318), P(0x08328), P(0x0832c), P(0x08330),
|
||||
P(0x08334), P(0x08338), P(0x0833c), P(0x08340), P(0x09808),
|
||||
P(0x0980c), P(0x09810), P(0x09814), P(0x0981c), P(0x0982c),
|
||||
P(0x09830), P(0x0983c), P(0x09840), P(0x0984c), P(0x09854),
|
||||
P(0x09900), P(0x09904), P(0x09908), P(0x0990c), P(0x0991c),
|
||||
P(0x09920), P(0x0a920), P(0x0b920), P(0x09928), P(0x0992c),
|
||||
P(0x09934), P(0x09938), P(0x0993c), P(0x09948), P(0x0994c),
|
||||
P(0x09954), P(0x09958), P(0x09940), P(0x0c95c), P(0x09970),
|
||||
P(0x09974), P(0x09978), P(0x0997c), P(0x09980), P(0x09984),
|
||||
P(0x09988), P(0x0998c), P(0x09990), P(0x09994), P(0x09998),
|
||||
P(0x0999c), P(0x099a0), P(0x099a4), P(0x099a8), P(0x099ac),
|
||||
P(0x099b0), P(0x099dc), P(0x099e0), P(0x099e4), P(0x099e8),
|
||||
P(0x099ec), P(0x099fc), P(0x09b00), P(0x09b04), P(0x09b08),
|
||||
P(0x09b0c), P(0x09b10), P(0x09b14), P(0x09b18), P(0x09b1c),
|
||||
P(0x09b20), P(0x09b24), P(0x09b28), P(0x09b2c), P(0x09b30),
|
||||
P(0x09b34), P(0x09b38), P(0x09b3c), P(0x09b40), P(0x09b44),
|
||||
P(0x09b48), P(0x09b4c), P(0x09b50), P(0x09b54), P(0x09b58),
|
||||
P(0x09b5c), P(0x09b60), P(0x09b64), P(0x09b68), P(0x09b6c),
|
||||
P(0x09b70), P(0x09b74), P(0x09b78), P(0x09b7c), P(0x09b80),
|
||||
P(0x09b84), P(0x09b88), P(0x09b8c), P(0x09b90), P(0x09b94),
|
||||
P(0x09b98), P(0x09b9c), P(0x09ba0), P(0x09ba4), P(0x09ba8),
|
||||
P(0x09bac), P(0x09bb0), P(0x09bb4), P(0x09bb8), P(0x09bbc),
|
||||
P(0x09bc0), P(0x09bc4), P(0x09bc8), P(0x09bcc), P(0x09bd0),
|
||||
P(0x09bd4), P(0x09bd8), P(0x09bdc), P(0x09be0), P(0x09be4),
|
||||
P(0x09be8), P(0x09bec), P(0x09bf0), P(0x09bf4), P(0x09bf8),
|
||||
P(0x09bfc), P(0x0a210), P(0x0a214), P(0x0a218), P(0x0a220),
|
||||
P(0x0a224), P(0x0a228), P(0x0a22c), P(0x0a234), P(0x0a238),
|
||||
P(0x0a23c), P(0x0a240), P(0x0a244), P(0x0a248), P(0x0a24c),
|
||||
P(0x0a250), P(0x0a254), P(0x0a258), P(0x0a25c), P(0x0a260),
|
||||
P(0x0a268), P(0x0a26c), P(0x0b26c), P(0x0c26c), P(0x0d270),
|
||||
P(0x0a278), P(0x0a27c), P(0x0a338), P(0x0a33c), P(0x0a340),
|
||||
P(0x0a344), P(0x0a348), P(0x0a34c), P(0x0a350), P(0x0a354),
|
||||
P(0x0a358), P(0x0d35c), P(0x0d360), P(0x0d364), P(0x0d368),
|
||||
P(0x0d36c), P(0x0d370), P(0x0d374), P(0x0d378), P(0x0d37c),
|
||||
P(0x0d380), P(0x0d384), P(0x0a388), P(0x0a38c), P(0x0a390),
|
||||
P(0x0a394), P(0x0a398), P(0x0a39c), P(0x0a3a0), P(0x0a3a4),
|
||||
P(0x0a3a8), P(0x0a3ac), P(0x0a3b0), P(0x0a3b4), P(0x0a3b8),
|
||||
P(0x0a3bc), P(0x0a3c0), P(0x0a3c4), P(0x0a3c8), P(0x0a3cc),
|
||||
P(0x0a3d0), P(0x0a3d4), P(0x0a3dc), P(0x0a3e0)
|
||||
};
|
||||
|
||||
static const uint32_t ar9160_cm_vals[] = {
|
||||
0x00000000, 0x00020015, 0x00000005, 0x00000000, 0x00000008,
|
||||
0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
|
||||
0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
|
||||
0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000002, 0x00000002, 0x00000020, 0x000004c2,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000700, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x40000000, 0x00000000, 0x00000000,
|
||||
0x000fc78f, 0x0000000f, 0x00000000, 0x2a82301a, 0x05dc01e0,
|
||||
0x1f402710, 0x01f40000, 0x00001e00, 0x00000000, 0x00400000,
|
||||
0xffffffff, 0x0000ffff, 0x003f3f3f, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00020000, 0x00020000, 0x00000001,
|
||||
0x00000052, 0x00000000, 0x00000168, 0x000100aa, 0x00003210,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000,
|
||||
0x32143320, 0xfaa4fa50, 0x00000100, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00100000, 0x0010f400, 0x00000100, 0x0001e800,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x400000ff, 0x00080922,
|
||||
0x88a00010, 0x00000000, 0x40000000, 0x003e4180, 0x00000000,
|
||||
0x0000002c, 0x0000002c, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x00000302,
|
||||
0x00000e00, 0x00ff0000, 0x00000000, 0x000107ff, 0x00000000,
|
||||
0xad848e19, 0x7d14e000, 0x9c0a9f6b, 0x00000000, 0x0000a000,
|
||||
0x00000000, 0x00200400, 0x206a01ae, 0x1284233c, 0x00000859,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10000fff,
|
||||
0x05100000, 0x05100000, 0x05100000, 0x00000001, 0x00000004,
|
||||
0x1e1f2022, 0x0a0b0c0d, 0x00000000, 0x9280b212, 0x00020028,
|
||||
0x5f3ca3de, 0x2108ecff, 0x00750604, 0x004b6a8e, 0x190fb515,
|
||||
0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000001, 0x201fff00, 0x006f0000,
|
||||
0x03051000, 0x00000000, 0x00000200, 0xaaaaaaaa, 0x3c466478,
|
||||
0x0cc80caa, 0x00001042, 0x00000000, 0x00000001, 0x00000002,
|
||||
0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009,
|
||||
0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d, 0x00000010,
|
||||
0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015,
|
||||
0x00000018, 0x00000019, 0x0000001a, 0x0000001b, 0x0000001c,
|
||||
0x0000001d, 0x00000020, 0x00000021, 0x00000022, 0x00000023,
|
||||
0x00000024, 0x00000025, 0x00000028, 0x00000029, 0x0000002a,
|
||||
0x0000002b, 0x0000002c, 0x0000002d, 0x00000030, 0x00000031,
|
||||
0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000035,
|
||||
0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
|
||||
0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
|
||||
0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
|
||||
0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000010,
|
||||
0x0000001a, 0x40806333, 0x00106c10, 0x009c4060, 0x018830c6,
|
||||
0x00000400, 0x001a0bb5, 0x00000000, 0x20202020, 0x20202020,
|
||||
0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc, 0x00000001,
|
||||
0x0000e000, 0x00000000, 0x0cc75380, 0x0f0f0f01, 0xdfa91f01,
|
||||
0x00000001, 0x0e79e5c6, 0x0e79e5c6, 0x0e79e5c6, 0x00820820,
|
||||
0x1ce739ce, 0x050701ce, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff,
|
||||
0x79bfaa03, 0x07ffffef, 0x0fffffe7, 0x17ffffe5, 0x1fffffe4,
|
||||
0x37ffffe3, 0x3fffffe3, 0x57ffffe3, 0x5fffffe2, 0x7fffffe2,
|
||||
0x7f3c7bba, 0xf3307ff0, 0x0c000000, 0x20202020, 0x20202020,
|
||||
0x1ce739ce, 0x000001ce, 0x00000001, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000246, 0x20202020,
|
||||
0x20202020, 0x20202020, 0x1ce739ce, 0x000001ce
|
||||
};
|
||||
|
||||
static const struct athn_ini ar9160_ini = {
|
||||
.nregs = __arraycount(ar9160_regs),
|
||||
.regs = ar9160_regs,
|
||||
.vals_5g20 = ar9160_vals_5g20,
|
||||
#ifndef IEEE80211_NO_HT
|
||||
.vals_5g40 = ar9160_vals_5g40,
|
||||
.vals_2g40 = ar9160_vals_2g40,
|
||||
#endif
|
||||
.vals_2g20 = ar9160_vals_2g20,
|
||||
.ncmregs = __arraycount(ar9160_cm_regs),
|
||||
.cmregs = ar9160_cm_regs,
|
||||
.cmvals = ar9160_cm_vals
|
||||
};
|
||||
|
||||
/*
|
||||
* BB/RF Gains common to AR5416 and AR9160.
|
||||
*/
|
||||
static const uint32_t ar5416_bb_rfgain_vals_5g[] = {
|
||||
0x00000000, 0x00000040, 0x00000080, 0x000001a1, 0x000001e1,
|
||||
0x00000021, 0x00000061, 0x00000168, 0x000001a8, 0x000001e8,
|
||||
0x00000028, 0x00000068, 0x00000189, 0x000001c9, 0x00000009,
|
||||
0x00000049, 0x00000089, 0x00000170, 0x000001b0, 0x000001f0,
|
||||
0x00000030, 0x00000070, 0x00000191, 0x000001d1, 0x00000011,
|
||||
0x00000051, 0x00000091, 0x000001b8, 0x000001f8, 0x00000038,
|
||||
0x00000078, 0x00000199, 0x000001d9, 0x00000019, 0x00000059,
|
||||
0x00000099, 0x000000d9, 0x000000f9, 0x000000f9, 0x000000f9,
|
||||
0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
|
||||
0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
|
||||
0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
|
||||
0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
|
||||
0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9
|
||||
};
|
||||
|
||||
static const uint32_t ar5416_bb_rfgain_vals_2g[] = {
|
||||
0x00000000, 0x00000040, 0x00000080, 0x00000141, 0x00000181,
|
||||
0x000001c1, 0x00000001, 0x00000041, 0x000001a8, 0x000001e8,
|
||||
0x00000028, 0x00000068, 0x000000a8, 0x00000169, 0x000001a9,
|
||||
0x000001e9, 0x00000029, 0x00000069, 0x00000190, 0x000001d0,
|
||||
0x00000010, 0x00000050, 0x00000090, 0x00000151, 0x00000191,
|
||||
0x000001d1, 0x00000011, 0x00000051, 0x00000198, 0x000001d8,
|
||||
0x00000018, 0x00000058, 0x00000098, 0x00000159, 0x00000199,
|
||||
0x000001d9, 0x00000019, 0x00000059, 0x00000099, 0x000000d9,
|
||||
0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
|
||||
0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
|
||||
0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
|
||||
0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
|
||||
0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9
|
||||
};
|
||||
|
||||
static const uint32_t ar5416_2_1_addac_vals[] = {
|
||||
0x00000000, 0x00000003, 0x00000000, 0x0000000c, 0x00000000,
|
||||
0x00000030, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000060, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const struct athn_addac ar5416_2_1_addac = {
|
||||
__arraycount(ar5416_2_1_addac_vals),
|
||||
ar5416_2_1_addac_vals
|
||||
};
|
||||
|
||||
static const uint32_t ar5416_2_2_addac_vals[] = {
|
||||
0x00000000, 0x00000003, 0x00000000, 0x0000000c, 0x00000000,
|
||||
0x00000030, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000060, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000058, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const struct athn_addac ar5416_2_2_addac = {
|
||||
__arraycount(ar5416_2_2_addac_vals),
|
||||
ar5416_2_2_addac_vals
|
||||
};
|
||||
|
||||
static const uint32_t ar9160_1_0_addac_vals[] = {
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x000000c0, 0x00000018, 0x00000004, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x000000c0, 0x00000019, 0x00000004, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000004, 0x00000003, 0x00000008,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const struct athn_addac ar9160_1_0_addac = {
|
||||
__arraycount(ar9160_1_0_addac_vals),
|
||||
ar9160_1_0_addac_vals
|
||||
};
|
||||
|
||||
static const uint32_t ar9160_1_1_addac_vals[] = {
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x000000c0, 0x00000018, 0x00000004, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x000000c0, 0x00000019, 0x00000004, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const struct athn_addac ar9160_1_1_addac = {
|
||||
__arraycount(ar9160_1_1_addac_vals),
|
||||
ar9160_1_1_addac_vals
|
||||
};
|
||||
|
||||
static const uint32_t ar5416_bank6tpc_vals[] = {
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00e00000, 0x005e0000,
|
||||
0x00120000, 0x00620000, 0x00020000, 0x00ff0000, 0x00ff0000,
|
||||
0x00ff0000, 0x40ff0000, 0x005f0000, 0x00870000, 0x00f90000,
|
||||
0x007b0000, 0x00ff0000, 0x00f50000, 0x00dc0000, 0x00110000,
|
||||
0x006100a8, 0x00423022, 0x201400df, 0x00c40002, 0x003000f2,
|
||||
0x00440016, 0x00410040, 0x0001805e, 0x0000c0ab, 0x000000e1,
|
||||
0x00007081, 0x000000d4
|
||||
};
|
||||
|
||||
static const uint32_t ar9160_bank6tpc_vals[] = {
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00e00000, 0x005e0000,
|
||||
0x00120000, 0x00620000, 0x00020000, 0x00ff0000, 0x00ff0000,
|
||||
0x00ff0000, 0x40ff0000, 0x005f0000, 0x00870000, 0x00f90000,
|
||||
0x007b0000, 0x00ff0000, 0x00f50000, 0x00dc0000, 0x00110000,
|
||||
0x006100a8, 0x00423022, 0x2014008f, 0x00c40002, 0x003000f2,
|
||||
0x00440016, 0x00410040, 0x0001805e, 0x0000c0ab, 0x000000e1,
|
||||
0x00007080, 0x000000d4
|
||||
};
|
||||
|
||||
static const uint32_t ar5416_bank6_vals[] = {
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00e00000, 0x005e0000,
|
||||
0x00120000, 0x00620000, 0x00020000, 0x00ff0000, 0x00ff0000,
|
||||
0x00ff0000, 0x40ff0000, 0x005f0000, 0x00870000, 0x00f90000,
|
||||
0x007b0000, 0x00ff0000, 0x00f50000, 0x00dc0000, 0x00110000,
|
||||
0x006100a8, 0x004210a2, 0x0014008f, 0x00c40003, 0x003000f2,
|
||||
0x00440016, 0x00410040, 0x0001805e, 0x0000c0ab, 0x000000f1,
|
||||
0x00002081, 0x000000d4
|
||||
};
|
||||
|
||||
/*
|
||||
* Serializer/Deserializer programming.
|
||||
*/
|
||||
|
||||
static const uint32_t ar5416_serdes_regs[] = {
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES2
|
||||
};
|
||||
|
||||
static const uint32_t ar5416_serdes_vals[] = {
|
||||
0x9248fc00,
|
||||
0x24924924,
|
||||
/* RX shut off when elecidle is asserted. */
|
||||
0x28000039,
|
||||
0x53160824,
|
||||
0xe5980579,
|
||||
0x001defff,
|
||||
0x1aaabe40,
|
||||
0xbe105554,
|
||||
0x000e3007,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const struct athn_serdes ar5416_serdes = {
|
||||
__arraycount(ar5416_serdes_vals),
|
||||
ar5416_serdes_regs,
|
||||
ar5416_serdes_vals,
|
||||
};
|
||||
|
||||
#endif /* _ARN5416REG_H_ */
|
3447
sys/dev/ic/arn9003.c
Normal file
3447
sys/dev/ic/arn9003.c
Normal file
File diff suppressed because it is too large
Load Diff
42
sys/dev/ic/arn9003.h
Normal file
42
sys/dev/ic/arn9003.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* $NetBSD: arn9003.h,v 1.1 2013/03/30 02:53:01 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _IF_ARN9003_H_
|
||||
#define _IF_ARN9003_H_
|
||||
|
||||
int ar9003_attach(struct athn_softc *);
|
||||
int ar9003_init_calib(struct athn_softc *);
|
||||
void ar9003_reset_txsring(struct athn_softc *);
|
||||
void ar9003_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *,
|
||||
uint8_t, const uint8_t *, const struct ar_cal_target_power_leg *,
|
||||
int, uint8_t[]);
|
||||
void ar9003_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *,
|
||||
uint8_t, const uint8_t *, const struct ar_cal_target_power_ht *,
|
||||
int, uint8_t[]);
|
||||
void ar9003_write_txpower(struct athn_softc *, int16_t power[]);
|
||||
|
||||
#endif /* _IF_ARN9003_H_ */
|
1205
sys/dev/ic/arn9003reg.h
Normal file
1205
sys/dev/ic/arn9003reg.h
Normal file
File diff suppressed because it is too large
Load Diff
627
sys/dev/ic/arn9280.c
Normal file
627
sys/dev/ic/arn9280.c
Normal file
@ -0,0 +1,627 @@
|
||||
/* $NetBSD: arn9280.c,v 1.1 2013/03/30 02:53:01 christos Exp $ */
|
||||
/* $OpenBSD: ar9280.c,v 1.18 2012/06/10 21:23:36 kettenis Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Driver for Atheros 802.11a/g/n chipsets.
|
||||
* Routines for AR9220, AR9223, AR9280 and AR9281 chipsets.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: arn9280.c,v 1.1 2013/03/30 02:53:01 christos Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/intr.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_amrr.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/ic/athnreg.h>
|
||||
#include <dev/ic/athnvar.h>
|
||||
|
||||
#include <dev/ic/arn5008reg.h>
|
||||
#include <dev/ic/arn5008.h>
|
||||
#include <dev/ic/arn5416reg.h> /* We share the ROM layout. */
|
||||
#include <dev/ic/arn5416.h> /* We share the ROM layout. */
|
||||
#include <dev/ic/arn9280reg.h>
|
||||
#include <dev/ic/arn9280.h>
|
||||
|
||||
#define Static static
|
||||
|
||||
Static void ar9280_init_from_rom(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9280_olpc_init(struct athn_softc *);
|
||||
Static void ar9280_olpc_temp_compensation(struct athn_softc *);
|
||||
Static void ar9280_setup(struct athn_softc *);
|
||||
|
||||
PUBLIC int
|
||||
ar9280_attach(struct athn_softc *sc)
|
||||
{
|
||||
|
||||
sc->sc_eep_base = AR5416_EEP_START_LOC;
|
||||
sc->sc_eep_size = sizeof(struct ar5416_eeprom);
|
||||
sc->sc_def_nf = AR9280_PHY_CCA_MAX_GOOD_VALUE;
|
||||
sc->sc_ngpiopins = (sc->sc_flags & ATHN_FLAG_USB) ? 16 : 10;
|
||||
sc->sc_led_pin = 1;
|
||||
sc->sc_workaround = AR9280_WA_DEFAULT;
|
||||
sc->sc_ops.setup = ar9280_setup;
|
||||
sc->sc_ops.swap_rom = ar5416_swap_rom;
|
||||
sc->sc_ops.init_from_rom = ar9280_init_from_rom;
|
||||
sc->sc_ops.set_txpower = ar5416_set_txpower;
|
||||
sc->sc_ops.set_synth = ar9280_set_synth;
|
||||
sc->sc_ops.spur_mitigate = ar9280_spur_mitigate;
|
||||
sc->sc_ops.get_spur_chans = ar5416_get_spur_chans;
|
||||
sc->sc_ops.olpc_init = ar9280_olpc_init;
|
||||
sc->sc_ops.olpc_temp_compensation = ar9280_olpc_temp_compensation;
|
||||
sc->sc_ini = &ar9280_2_0_ini;
|
||||
sc->sc_serdes = &ar9280_2_0_serdes;
|
||||
|
||||
return ar5008_attach(sc);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9280_setup(struct athn_softc *sc)
|
||||
{
|
||||
const struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
uint8_t type;
|
||||
|
||||
/* Determine if open loop power control should be used. */
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_19 &&
|
||||
eep->baseEepHeader.openLoopPwrCntl)
|
||||
sc->sc_flags |= ATHN_FLAG_OLPC;
|
||||
|
||||
/* Determine if fast PLL clock is supported. */
|
||||
if (AR_SREV_9280_20(sc) &&
|
||||
(sc->sc_eep_rev <= AR_EEP_MINOR_VER_16 ||
|
||||
eep->baseEepHeader.fastClk5g))
|
||||
sc->sc_flags |= ATHN_FLAG_FAST_PLL_CLOCK;
|
||||
|
||||
/*
|
||||
* Determine if initialization value for AR_AN_TOP2 must be fixed.
|
||||
* This is required for some AR9220 devices such as Ubiquiti SR71-12.
|
||||
*/
|
||||
if (AR_SREV_9280_20(sc) &&
|
||||
sc->sc_eep_rev > AR_EEP_MINOR_VER_10 &&
|
||||
!eep->baseEepHeader.pwdclkind) {
|
||||
DPRINTFN(DBG_INIT, sc, "AR_AN_TOP2 fixup required\n");
|
||||
sc->sc_flags |= ATHN_FLAG_AN_TOP2_FIXUP;
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_20(sc)) {
|
||||
/* Check if we have a valid rxGainType field in ROM. */
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_17) {
|
||||
/* Select initialization values based on ROM. */
|
||||
type = eep->baseEepHeader.rxGainType;
|
||||
DPRINTFN(DBG_INIT, sc, "Rx gain type=0x%x\n", type);
|
||||
if (type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
|
||||
sc->sc_rx_gain = &ar9280_2_0_rx_gain_23db_backoff;
|
||||
else if (type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
|
||||
sc->sc_rx_gain = &ar9280_2_0_rx_gain_13db_backoff;
|
||||
else
|
||||
sc->sc_rx_gain = &ar9280_2_0_rx_gain;
|
||||
}
|
||||
else
|
||||
sc->sc_rx_gain = &ar9280_2_0_rx_gain;
|
||||
|
||||
/* Check if we have a valid txGainType field in ROM. */
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_19) {
|
||||
/* Select initialization values based on ROM. */
|
||||
type = eep->baseEepHeader.txGainType;
|
||||
DPRINTFN(DBG_INIT, sc, "Tx gain type=0x%x\n", type);
|
||||
if (type == AR_EEP_TXGAIN_HIGH_POWER)
|
||||
sc->sc_tx_gain = &ar9280_2_0_tx_gain_high_power;
|
||||
else
|
||||
sc->sc_tx_gain = &ar9280_2_0_tx_gain;
|
||||
}
|
||||
else
|
||||
sc->sc_tx_gain = &ar9280_2_0_tx_gain;
|
||||
}
|
||||
}
|
||||
|
||||
PUBLIC int
|
||||
ar9280_set_synth(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
uint32_t phy, reg, ndiv = 0;
|
||||
uint32_t freq = c->ic_freq;
|
||||
|
||||
phy = AR_READ(sc, AR9280_PHY_SYNTH_CONTROL) & ~0x3fffffff;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
phy |= (freq << 16) / 15;
|
||||
phy |= AR9280_BMODE | AR9280_FRACMODE;
|
||||
|
||||
if (AR_SREV_9287_11_OR_LATER(sc)) {
|
||||
/* NB: Magic values from the Linux driver. */
|
||||
if (freq == 2484) { /* Channel 14. */
|
||||
/* Japanese regulatory requirements. */
|
||||
AR_WRITE(sc, AR_PHY(637), 0x00000000);
|
||||
AR_WRITE(sc, AR_PHY(638), 0xefff0301);
|
||||
AR_WRITE(sc, AR_PHY(639), 0xca9228ee);
|
||||
}
|
||||
else {
|
||||
AR_WRITE(sc, AR_PHY(637), 0x00fffeff);
|
||||
AR_WRITE(sc, AR_PHY(638), 0x00f5f9ff);
|
||||
AR_WRITE(sc, AR_PHY(639), 0xb79f6427);
|
||||
}
|
||||
}
|
||||
else {
|
||||
reg = AR_READ(sc, AR_PHY_CCK_TX_CTRL);
|
||||
if (freq == 2484) /* Channel 14. */
|
||||
reg |= AR_PHY_CCK_TX_CTRL_JAPAN;
|
||||
else
|
||||
reg &= ~AR_PHY_CCK_TX_CTRL_JAPAN;
|
||||
AR_WRITE(sc, AR_PHY_CCK_TX_CTRL, reg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (AR_SREV_9285_10_OR_LATER(sc) ||
|
||||
sc->sc_eep_rev < AR_EEP_MINOR_VER_22 ||
|
||||
!((struct ar5416_base_eep_header *)sc->sc_eep)->frac_n_5g) {
|
||||
if ((freq % 20) == 0) {
|
||||
ndiv = (freq * 3) / 60;
|
||||
phy |= SM(AR9280_AMODE_REFSEL, 3);
|
||||
}
|
||||
else if ((freq % 10) == 0) {
|
||||
ndiv = (freq * 6) / 60;
|
||||
phy |= SM(AR9280_AMODE_REFSEL, 2);
|
||||
}
|
||||
}
|
||||
if (ndiv != 0) {
|
||||
phy |= (ndiv & 0x1ff) << 17;
|
||||
phy |= (ndiv & ~0x1ff) * 2;
|
||||
}
|
||||
else {
|
||||
phy |= (freq << 15) / 15;
|
||||
phy |= AR9280_FRACMODE;
|
||||
|
||||
reg = AR_READ(sc, AR_AN_SYNTH9);
|
||||
reg = RW(reg, AR_AN_SYNTH9_REFDIVA, 1);
|
||||
AR_WRITE(sc, AR_AN_SYNTH9, reg);
|
||||
}
|
||||
}
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DPRINTFN(DBG_RF, sc, "AR9280_PHY_SYNTH_CONTROL=0x%08x\n", phy);
|
||||
AR_WRITE(sc, AR9280_PHY_SYNTH_CONTROL, phy);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9280_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
|
||||
const struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
const struct ar5416_modal_eep_header *modal;
|
||||
uint32_t reg, offset;
|
||||
uint8_t txRxAtten;
|
||||
int i;
|
||||
|
||||
modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
|
||||
|
||||
AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon);
|
||||
|
||||
for (i = 0; i < AR9280_MAX_CHAINS; i++) {
|
||||
if (sc->sc_rxchainmask == 0x5 || sc->sc_txchainmask == 0x5)
|
||||
offset = chainoffset[i];
|
||||
else
|
||||
offset = i * 0x1000;
|
||||
|
||||
AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0 + offset,
|
||||
modal->antCtrlChain[i]);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0 + offset);
|
||||
reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
|
||||
modal->iqCalICh[i]);
|
||||
reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
|
||||
modal->iqCalQCh[i]);
|
||||
AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0 + offset, reg);
|
||||
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3) {
|
||||
reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
|
||||
modal->bswMargin[i]);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
|
||||
modal->bswAtten[i]);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
|
||||
modal->xatten2Margin[i]);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
|
||||
modal->xatten2Db[i]);
|
||||
AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
|
||||
}
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3)
|
||||
txRxAtten = modal->txRxAttenCh[i];
|
||||
else /* Workaround for ROM versions < 14.3. */
|
||||
txRxAtten = IEEE80211_IS_CHAN_2GHZ(c) ? 23 : 44;
|
||||
reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
|
||||
reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN,
|
||||
txRxAtten);
|
||||
reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN,
|
||||
modal->rxTxMarginCh[i]);
|
||||
AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
|
||||
}
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
reg = AR_READ(sc, AR_AN_RF2G1_CH0);
|
||||
reg = RW(reg, AR_AN_RF2G1_CH0_OB, modal->ob);
|
||||
reg = RW(reg, AR_AN_RF2G1_CH0_DB, modal->db);
|
||||
AR_WRITE(sc, AR_AN_RF2G1_CH0, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
|
||||
reg = AR_READ(sc, AR_AN_RF2G1_CH1);
|
||||
reg = RW(reg, AR_AN_RF2G1_CH1_OB, modal->ob_ch1);
|
||||
reg = RW(reg, AR_AN_RF2G1_CH1_DB, modal->db_ch1);
|
||||
AR_WRITE(sc, AR_AN_RF2G1_CH1, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
}
|
||||
else {
|
||||
reg = AR_READ(sc, AR_AN_RF5G1_CH0);
|
||||
reg = RW(reg, AR_AN_RF5G1_CH0_OB5, modal->ob);
|
||||
reg = RW(reg, AR_AN_RF5G1_CH0_DB5, modal->db);
|
||||
AR_WRITE(sc, AR_AN_RF5G1_CH0, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
|
||||
reg = AR_READ(sc, AR_AN_RF5G1_CH1);
|
||||
reg = RW(reg, AR_AN_RF5G1_CH1_OB5, modal->ob_ch1);
|
||||
reg = RW(reg, AR_AN_RF5G1_CH1_DB5, modal->db_ch1);
|
||||
AR_WRITE(sc, AR_AN_RF5G1_CH1, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
}
|
||||
reg = AR_READ(sc, AR_AN_TOP2);
|
||||
if ((sc->sc_flags & ATHN_FLAG_USB) && IEEE80211_IS_CHAN_5GHZ(c)) {
|
||||
/*
|
||||
* Hardcode the output voltage of x-PA bias LDO to the
|
||||
* lowest value for UB94 such that the card doesn't get
|
||||
* too hot.
|
||||
*/
|
||||
reg = RW(reg, AR_AN_TOP2_XPABIAS_LVL, 0);
|
||||
}
|
||||
else
|
||||
reg = RW(reg, AR_AN_TOP2_XPABIAS_LVL, modal->xpaBiasLvl);
|
||||
if (modal->flagBits & AR5416_EEP_FLAG_LOCALBIAS)
|
||||
reg |= AR_AN_TOP2_LOCALBIAS;
|
||||
else
|
||||
reg &= ~AR_AN_TOP2_LOCALBIAS;
|
||||
AR_WRITE(sc, AR_AN_TOP2, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_XPA_CFG);
|
||||
if (modal->flagBits & AR5416_EEP_FLAG_FORCEXPAON)
|
||||
reg |= AR_PHY_FORCE_XPA_CFG;
|
||||
else
|
||||
reg &= ~AR_PHY_FORCE_XPA_CFG;
|
||||
AR_WRITE(sc, AR_PHY_XPA_CFG, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_SETTLING);
|
||||
reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
|
||||
AR_WRITE(sc, AR_PHY_SETTLING, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
|
||||
reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
|
||||
AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
|
||||
|
||||
reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
|
||||
reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
|
||||
reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
|
||||
reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_RF_CTL3);
|
||||
reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_CCA(0));
|
||||
reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62);
|
||||
AR_WRITE(sc, AR_PHY_CCA(0), reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_EXT_CCA0);
|
||||
reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62);
|
||||
AR_WRITE(sc, AR_PHY_EXT_CCA0, reg);
|
||||
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2) {
|
||||
reg = AR_READ(sc, AR_PHY_RF_CTL2);
|
||||
reg = RW(reg, AR_PHY_TX_END_DATA_START,
|
||||
modal->txFrameToDataStart);
|
||||
reg = RW(reg, AR_PHY_TX_END_PA_ON, modal->txFrameToPaOn);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
|
||||
}
|
||||
#ifndef IEEE80211_NO_HT
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
|
||||
/* Overwrite switch settling with HT-40 value. */
|
||||
reg = AR_READ(sc, AR_PHY_SETTLING);
|
||||
reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
|
||||
AR_WRITE(sc, AR_PHY_SETTLING, reg);
|
||||
}
|
||||
#endif
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_19) {
|
||||
reg = AR_READ(sc, AR_PHY_CCK_TX_CTRL);
|
||||
reg = RW(reg, AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
|
||||
MS(modal->miscBits, AR5416_EEP_MISC_TX_DAC_SCALE_CCK));
|
||||
AR_WRITE(sc, AR_PHY_CCK_TX_CTRL, reg);
|
||||
}
|
||||
if (AR_SREV_9280_20(sc) &&
|
||||
sc->sc_eep_rev >= AR_EEP_MINOR_VER_20) {
|
||||
reg = AR_READ(sc, AR_AN_TOP1);
|
||||
if (eep->baseEepHeader.dacLpMode &&
|
||||
(IEEE80211_IS_CHAN_2GHZ(c) ||
|
||||
!eep->baseEepHeader.dacHiPwrMode_5G))
|
||||
reg |= AR_AN_TOP1_DACLPMODE;
|
||||
else
|
||||
reg &= ~AR_AN_TOP1_DACLPMODE;
|
||||
AR_WRITE(sc, AR_AN_TOP1, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_FRAME_CTL);
|
||||
reg = RW(reg, AR_PHY_FRAME_CTL_TX_CLIP,
|
||||
MS(modal->miscBits, AR5416_EEP_MISC_TX_CLIP));
|
||||
AR_WRITE(sc, AR_PHY_FRAME_CTL, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TX_PWRCTRL9);
|
||||
reg = RW(reg, AR_PHY_TX_DESIRED_SCALE_CCK,
|
||||
eep->baseEepHeader.desiredScaleCCK);
|
||||
AR_WRITE(sc, AR_PHY_TX_PWRCTRL9, reg);
|
||||
}
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar9280_olpc_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
int chain, uint8_t *boundaries, uint8_t *pdadcs, uint8_t *txgain)
|
||||
{
|
||||
const struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
const struct ar_cal_data_per_freq_olpc *pierdata;
|
||||
const uint8_t *pierfreq;
|
||||
uint8_t fbin, pcdac, pwr, idx;
|
||||
int i, lo, hi, npiers;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
pierfreq = eep->calFreqPier2G;
|
||||
pierdata = (const struct ar_cal_data_per_freq_olpc *)
|
||||
eep->calPierData2G[chain];
|
||||
npiers = AR5416_NUM_2G_CAL_PIERS;
|
||||
}
|
||||
else {
|
||||
pierfreq = eep->calFreqPier5G;
|
||||
pierdata = (const struct ar_cal_data_per_freq_olpc *)
|
||||
eep->calPierData5G[chain];
|
||||
npiers = AR5416_NUM_5G_CAL_PIERS;
|
||||
}
|
||||
/* Find channel in ROM pier table. */
|
||||
fbin = athn_chan2fbin(c);
|
||||
athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
|
||||
|
||||
/* Get average. */
|
||||
pwr = (pierdata[lo].pwrPdg[0][0] + pierdata[hi].pwrPdg[0][0]) / 2;
|
||||
pwr /= 2; /* Convert to dB. */
|
||||
|
||||
/* Find power control digital-to-analog converter (PCDAC) value. */
|
||||
pcdac = pierdata[hi].pcdac[0][0];
|
||||
for (idx = 0; idx < AR9280_TX_GAIN_TABLE_SIZE - 1; idx++)
|
||||
if (pcdac <= sc->sc_tx_gain_tbl[idx])
|
||||
break;
|
||||
*txgain = idx;
|
||||
|
||||
DPRINTFN(DBG_RF, sc,
|
||||
"fbin=%d lo=%d hi=%d pwr=%d pcdac=%d txgain=%d\n",
|
||||
fbin, lo, hi, pwr, pcdac, idx);
|
||||
|
||||
/* Fill phase domain analog-to-digital converter (PDADC) table. */
|
||||
for (i = 0; i < AR_NUM_PDADC_VALUES; i++)
|
||||
pdadcs[i] = (i < pwr) ? 0x00 : 0xff;
|
||||
|
||||
for (i = 0; i < AR_PD_GAINS_IN_MASK; i++)
|
||||
boundaries[i] = AR9280_PD_GAIN_BOUNDARY_DEFAULT;
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar9280_spur_mitigate(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
const struct ar_spur_chan *spurchans;
|
||||
int spur, bin, spur_delta_phase, spur_freq_sd, spur_subchannel_sd;
|
||||
int spur_off, range, i;
|
||||
|
||||
/* NB: Always clear. */
|
||||
AR_CLRBITS(sc, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
|
||||
|
||||
range = (extc != NULL) ? 19 : 10;
|
||||
|
||||
spurchans = sc->sc_ops.get_spur_chans(sc, IEEE80211_IS_CHAN_2GHZ(c));
|
||||
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
|
||||
spur = spurchans[i].spurChan;
|
||||
if (spur == AR_NO_SPUR)
|
||||
return; /* XXX disable if it was enabled! */
|
||||
spur /= 10;
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
spur += AR_BASE_FREQ_2GHZ;
|
||||
else
|
||||
spur += AR_BASE_FREQ_5GHZ;
|
||||
spur -= c->ic_freq;
|
||||
if (abs(spur) < range)
|
||||
break;
|
||||
}
|
||||
if (i == AR_EEPROM_MODAL_SPURS)
|
||||
return; /* XXX disable if it was enabled! */
|
||||
DPRINTFN(DBG_RF, sc, "enabling spur mitigation\n");
|
||||
|
||||
AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0,
|
||||
AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
|
||||
AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
|
||||
AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
|
||||
AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
|
||||
|
||||
AR_WRITE(sc, AR_PHY_SPUR_REG,
|
||||
AR_PHY_SPUR_REG_MASK_RATE_CNTL |
|
||||
AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
|
||||
AR_PHY_SPUR_REG_MASK_RATE_SELECT |
|
||||
AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
|
||||
SM(AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, AR_SPUR_RSSI_THRESH));
|
||||
|
||||
#ifndef IEEE80211_NO_HT
|
||||
if (extc != NULL) {
|
||||
spur_delta_phase = (spur * 262144) / 10;
|
||||
if (spur < 0) {
|
||||
spur_subchannel_sd = 1;
|
||||
spur_off = spur + 10;
|
||||
}
|
||||
else {
|
||||
spur_subchannel_sd = 0;
|
||||
spur_off = spur - 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
spur_delta_phase = (spur * 524288) / 10;
|
||||
spur_subchannel_sd = 0;
|
||||
spur_off = spur;
|
||||
}
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
spur_freq_sd = (spur_off * 2048) / 44;
|
||||
else
|
||||
spur_freq_sd = (spur_off * 2048) / 40;
|
||||
|
||||
AR_WRITE(sc, AR_PHY_TIMING11,
|
||||
AR_PHY_TIMING11_USE_SPUR_IN_AGC |
|
||||
SM(AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd) |
|
||||
SM(AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase));
|
||||
|
||||
AR_WRITE(sc, AR_PHY_SFCORR_EXT,
|
||||
SM(AR_PHY_SFCORR_SPUR_SUBCHNL_SD, spur_subchannel_sd));
|
||||
AR_WRITE_BARRIER(sc);
|
||||
|
||||
bin = spur * 320;
|
||||
ar5008_set_viterbi_mask(sc, bin);
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar9280_reset_rx_gain(struct athn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
const struct athn_gain *prog = sc->sc_rx_gain;
|
||||
const uint32_t *pvals;
|
||||
int i;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
pvals = prog->vals_2g;
|
||||
else
|
||||
pvals = prog->vals_5g;
|
||||
for (i = 0; i < prog->nregs; i++)
|
||||
AR_WRITE(sc, prog->regs[i], pvals[i]);
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar9280_reset_tx_gain(struct athn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
const struct athn_gain *prog = sc->sc_tx_gain;
|
||||
const uint32_t *pvals;
|
||||
int i;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
pvals = prog->vals_2g;
|
||||
else
|
||||
pvals = prog->vals_5g;
|
||||
for (i = 0; i < prog->nregs; i++)
|
||||
AR_WRITE(sc, prog->regs[i], pvals[i]);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9280_olpc_init(struct athn_softc *sc)
|
||||
{
|
||||
uint32_t reg;
|
||||
int i;
|
||||
|
||||
/* Save original Tx gain values. */
|
||||
for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
|
||||
reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i));
|
||||
sc->sc_tx_gain_tbl[i] = MS(reg, AR_PHY_TX_GAIN);
|
||||
}
|
||||
/* Initial Tx gain temperature compensation. */
|
||||
sc->sc_tcomp = 0;
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9280_olpc_temp_compensation(struct athn_softc *sc)
|
||||
{
|
||||
const struct ar5416_eeprom *eep = sc->sc_eep;
|
||||
int8_t pdadc, txgain, tcomp;
|
||||
uint32_t reg;
|
||||
int i;
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TX_PWRCTRL4);
|
||||
pdadc = MS(reg, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
|
||||
DPRINTFN(DBG_RF, sc, "PD Avg Out=%d\n", pdadc);
|
||||
|
||||
if (sc->sc_pdadc == 0 || pdadc == 0)
|
||||
return; /* No frames transmitted yet. */
|
||||
|
||||
/* Compute Tx gain temperature compensation. */
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_20 &&
|
||||
eep->baseEepHeader.dacHiPwrMode_5G)
|
||||
tcomp = (pdadc - sc->sc_pdadc + 4) / 8;
|
||||
else
|
||||
tcomp = (pdadc - sc->sc_pdadc + 5) / 10;
|
||||
DPRINTFN(DBG_RF, sc, "OLPC temp compensation=%d\n", tcomp);
|
||||
|
||||
if (tcomp == sc->sc_tcomp)
|
||||
return; /* Don't rewrite the same values. */
|
||||
sc->sc_tcomp = tcomp;
|
||||
|
||||
/* Adjust Tx gain values. */
|
||||
for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
|
||||
txgain = sc->sc_tx_gain_tbl[i] - tcomp;
|
||||
if (txgain < 0)
|
||||
txgain = 0;
|
||||
reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i));
|
||||
reg = RW(reg, AR_PHY_TX_GAIN, txgain);
|
||||
AR_WRITE(sc, AR_PHY_TX_GAIN_TBL(i), reg);
|
||||
}
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
42
sys/dev/ic/arn9280.h
Normal file
42
sys/dev/ic/arn9280.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* $NetBSD: arn9280.h,v 1.1 2013/03/30 02:53:01 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _IF_ARN9280_H_
|
||||
#define _IF_ARN9280_H_
|
||||
|
||||
int ar9280_attach(struct athn_softc *);
|
||||
void ar9280_reset_rx_gain(struct athn_softc *, struct ieee80211_channel *);
|
||||
void ar9280_reset_tx_gain(struct athn_softc *, struct ieee80211_channel *);
|
||||
void ar9280_olpc_get_pdadcs(struct athn_softc *, struct ieee80211_channel *,
|
||||
int, uint8_t *, uint8_t *, uint8_t *);
|
||||
|
||||
int ar9280_set_synth(struct athn_softc *, struct ieee80211_channel *,
|
||||
struct ieee80211_channel *);
|
||||
void ar9280_spur_mitigate(struct athn_softc *, struct ieee80211_channel *,
|
||||
struct ieee80211_channel *);
|
||||
|
||||
#endif /* _IF_ARN9280_H_ */
|
630
sys/dev/ic/arn9280reg.h
Normal file
630
sys/dev/ic/arn9280reg.h
Normal file
@ -0,0 +1,630 @@
|
||||
/* $NetBSD: arn9280reg.h,v 1.1 2013/03/30 02:53:01 christos Exp $ */
|
||||
/* $OpenBSD: ar9280reg.h,v 1.6 2012/10/20 09:54:20 stsp Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _ARN9280REG_H_
|
||||
#define _ARN9280REG_H_
|
||||
|
||||
#define AR9280_MAX_CHAINS 2
|
||||
|
||||
#define AR9280_PD_GAIN_BOUNDARY_DEFAULT 56
|
||||
#define AR9280_PHY_CCA_MAX_GOOD_VALUE (-112)
|
||||
|
||||
#define AR9280_PHY_SYNTH_CONTROL 0x9874
|
||||
|
||||
/* Bits for AR9280_PHY_SYNTH_CONTROL. */
|
||||
#define AR9280_BMODE 0x20000000
|
||||
#define AR9280_FRACMODE 0x10000000
|
||||
#define AR9280_AMODE_REFSEL_M 0x0c000000
|
||||
#define AR9280_AMODE_REFSEL_S 26
|
||||
|
||||
/*
|
||||
* NB: The AR9280 uses the same ROM layout than the AR5416.
|
||||
*/
|
||||
|
||||
/* Macro to "pack" registers to 16-bit to save some .rodata space. */
|
||||
#define P(x) (x)
|
||||
|
||||
/*
|
||||
* AR9280 2.0 initialization values.
|
||||
*/
|
||||
static const uint16_t ar9280_2_0_regs[] = {
|
||||
P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
|
||||
P(0x0801c), P(0x08120), P(0x081d0), P(0x08318), P(0x09804),
|
||||
P(0x09820), P(0x09824), P(0x09828), P(0x09834), P(0x09838),
|
||||
P(0x09840), P(0x09844), P(0x09850), P(0x09858), P(0x0985c),
|
||||
P(0x09860), P(0x09864), P(0x09868), P(0x0986c), P(0x09914),
|
||||
P(0x09918), P(0x09924), P(0x09944), P(0x09960), P(0x0a960),
|
||||
P(0x09964), P(0x0c968), P(0x099b8), P(0x099bc), P(0x099c0),
|
||||
P(0x0a204), P(0x0a20c), P(0x0b20c), P(0x0a21c), P(0x0a230),
|
||||
P(0x0a23c), P(0x0a250), P(0x0a358), P(0x0a388), P(0x0a3d8),
|
||||
P(0x07894)
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_vals_5g20[] = {
|
||||
0x00000230, 0x00000168, 0x00000e60, 0x00000000, 0x03e803e8,
|
||||
0x128d8027, 0x08f04800, 0x00003210, 0x00003e80, 0x00000300,
|
||||
0x02020200, 0x01000e0e, 0x0a020001, 0x00000e0e, 0x00000007,
|
||||
0x206a022e, 0x0372161e, 0x6c4000e2, 0x7ec88d2e, 0x31395d5e,
|
||||
0x00048d18, 0x0001ce00, 0x5ac640d0, 0x06903081, 0x000007d0,
|
||||
0x0000000a, 0xd00a8a0b, 0xffbc1010, 0x00000010, 0x00000010,
|
||||
0x00000210, 0x000003b5, 0x0000001c, 0x00000a00, 0x05eea6d4,
|
||||
0x00000444, 0x00000014, 0x00000014, 0x1883800a, 0x00000000,
|
||||
0x13c88000, 0x001ff000, 0x7999aa02, 0x0c000000, 0x00000000,
|
||||
0x5a508000
|
||||
};
|
||||
|
||||
#ifndef IEEE80211_NO_HT
|
||||
static const uint32_t ar9280_2_0_vals_5g40[] = {
|
||||
0x00000460, 0x000002d0, 0x00001cc0, 0x00000000, 0x07d007d0,
|
||||
0x128d804f, 0x08f04800, 0x00003210, 0x00007d00, 0x000003c4,
|
||||
0x02020200, 0x01000e0e, 0x0a020001, 0x00000e0e, 0x00000007,
|
||||
0x206a022e, 0x0372161e, 0x6d4000e2, 0x7ec88d2e, 0x3139605e,
|
||||
0x00048d18, 0x0001ce00, 0x5ac640d0, 0x06903081, 0x00000fa0,
|
||||
0x00000014, 0xd00a8a0b, 0xffbc1010, 0x00000010, 0x00000010,
|
||||
0x00000210, 0x000003b5, 0x0000001c, 0x00000a00, 0x05eea6d4,
|
||||
0x00000444, 0x00000014, 0x00000014, 0x1883800a, 0x00000000,
|
||||
0x13c88000, 0x001ff000, 0x7999aa02, 0x0c000000, 0x00000000,
|
||||
0x5a508000
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_vals_2g40[] = {
|
||||
0x000002c0, 0x00000318, 0x00007c70, 0x00000000, 0x10801600,
|
||||
0x12e00057, 0x08f04810, 0x0000320a, 0x00006880, 0x000003c4,
|
||||
0x02020200, 0x01000e0e, 0x0a020001, 0x00000e0e, 0x00000007,
|
||||
0x206a012e, 0x037216a0, 0x6d4000e2, 0x7ec84d2e, 0x3139605e,
|
||||
0x00048d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00001130,
|
||||
0x00000268, 0xd00a8a0d, 0xffbc1010, 0x00000010, 0x00000010,
|
||||
0x00000210, 0x000003ce, 0x0000001c, 0x00000c00, 0x05eea6d4,
|
||||
0x00000444, 0x0001f019, 0x0001f019, 0x1883800a, 0x00000210,
|
||||
0x13c88001, 0x0004a000, 0x7999aa0e, 0x08000000, 0x00000000,
|
||||
0x5a508000
|
||||
};
|
||||
#endif
|
||||
|
||||
static const uint32_t ar9280_2_0_vals_2g20[] = {
|
||||
0x00000160, 0x0000018c, 0x00003e38, 0x00000000, 0x08400b00,
|
||||
0x12e0002b, 0x08f04810, 0x0000320a, 0x00003440, 0x00000300,
|
||||
0x02020200, 0x01000e0e, 0x0a020001, 0x00000e0e, 0x00000007,
|
||||
0x206a012e, 0x037216a0, 0x6c4000e2, 0x7ec84d2e, 0x31395d5e,
|
||||
0x00048d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00000898,
|
||||
0x0000000b, 0xd00a8a0d, 0xffbc1010, 0x00000010, 0x00000010,
|
||||
0x00000210, 0x000003ce, 0x0000001c, 0x00000c00, 0x05eea6d4,
|
||||
0x00000444, 0x0001f019, 0x0001f019, 0x1883800a, 0x00000108,
|
||||
0x13c88000, 0x0004a000, 0x7999aa0e, 0x0c000000, 0x00000000,
|
||||
0x5a508000
|
||||
};
|
||||
|
||||
static const uint16_t ar9280_2_0_cm_regs[] = {
|
||||
P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
|
||||
P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
|
||||
P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
|
||||
P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
|
||||
P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
|
||||
P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
|
||||
P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
|
||||
P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
|
||||
P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
|
||||
P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
|
||||
P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
|
||||
P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
|
||||
P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
|
||||
P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
|
||||
P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
|
||||
P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
|
||||
P(0x0147c), P(0x04030), P(0x0403c), P(0x04024), P(0x04060),
|
||||
P(0x04064), P(0x07010), P(0x07034), P(0x07038), P(0x08004),
|
||||
P(0x08008), P(0x0800c), P(0x08018), P(0x08020), P(0x08038),
|
||||
P(0x0803c), P(0x08048), P(0x08054), P(0x08058), P(0x0805c),
|
||||
P(0x08060), P(0x08064), P(0x08070), P(0x080c0), P(0x080c4),
|
||||
P(0x080c8), P(0x080cc), P(0x080d0), P(0x080d4), P(0x080d8),
|
||||
P(0x080e0), P(0x080e4), P(0x080e8), P(0x080ec), P(0x080f0),
|
||||
P(0x080f4), P(0x080f8), P(0x080fc), P(0x08100), P(0x08104),
|
||||
P(0x08108), P(0x0810c), P(0x08110), P(0x08118), P(0x0811c),
|
||||
P(0x08124), P(0x08128), P(0x0812c), P(0x08130), P(0x08134),
|
||||
P(0x08138), P(0x0813c), P(0x08144), P(0x08168), P(0x0816c),
|
||||
P(0x08170), P(0x08174), P(0x08178), P(0x0817c), P(0x081c0),
|
||||
P(0x081ec), P(0x081f0), P(0x081f4), P(0x081f8), P(0x081fc),
|
||||
P(0x08200), P(0x08204), P(0x08208), P(0x0820c), P(0x08210),
|
||||
P(0x08214), P(0x08218), P(0x0821c), P(0x08220), P(0x08224),
|
||||
P(0x08228), P(0x0822c), P(0x08230), P(0x08234), P(0x08238),
|
||||
P(0x0823c), P(0x08240), P(0x08244), P(0x08248), P(0x0824c),
|
||||
P(0x08250), P(0x08254), P(0x08258), P(0x0825c), P(0x08260),
|
||||
P(0x08264), P(0x08270), P(0x08274), P(0x08278), P(0x0827c),
|
||||
P(0x08284), P(0x08288), P(0x0828c), P(0x08294), P(0x08298),
|
||||
P(0x0829c), P(0x08300), P(0x08314), P(0x08328), P(0x0832c),
|
||||
P(0x08330), P(0x08334), P(0x08338), P(0x0833c), P(0x08340),
|
||||
P(0x08344), P(0x09808), P(0x0980c), P(0x09810), P(0x09814),
|
||||
P(0x0981c), P(0x0982c), P(0x09830), P(0x0983c), P(0x0984c),
|
||||
P(0x0a84c), P(0x09854), P(0x09900), P(0x09904), P(0x09908),
|
||||
P(0x0990c), P(0x09910), P(0x0991c), P(0x09920), P(0x0a920),
|
||||
P(0x09928), P(0x0992c), P(0x09934), P(0x09938), P(0x0993c),
|
||||
P(0x09948), P(0x0994c), P(0x09954), P(0x09958), P(0x09940),
|
||||
P(0x0c95c), P(0x09970), P(0x09974), P(0x09978), P(0x0997c),
|
||||
P(0x09980), P(0x09984), P(0x09988), P(0x0998c), P(0x09990),
|
||||
P(0x09994), P(0x09998), P(0x0999c), P(0x099a0), P(0x099a4),
|
||||
P(0x099a8), P(0x099ac), P(0x099b0), P(0x099b4), P(0x099c4),
|
||||
P(0x099c8), P(0x099cc), P(0x099d0), P(0x099d4), P(0x099d8),
|
||||
P(0x099dc), P(0x099e0), P(0x099e4), P(0x099e8), P(0x099ec),
|
||||
P(0x099f0), P(0x099fc), P(0x0a208), P(0x0a210), P(0x0a214),
|
||||
P(0x0a218), P(0x0a220), P(0x0a224), P(0x0a228), P(0x0a22c),
|
||||
P(0x0a234), P(0x0a238), P(0x0a240), P(0x0a244), P(0x0a248),
|
||||
P(0x0a24c), P(0x0a254), P(0x0a258), P(0x0a25c), P(0x0a260),
|
||||
P(0x0a268), P(0x0a26c), P(0x0b26c), P(0x0d270), P(0x0a278),
|
||||
P(0x0d35c), P(0x0d360), P(0x0d364), P(0x0d368), P(0x0d36c),
|
||||
P(0x0d370), P(0x0d374), P(0x0d378), P(0x0d37c), P(0x0d380),
|
||||
P(0x0d384), P(0x0a38c), P(0x0a390), P(0x0a394), P(0x0a398),
|
||||
P(0x0a39c), P(0x0a3a0), P(0x0a3a4), P(0x0a3a8), P(0x0a3ac),
|
||||
P(0x0a3b0), P(0x0a3b4), P(0x0a3b8), P(0x0a3bc), P(0x0a3c0),
|
||||
P(0x0a3c4), P(0x0a3c8), P(0x0a3cc), P(0x0a3d0), P(0x0a3d4),
|
||||
P(0x0a3dc), P(0x0a3e0), P(0x0a3e4), P(0x0a3e8), P(0x07800),
|
||||
P(0x07804), P(0x07808), P(0x0780c), P(0x07810), P(0x07818),
|
||||
P(0x07824), P(0x07828), P(0x0782c), P(0x07830), P(0x07834),
|
||||
P(0x0783c), P(0x07848), P(0x0784c), P(0x07850), P(0x07854),
|
||||
P(0x07858), P(0x07860), P(0x07864), P(0x07868), P(0x0786c),
|
||||
P(0x07870), P(0x07874), P(0x07878), P(0x0787c), P(0x07880),
|
||||
P(0x07884), P(0x07888), P(0x0788c), P(0x07890), P(0x07898)
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_cm_vals[] = {
|
||||
0x00000000, 0x00020015, 0x00000005, 0x00000000, 0x00000008,
|
||||
0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
|
||||
0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
|
||||
0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000002, 0x00000002, 0x0000001f, 0x00000000,
|
||||
0x00000000, 0x00000033, 0x00000002, 0x000004c2, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000700, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x40000000, 0x00000000, 0x00000000, 0x000fc78f,
|
||||
0x0000000f, 0x00000000, 0x00000000, 0x2a80001a, 0x05dc01e0,
|
||||
0x1f402710, 0x01f40000, 0x00001e00, 0x00000000, 0x00400000,
|
||||
0xffffffff, 0x0000ffff, 0x003f3f3f, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00020000, 0x00020000, 0x00000001,
|
||||
0x00000052, 0x00000000, 0x00000168, 0x000100aa, 0x00003210,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000,
|
||||
0x32143320, 0xfaa4fa50, 0x00000100, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00100000, 0x0010f400, 0x00000100, 0x0001e800,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x400000ff, 0x00080922,
|
||||
0x88a00010, 0x00000000, 0x40000000, 0x003e4180, 0x00000000,
|
||||
0x0000002c, 0x0000002c, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x00000007,
|
||||
0x00000302, 0x00000e00, 0x00ff0000, 0x00000000, 0x000107ff,
|
||||
0x00481043, 0x00000000, 0xafa68e30, 0xfd14e000, 0x9c0a9f6b,
|
||||
0x00000000, 0x0000a000, 0x00000000, 0x00200400, 0x0040233c,
|
||||
0x0040233c, 0x00000044, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x01002310, 0x10000fff, 0x04900000, 0x04900000,
|
||||
0x00000001, 0x00000004, 0x1e1f2022, 0x0a0b0c0d, 0x00000000,
|
||||
0x9280c00a, 0x00020028, 0x5f3ca3de, 0x2108ecff, 0x14750604,
|
||||
0x004b6a8e, 0x190fb514, 0x00000000, 0x00000001, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
|
||||
0x201fff00, 0x006f0000, 0x03051000, 0x00000820, 0x06336f77,
|
||||
0x6af6532f, 0x08f186c8, 0x00046384, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0xaaaaaaaa, 0x3c466478, 0x0cc80caa,
|
||||
0x00000000, 0x00001042, 0x803e4788, 0x4080a333, 0x40206c10,
|
||||
0x009c4060, 0x01834061, 0x00000400, 0x000003b5, 0x233f7180,
|
||||
0x20202020, 0x20202020, 0x38490a20, 0x00007bb6, 0x0fff3ffc,
|
||||
0x00000000, 0x00000000, 0x0cdbd380, 0x0f0f0f01, 0xdfa91f01,
|
||||
0x00000000, 0x0e79e5c6, 0x0e79e5c6, 0x00820820, 0x1ce739ce,
|
||||
0x07ffffef, 0x0fffffe7, 0x17ffffe5, 0x1fffffe4, 0x37ffffe3,
|
||||
0x3fffffe3, 0x57ffffe3, 0x5fffffe2, 0x7fffffe2, 0x7f3c7bba,
|
||||
0xf3307ff0, 0x20202020, 0x20202020, 0x1ce739ce, 0x000001ce,
|
||||
0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000246, 0x20202020, 0x20202020, 0x20202020,
|
||||
0x1ce739ce, 0x000001ce, 0x00000000, 0x18c43433, 0x00040000,
|
||||
0xdb005012, 0x04924914, 0x21084210, 0x6d801300, 0x07e41000,
|
||||
0x00040000, 0xdb005012, 0x04924914, 0x21084210, 0x6d801300,
|
||||
0x07e40000, 0x00100000, 0x773f0567, 0x54214514, 0x12035828,
|
||||
0x9259269a, 0x52802000, 0x0a8e370e, 0xc0102850, 0x812d4000,
|
||||
0x807ec400, 0x001b6db0, 0x00376b63, 0x06db6db6, 0x006d8000,
|
||||
0xffeffffe, 0xffeffffe, 0x00010000, 0x02060aeb, 0x2a850160
|
||||
};
|
||||
|
||||
static const uint16_t ar9280_2_0_fast_clock_regs[] = {
|
||||
P(0x01030), P(0x01070), P(0x010b0), P(0x08014), P(0x0801c),
|
||||
P(0x08318), P(0x09820), P(0x09824), P(0x09828), P(0x09834),
|
||||
P(0x09844), P(0x09914), P(0x09918)
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_fast_clock_vals_5g20[] = {
|
||||
0x00000268, 0x0000018c, 0x00000fd0, 0x044c044c, 0x148ec02b,
|
||||
0x000044c0, 0x02020200, 0x01000f0f, 0x0b020001, 0x00000f0f,
|
||||
0x03721821, 0x00000898, 0x0000000b
|
||||
};
|
||||
|
||||
#ifndef IEEE80211_NO_HT
|
||||
static const uint32_t ar9280_2_0_fast_clock_vals_5g40[] = {
|
||||
0x000004d0, 0x00000318, 0x00001fa0, 0x08980898, 0x148ec057,
|
||||
0x00008980, 0x02020200, 0x01000f0f, 0x0b020001, 0x00000f0f,
|
||||
0x03721821, 0x00001130, 0x00000016
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct athn_ini ar9280_2_0_ini = {
|
||||
__arraycount(ar9280_2_0_regs),
|
||||
ar9280_2_0_regs,
|
||||
ar9280_2_0_vals_5g20,
|
||||
#ifndef IEEE80211_NO_HT
|
||||
ar9280_2_0_vals_5g40,
|
||||
ar9280_2_0_vals_2g40,
|
||||
#endif
|
||||
ar9280_2_0_vals_2g20,
|
||||
__arraycount(ar9280_2_0_cm_regs),
|
||||
ar9280_2_0_cm_regs,
|
||||
ar9280_2_0_cm_vals,
|
||||
__arraycount(ar9280_2_0_fast_clock_regs),
|
||||
ar9280_2_0_fast_clock_regs,
|
||||
ar9280_2_0_fast_clock_vals_5g20,
|
||||
#ifndef IEEE80211_NO_HT
|
||||
ar9280_2_0_fast_clock_vals_5g40
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* AR9280 2.0 Tx gains.
|
||||
*/
|
||||
static const uint16_t ar9280_2_0_tx_gain_regs[] = {
|
||||
P(0x0a274), P(0x0a27c), P(0x0a300), P(0x0a304), P(0x0a308),
|
||||
P(0x0a30c), P(0x0a310), P(0x0a314), P(0x0a318), P(0x0a31c),
|
||||
P(0x0a320), P(0x0a324), P(0x0a328), P(0x0a32c), P(0x0a330),
|
||||
P(0x0a334), P(0x0a338), P(0x0a33c), P(0x0a340), P(0x0a344),
|
||||
P(0x0a348), P(0x0a34c), P(0x0a350), P(0x0a354), P(0x0a3ec),
|
||||
P(0x07814), P(0x07838), P(0x0781c), P(0x07840), P(0x07820),
|
||||
P(0x07844)
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_tx_gain_vals_5g[] = {
|
||||
0x0a19c652, 0x050701ce, 0x00000000, 0x00003002, 0x00006004,
|
||||
0x0000a006, 0x0000e012, 0x00011014, 0x0001504a, 0x0001904c,
|
||||
0x0001c04e, 0x00020092, 0x0002410a, 0x0002710c, 0x0002b18b,
|
||||
0x0002e1cc, 0x000321ec, 0x000321ec, 0x000321ec, 0x000321ec,
|
||||
0x000321ec, 0x000321ec, 0x000321ec, 0x000321ec, 0x00f70081,
|
||||
0x0019beff, 0x0019beff, 0x00392000, 0x00392000, 0x92592480,
|
||||
0x92592480
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_tx_gain_vals_2g[] = {
|
||||
0x0a1aa652, 0x050701ce, 0x00000000, 0x00003002, 0x00008009,
|
||||
0x0000b00b, 0x0000e012, 0x00012048, 0x0001604a, 0x0001a211,
|
||||
0x0001e213, 0x0002121b, 0x00024412, 0x00028414, 0x0002b44a,
|
||||
0x00030649, 0x0003364b, 0x00038a49, 0x0003be48, 0x0003ee4a,
|
||||
0x00042e88, 0x00046e8a, 0x00049ec9, 0x0004bf42, 0x00f70081,
|
||||
0x0019beff, 0x0019beff, 0x00392000, 0x00392000, 0x92592480,
|
||||
0x92592480
|
||||
};
|
||||
|
||||
static const struct athn_gain ar9280_2_0_tx_gain = {
|
||||
__arraycount(ar9280_2_0_tx_gain_regs),
|
||||
ar9280_2_0_tx_gain_regs,
|
||||
ar9280_2_0_tx_gain_vals_5g,
|
||||
ar9280_2_0_tx_gain_vals_2g
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_tx_gain_high_power_vals_5g[] = {
|
||||
0x0a19e652, 0x050739ce, 0x00000000, 0x00003002, 0x00006004,
|
||||
0x0000a006, 0x0000e012, 0x00011014, 0x0001504a, 0x0001904c,
|
||||
0x0001c04e, 0x00021092, 0x0002510a, 0x0002910c, 0x0002c18b,
|
||||
0x0002f1cc, 0x000321eb, 0x000341ec, 0x000341ec, 0x000341ec,
|
||||
0x000341ec, 0x000341ec, 0x000341ec, 0x000341ec, 0x00f70081,
|
||||
0x00198eff, 0x00198eff, 0x00172000, 0x00172000, 0xf258a480,
|
||||
0xf258a480
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_tx_gain_high_power_vals_2g[] = {
|
||||
0x0a1aa652, 0x050739ce, 0x00000000, 0x00004002, 0x00007008,
|
||||
0x0000c010, 0x00010012, 0x00013014, 0x0001820a, 0x0001b211,
|
||||
0x0001e213, 0x00022411, 0x00025413, 0x00029811, 0x0002c813,
|
||||
0x00030a14, 0x00035a50, 0x00039c4c, 0x0003de8a, 0x00042e92,
|
||||
0x00046ed2, 0x0004bed5, 0x0004ff54, 0x00055fd5, 0x00f70081,
|
||||
0x00198eff, 0x00198eff, 0x00172000, 0x00172000, 0xf258a480,
|
||||
0xf258a480
|
||||
};
|
||||
|
||||
static const struct athn_gain ar9280_2_0_tx_gain_high_power = {
|
||||
__arraycount(ar9280_2_0_tx_gain_regs),
|
||||
ar9280_2_0_tx_gain_regs,
|
||||
ar9280_2_0_tx_gain_high_power_vals_5g,
|
||||
ar9280_2_0_tx_gain_high_power_vals_2g
|
||||
};
|
||||
|
||||
/*
|
||||
* AR9280 2.0 Rx gains.
|
||||
*/
|
||||
static const uint16_t ar9280_2_0_rx_gain_regs[] = {
|
||||
P(0x09a00), P(0x09a04), P(0x09a08), P(0x09a0c), P(0x09a10),
|
||||
P(0x09a14), P(0x09a18), P(0x09a1c), P(0x09a20), P(0x09a24),
|
||||
P(0x09a28), P(0x09a2c), P(0x09a30), P(0x09a34), P(0x09a38),
|
||||
P(0x09a3c), P(0x09a40), P(0x09a44), P(0x09a48), P(0x09a4c),
|
||||
P(0x09a50), P(0x09a54), P(0x09a58), P(0x09a5c), P(0x09a60),
|
||||
P(0x09a64), P(0x09a68), P(0x09a6c), P(0x09a70), P(0x09a74),
|
||||
P(0x09a78), P(0x09a7c), P(0x09a80), P(0x09a84), P(0x09a88),
|
||||
P(0x09a8c), P(0x09a90), P(0x09a94), P(0x09a98), P(0x09a9c),
|
||||
P(0x09aa0), P(0x09aa4), P(0x09aa8), P(0x09aac), P(0x09ab0),
|
||||
P(0x09ab4), P(0x09ab8), P(0x09abc), P(0x09ac0), P(0x09ac4),
|
||||
P(0x09ac8), P(0x09acc), P(0x09ad0), P(0x09ad4), P(0x09ad8),
|
||||
P(0x09adc), P(0x09ae0), P(0x09ae4), P(0x09ae8), P(0x09aec),
|
||||
P(0x09af0), P(0x09af4), P(0x09af8), P(0x09afc), P(0x09b00),
|
||||
P(0x09b04), P(0x09b08), P(0x09b0c), P(0x09b10), P(0x09b14),
|
||||
P(0x09b18), P(0x09b1c), P(0x09b20), P(0x09b24), P(0x09b28),
|
||||
P(0x09b2c), P(0x09b30), P(0x09b34), P(0x09b38), P(0x09b3c),
|
||||
P(0x09b40), P(0x09b44), P(0x09b48), P(0x09b4c), P(0x09b50),
|
||||
P(0x09b54), P(0x09b58), P(0x09b5c), P(0x09b60), P(0x09b64),
|
||||
P(0x09b68), P(0x09b6c), P(0x09b70), P(0x09b74), P(0x09b78),
|
||||
P(0x09b7c), P(0x09b80), P(0x09b84), P(0x09b88), P(0x09b8c),
|
||||
P(0x09b90), P(0x09b94), P(0x09b98), P(0x09b9c), P(0x09ba0),
|
||||
P(0x09ba4), P(0x09ba8), P(0x09bac), P(0x09bb0), P(0x09bb4),
|
||||
P(0x09bb8), P(0x09bbc), P(0x09bc0), P(0x09bc4), P(0x09bc8),
|
||||
P(0x09bcc), P(0x09bd0), P(0x09bd4), P(0x09bd8), P(0x09bdc),
|
||||
P(0x09be0), P(0x09be4), P(0x09be8), P(0x09bec), P(0x09bf0),
|
||||
P(0x09bf4), P(0x09bf8), P(0x09bfc), P(0x09848), P(0x0a848)
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_rx_gain_vals_5g[] = {
|
||||
0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
|
||||
0x00008200, 0x00008204, 0x00008208, 0x0000820c, 0x00008210,
|
||||
0x00008214, 0x00008280, 0x00008284, 0x00008288, 0x0000828c,
|
||||
0x00008290, 0x00008300, 0x00008304, 0x00008308, 0x0000830c,
|
||||
0x00008310, 0x00008314, 0x00008380, 0x00008384, 0x00008388,
|
||||
0x0000838c, 0x00008390, 0x00008394, 0x0000a380, 0x0000a384,
|
||||
0x0000a388, 0x0000a38c, 0x0000a390, 0x0000a394, 0x0000a780,
|
||||
0x0000a784, 0x0000a788, 0x0000a78c, 0x0000a790, 0x0000a794,
|
||||
0x0000ab84, 0x0000ab88, 0x0000ab8c, 0x0000ab90, 0x0000ab94,
|
||||
0x0000af80, 0x0000af84, 0x0000af88, 0x0000af8c, 0x0000af90,
|
||||
0x0000af94, 0x0000b380, 0x0000b384, 0x0000b388, 0x0000b38c,
|
||||
0x0000b390, 0x0000b394, 0x0000b398, 0x0000b780, 0x0000b784,
|
||||
0x0000b788, 0x0000b78c, 0x0000b790, 0x0000b794, 0x0000b798,
|
||||
0x0000d784, 0x0000d788, 0x0000d78c, 0x0000d790, 0x0000f780,
|
||||
0x0000f784, 0x0000f788, 0x0000f78c, 0x0000f790, 0x0000f794,
|
||||
0x0000f7a4, 0x0000f7a8, 0x0000f7ac, 0x0000f7b0, 0x0000f7b4,
|
||||
0x0000f7a1, 0x0000f7a5, 0x0000f7a9, 0x0000f7ad, 0x0000f7b1,
|
||||
0x0000f7b5, 0x0000f7c5, 0x0000f7c9, 0x0000f7cd, 0x0000f7d1,
|
||||
0x0000f7d5, 0x0000f7c2, 0x0000f7c6, 0x0000f7ca, 0x0000f7ce,
|
||||
0x0000f7d2, 0x0000f7d6, 0x0000f7c3, 0x0000f7c7, 0x0000f7cb,
|
||||
0x0000f7d3, 0x0000f7d7, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x00001066, 0x00001066
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_rx_gain_vals_2g[] = {
|
||||
0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000,
|
||||
0x00008000, 0x00008004, 0x00008008, 0x0000800c, 0x00008080,
|
||||
0x00008084, 0x00008088, 0x0000808c, 0x00008100, 0x00008104,
|
||||
0x00008108, 0x0000810c, 0x00008110, 0x00008114, 0x00008180,
|
||||
0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
|
||||
0x000081a0, 0x0000820c, 0x000081a8, 0x00008284, 0x00008288,
|
||||
0x00008224, 0x00008290, 0x00008300, 0x00008304, 0x00008308,
|
||||
0x0000830c, 0x00008380, 0x00008384, 0x00008700, 0x00008704,
|
||||
0x00008708, 0x0000870c, 0x00008780, 0x00008784, 0x00008b00,
|
||||
0x00008b04, 0x00008b08, 0x00008b0c, 0x00008b80, 0x00008b84,
|
||||
0x00008b88, 0x00008b8c, 0x00008b90, 0x00008f80, 0x00008f84,
|
||||
0x00008f88, 0x00008f8c, 0x00008f90, 0x0000930c, 0x00009310,
|
||||
0x00009384, 0x00009388, 0x00009324, 0x00009704, 0x000096a4,
|
||||
0x000096a8, 0x00009710, 0x00009714, 0x00009720, 0x00009724,
|
||||
0x00009728, 0x0000972c, 0x000097a0, 0x000097a4, 0x000097a8,
|
||||
0x000097b0, 0x000097b4, 0x000097b8, 0x000097a5, 0x000097a9,
|
||||
0x000097ad, 0x000097b1, 0x000097b5, 0x000097b9, 0x000097c5,
|
||||
0x000097c9, 0x000097d1, 0x000097d5, 0x000097d9, 0x000097c6,
|
||||
0x000097ca, 0x000097ce, 0x000097d2, 0x000097d6, 0x000097c3,
|
||||
0x000097c7, 0x000097cb, 0x000097cf, 0x000097d7, 0x000097db,
|
||||
0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
|
||||
0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
|
||||
0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
|
||||
0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
|
||||
0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
|
||||
0x000097db, 0x000097db, 0x000097db, 0x00001063, 0x00001063
|
||||
};
|
||||
|
||||
static const struct athn_gain ar9280_2_0_rx_gain = {
|
||||
__arraycount(ar9280_2_0_rx_gain_regs),
|
||||
ar9280_2_0_rx_gain_regs,
|
||||
ar9280_2_0_rx_gain_vals_5g,
|
||||
ar9280_2_0_rx_gain_vals_2g
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_rx_gain_13db_backoff_vals_5g[] = {
|
||||
0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
|
||||
0x00008200, 0x00008204, 0x00008208, 0x0000820c, 0x00008210,
|
||||
0x00008214, 0x00008280, 0x00008284, 0x00008288, 0x0000828c,
|
||||
0x00008290, 0x00008300, 0x00008304, 0x00008308, 0x0000830c,
|
||||
0x00008310, 0x00008314, 0x00008380, 0x00008384, 0x00008388,
|
||||
0x0000838c, 0x00008390, 0x00008394, 0x0000a380, 0x0000a384,
|
||||
0x0000a388, 0x0000a38c, 0x0000a390, 0x0000a394, 0x0000a780,
|
||||
0x0000a784, 0x0000a788, 0x0000a78c, 0x0000a790, 0x0000a794,
|
||||
0x0000ab84, 0x0000ab88, 0x0000ab8c, 0x0000ab90, 0x0000ab94,
|
||||
0x0000af80, 0x0000af84, 0x0000af88, 0x0000af8c, 0x0000af90,
|
||||
0x0000af94, 0x0000b380, 0x0000b384, 0x0000b388, 0x0000b38c,
|
||||
0x0000b390, 0x0000b394, 0x0000b398, 0x0000b780, 0x0000b784,
|
||||
0x0000b788, 0x0000b78c, 0x0000b790, 0x0000b794, 0x0000b798,
|
||||
0x0000d784, 0x0000d788, 0x0000d78c, 0x0000d790, 0x0000f780,
|
||||
0x0000f784, 0x0000f788, 0x0000f78c, 0x0000f790, 0x0000f794,
|
||||
0x0000f7a4, 0x0000f7a8, 0x0000f7ac, 0x0000f7b0, 0x0000f7b4,
|
||||
0x0000f7a1, 0x0000f7a5, 0x0000f7a9, 0x0000f7ad, 0x0000f7b1,
|
||||
0x0000f7b5, 0x0000f7c5, 0x0000f7c9, 0x0000f7cd, 0x0000f7d1,
|
||||
0x0000f7d5, 0x0000f7c2, 0x0000f7c6, 0x0000f7ca, 0x0000f7ce,
|
||||
0x0000f7d2, 0x0000f7d6, 0x0000f7c3, 0x0000f7c7, 0x0000f7cb,
|
||||
0x0000f7d3, 0x0000f7d7, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x00001066, 0x00001066
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_rx_gain_13db_backoff_vals_2g[] = {
|
||||
0x00000290, 0x00000300, 0x00000304, 0x00000308, 0x0000030c,
|
||||
0x00008000, 0x00008004, 0x00008008, 0x0000800c, 0x00008080,
|
||||
0x00008084, 0x00008088, 0x0000808c, 0x00008100, 0x00008104,
|
||||
0x00008108, 0x0000810c, 0x00008110, 0x00008114, 0x00008180,
|
||||
0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
|
||||
0x000081a0, 0x0000820c, 0x000081a8, 0x00008284, 0x00008288,
|
||||
0x00008224, 0x00008290, 0x00008300, 0x00008304, 0x00008308,
|
||||
0x0000830c, 0x00008380, 0x00008384, 0x00008700, 0x00008704,
|
||||
0x00008708, 0x0000870c, 0x00008780, 0x00008784, 0x00008b00,
|
||||
0x00008b04, 0x00008b08, 0x00008b0c, 0x00008b80, 0x00008b84,
|
||||
0x00008b88, 0x00008b8c, 0x00008b90, 0x00008f80, 0x00008f84,
|
||||
0x00008f88, 0x00008f8c, 0x00008f90, 0x00009310, 0x00009314,
|
||||
0x00009320, 0x00009324, 0x00009328, 0x0000932c, 0x00009330,
|
||||
0x00009334, 0x00009321, 0x00009325, 0x00009329, 0x0000932d,
|
||||
0x00009331, 0x00009335, 0x00009322, 0x00009326, 0x0000932a,
|
||||
0x0000932e, 0x00009332, 0x00009336, 0x00009323, 0x00009327,
|
||||
0x0000932b, 0x0000932f, 0x00009333, 0x00009337, 0x00009343,
|
||||
0x00009347, 0x0000934b, 0x0000934f, 0x00009353, 0x00009357,
|
||||
0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
|
||||
0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
|
||||
0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
|
||||
0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
|
||||
0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
|
||||
0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
|
||||
0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
|
||||
0x0000935b, 0x0000935b, 0x0000935b, 0x0000105a, 0x0000105a
|
||||
};
|
||||
|
||||
static const struct athn_gain ar9280_2_0_rx_gain_13db_backoff = {
|
||||
__arraycount(ar9280_2_0_rx_gain_regs),
|
||||
ar9280_2_0_rx_gain_regs,
|
||||
ar9280_2_0_rx_gain_13db_backoff_vals_5g,
|
||||
ar9280_2_0_rx_gain_13db_backoff_vals_2g
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_rx_gain_23db_backoff_vals_5g[] = {
|
||||
0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
|
||||
0x00008200, 0x00008204, 0x00008208, 0x0000820c, 0x00008210,
|
||||
0x00008214, 0x00008280, 0x00008284, 0x00008288, 0x0000828c,
|
||||
0x00008290, 0x00008300, 0x00008304, 0x00008308, 0x0000830c,
|
||||
0x00008310, 0x00008314, 0x00008380, 0x00008384, 0x00008388,
|
||||
0x0000838c, 0x00008390, 0x00008394, 0x0000a380, 0x0000a384,
|
||||
0x0000a388, 0x0000a38c, 0x0000a390, 0x0000a394, 0x0000a780,
|
||||
0x0000a784, 0x0000a788, 0x0000a78c, 0x0000a790, 0x0000a794,
|
||||
0x0000ab84, 0x0000ab88, 0x0000ab8c, 0x0000ab90, 0x0000ab94,
|
||||
0x0000af80, 0x0000af84, 0x0000af88, 0x0000af8c, 0x0000af90,
|
||||
0x0000af94, 0x0000b380, 0x0000b384, 0x0000b388, 0x0000b38c,
|
||||
0x0000b390, 0x0000b394, 0x0000b398, 0x0000b780, 0x0000b784,
|
||||
0x0000b788, 0x0000b78c, 0x0000b790, 0x0000b794, 0x0000b798,
|
||||
0x0000d784, 0x0000d788, 0x0000d78c, 0x0000d790, 0x0000f780,
|
||||
0x0000f784, 0x0000f788, 0x0000f78c, 0x0000f790, 0x0000f794,
|
||||
0x0000f7a4, 0x0000f7a8, 0x0000f7ac, 0x0000f7b0, 0x0000f7b4,
|
||||
0x0000f7a1, 0x0000f7a5, 0x0000f7a9, 0x0000f7ad, 0x0000f7b1,
|
||||
0x0000f7b5, 0x0000f7c5, 0x0000f7c9, 0x0000f7cd, 0x0000f7d1,
|
||||
0x0000f7d5, 0x0000f7c2, 0x0000f7c6, 0x0000f7ca, 0x0000f7ce,
|
||||
0x0000f7d2, 0x0000f7d6, 0x0000f7c3, 0x0000f7c7, 0x0000f7cb,
|
||||
0x0000f7d3, 0x0000f7d7, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
|
||||
0x0000f7db, 0x0000f7db, 0x0000f7db, 0x00001066, 0x00001066
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_rx_gain_23db_backoff_vals_2g[] = {
|
||||
0x00000290, 0x00000300, 0x00000304, 0x00000308, 0x0000030c,
|
||||
0x00008000, 0x00008004, 0x00008008, 0x0000800c, 0x00008080,
|
||||
0x00008084, 0x00008088, 0x0000808c, 0x00008100, 0x00008104,
|
||||
0x00008108, 0x0000810c, 0x00008110, 0x00008114, 0x00008180,
|
||||
0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
|
||||
0x000081a0, 0x0000820c, 0x000081a8, 0x00008284, 0x00008288,
|
||||
0x00008224, 0x00008290, 0x00008300, 0x00008304, 0x00008308,
|
||||
0x0000830c, 0x00008380, 0x00008384, 0x00008700, 0x00008704,
|
||||
0x00008708, 0x0000870c, 0x00008780, 0x00008784, 0x00008b00,
|
||||
0x00008b04, 0x00008b08, 0x00008b0c, 0x00008b10, 0x00008b80,
|
||||
0x00008b84, 0x00008b88, 0x00008b8c, 0x00008b90, 0x00008b94,
|
||||
0x00008b98, 0x00008ba4, 0x00008ba8, 0x00008bac, 0x00008bb0,
|
||||
0x00008bb4, 0x00008ba1, 0x00008ba5, 0x00008ba9, 0x00008bad,
|
||||
0x00008bb1, 0x00008bb5, 0x00008ba2, 0x00008ba6, 0x00008baa,
|
||||
0x00008bae, 0x00008bb2, 0x00008bb6, 0x00008ba3, 0x00008ba7,
|
||||
0x00008bab, 0x00008baf, 0x00008bb3, 0x00008bb7, 0x00008bc3,
|
||||
0x00008bc7, 0x00008bcb, 0x00008bcf, 0x00008bd3, 0x00008bd7,
|
||||
0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb,
|
||||
0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb,
|
||||
0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb,
|
||||
0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb,
|
||||
0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb,
|
||||
0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb,
|
||||
0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb,
|
||||
0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00008bdb,
|
||||
0x00008bdb, 0x00008bdb, 0x00008bdb, 0x00001055, 0x00001055
|
||||
};
|
||||
|
||||
static const struct athn_gain ar9280_2_0_rx_gain_23db_backoff = {
|
||||
__arraycount(ar9280_2_0_rx_gain_regs),
|
||||
ar9280_2_0_rx_gain_regs,
|
||||
ar9280_2_0_rx_gain_23db_backoff_vals_5g,
|
||||
ar9280_2_0_rx_gain_23db_backoff_vals_2g
|
||||
};
|
||||
|
||||
/*
|
||||
* Serializer/Deserializer programming.
|
||||
*/
|
||||
|
||||
static const uint32_t ar9280_2_0_serdes_regs[] = {
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES,
|
||||
AR_PCIE_SERDES2,
|
||||
};
|
||||
|
||||
static const uint32_t ar9280_2_0_serdes_vals[] = {
|
||||
0x9248fd00,
|
||||
0x24924924,
|
||||
0xa8000019,
|
||||
0x13160820,
|
||||
0xe5980560,
|
||||
#ifdef ATHN_PCIE_CLKREQ
|
||||
0xc01dcffc,
|
||||
#else
|
||||
0xc01dcffd,
|
||||
#endif
|
||||
0x1aaabe41,
|
||||
0xbe105554,
|
||||
0x00043007,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const struct athn_serdes ar9280_2_0_serdes = {
|
||||
__arraycount(ar9280_2_0_serdes_vals),
|
||||
ar9280_2_0_serdes_regs,
|
||||
ar9280_2_0_serdes_vals
|
||||
};
|
||||
|
||||
#endif /* _ARN9280REG_H_ */
|
887
sys/dev/ic/arn9285.c
Normal file
887
sys/dev/ic/arn9285.c
Normal file
@ -0,0 +1,887 @@
|
||||
/* $NetBSD: arn9285.c,v 1.1 2013/03/30 02:53:01 christos Exp $ */
|
||||
/* $OpenBSD: ar9285.c,v 1.19 2012/06/10 21:23:36 kettenis Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2010 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2008-2010 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Driver for Atheros 802.11a/g/n chipsets.
|
||||
* Routines for AR9285 and AR9271 chipsets.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: arn9285.c,v 1.1 2013/03/30 02:53:01 christos Exp $");
|
||||
|
||||
#ifndef _MODULE
|
||||
#include "athn_usb.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/intr.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_amrr.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/ic/athnreg.h>
|
||||
#include <dev/ic/athnvar.h>
|
||||
#include <dev/ic/arn9285.h>
|
||||
|
||||
#include <dev/ic/arn5008reg.h>
|
||||
#include <dev/ic/arn9280reg.h>
|
||||
#include <dev/ic/arn9285reg.h>
|
||||
|
||||
#include <dev/ic/arn5008.h>
|
||||
#include <dev/ic/arn9280.h>
|
||||
#include <dev/ic/arn9285.h>
|
||||
|
||||
#define Static static
|
||||
|
||||
Static int ar9285_cl_cal(struct athn_softc *, struct ieee80211_channel *,
|
||||
struct ieee80211_channel *);
|
||||
Static void ar9285_get_pdadcs(struct athn_softc *,
|
||||
struct ieee80211_channel *, int, uint8_t, uint8_t *,
|
||||
uint8_t *);
|
||||
Static const struct ar_spur_chan *
|
||||
ar9285_get_spur_chans(struct athn_softc *, int);
|
||||
Static void ar9285_init_from_rom(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9285_set_power_calib(struct athn_softc *,
|
||||
struct ieee80211_channel *);
|
||||
Static void ar9285_set_txpower(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9285_setup(struct athn_softc *);
|
||||
Static void ar9285_swap_rom(struct athn_softc *);
|
||||
|
||||
PUBLIC int
|
||||
ar9285_attach(struct athn_softc *sc)
|
||||
{
|
||||
|
||||
sc->sc_eep_base = AR9285_EEP_START_LOC;
|
||||
sc->sc_eep_size = sizeof(struct ar9285_eeprom);
|
||||
sc->sc_def_nf = AR9285_PHY_CCA_MAX_GOOD_VALUE;
|
||||
sc->sc_ngpiopins = (sc->sc_flags & ATHN_FLAG_USB) ? 16 : 12;
|
||||
sc->sc_led_pin = (sc->sc_flags & ATHN_FLAG_USB) ? 15 : 1;
|
||||
sc->sc_workaround = AR9285_WA_DEFAULT;
|
||||
sc->sc_ops.setup = ar9285_setup;
|
||||
sc->sc_ops.swap_rom = ar9285_swap_rom;
|
||||
sc->sc_ops.init_from_rom = ar9285_init_from_rom;
|
||||
sc->sc_ops.set_txpower = ar9285_set_txpower;
|
||||
sc->sc_ops.set_synth = ar9280_set_synth;
|
||||
sc->sc_ops.spur_mitigate = ar9280_spur_mitigate;
|
||||
sc->sc_ops.get_spur_chans = ar9285_get_spur_chans;
|
||||
#if NATHN_USB > 0
|
||||
if (AR_SREV_9271(sc))
|
||||
sc->sc_ini = &ar9271_ini;
|
||||
else
|
||||
#endif
|
||||
sc->sc_ini = &ar9285_1_2_ini;
|
||||
sc->sc_serdes = &ar9280_2_0_serdes;
|
||||
|
||||
return ar5008_attach(sc);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9285_setup(struct athn_softc *sc)
|
||||
{
|
||||
const struct ar9285_eeprom *eep = sc->sc_eep;
|
||||
uint8_t type;
|
||||
|
||||
/* Select initialization values based on ROM. */
|
||||
type = eep->baseEepHeader.txGainType;
|
||||
DPRINTFN(DBG_TX, sc, "Tx gain type=0x%x\n", type);
|
||||
#if NATHN_USB > 0
|
||||
if (AR_SREV_9271(sc)) {
|
||||
if (type == AR_EEP_TXGAIN_HIGH_POWER)
|
||||
sc->sc_tx_gain = &ar9271_tx_gain_high_power;
|
||||
else
|
||||
sc->sc_tx_gain = &ar9271_tx_gain;
|
||||
}
|
||||
else
|
||||
#endif /* NATHN_USB */
|
||||
if ((AR_READ(sc, AR_AN_SYNTH9) & 0x7) == 0x1) { /* XE rev. */
|
||||
if (type == AR_EEP_TXGAIN_HIGH_POWER)
|
||||
sc->sc_tx_gain = &ar9285_2_0_tx_gain_high_power;
|
||||
else
|
||||
sc->sc_tx_gain = &ar9285_2_0_tx_gain;
|
||||
}
|
||||
else {
|
||||
if (type == AR_EEP_TXGAIN_HIGH_POWER)
|
||||
sc->sc_tx_gain = &ar9285_1_2_tx_gain_high_power;
|
||||
else
|
||||
sc->sc_tx_gain = &ar9285_1_2_tx_gain;
|
||||
}
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9285_swap_rom(struct athn_softc *sc)
|
||||
{
|
||||
struct ar9285_eeprom *eep = sc->sc_eep;
|
||||
int i;
|
||||
|
||||
eep->modalHeader.antCtrlCommon =
|
||||
bswap32(eep->modalHeader.antCtrlCommon);
|
||||
eep->modalHeader.antCtrlChain =
|
||||
bswap32(eep->modalHeader.antCtrlChain);
|
||||
|
||||
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
|
||||
eep->modalHeader.spurChans[i].spurChan =
|
||||
bswap16(eep->modalHeader.spurChans[i].spurChan);
|
||||
}
|
||||
}
|
||||
|
||||
Static const struct ar_spur_chan *
|
||||
ar9285_get_spur_chans(struct athn_softc *sc, int is2ghz)
|
||||
{
|
||||
const struct ar9285_eeprom *eep = sc->sc_eep;
|
||||
|
||||
KASSERT(is2ghz);
|
||||
return eep->modalHeader.spurChans;
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9285_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
const struct ar9285_eeprom *eep = sc->sc_eep;
|
||||
const struct ar9285_modal_eep_header *modal = &eep->modalHeader;
|
||||
uint32_t reg, offset = 0x1000;
|
||||
uint8_t ob[5], db1[5], db2[5];
|
||||
uint8_t txRxAtten;
|
||||
|
||||
AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon);
|
||||
AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0, modal->antCtrlChain);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0);
|
||||
reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, modal->iqCalI);
|
||||
reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, modal->iqCalQ);
|
||||
AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0, reg);
|
||||
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3) {
|
||||
reg = AR_READ(sc, AR_PHY_GAIN_2GHZ);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
|
||||
modal->bswMargin);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
|
||||
modal->bswAtten);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
|
||||
modal->xatten2Margin);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
|
||||
modal->xatten2Db);
|
||||
AR_WRITE(sc, AR_PHY_GAIN_2GHZ, reg);
|
||||
|
||||
/* Duplicate values of chain 0 for chain 1. */
|
||||
reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
|
||||
modal->bswMargin);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
|
||||
modal->bswAtten);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
|
||||
modal->xatten2Margin);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
|
||||
modal->xatten2Db);
|
||||
AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
|
||||
}
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3)
|
||||
txRxAtten = modal->txRxAtten;
|
||||
else /* Workaround for ROM versions < 14.3. */
|
||||
txRxAtten = 23;
|
||||
reg = AR_READ(sc, AR_PHY_RXGAIN);
|
||||
reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
|
||||
reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin);
|
||||
AR_WRITE(sc, AR_PHY_RXGAIN, reg);
|
||||
|
||||
/* Duplicate values of chain 0 for chain 1. */
|
||||
reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
|
||||
reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
|
||||
reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin);
|
||||
AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
|
||||
|
||||
if (modal->version >= 3) {
|
||||
/* Setup antenna diversity from ROM. */
|
||||
reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL);
|
||||
reg = RW(reg, AR9285_PHY_ANT_DIV_CTL_ALL, 0);
|
||||
reg = RW(reg, AR9285_PHY_ANT_DIV_CTL,
|
||||
(modal->ob_234 >> 12) & 0x1);
|
||||
reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_LNACONF,
|
||||
(modal->db1_234 >> 12) & 0x3);
|
||||
reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_LNACONF,
|
||||
(modal->db1_234 >> 14) & 0x3);
|
||||
reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_GAINTB,
|
||||
(modal->ob_234 >> 13) & 0x1);
|
||||
reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_GAINTB,
|
||||
(modal->ob_234 >> 14) & 0x1);
|
||||
AR_WRITE(sc, AR_PHY_MULTICHAIN_GAIN_CTL, reg);
|
||||
reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL); /* Flush. */
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_CCK_DETECT);
|
||||
if (modal->ob_234 & (1 << 15))
|
||||
reg |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
|
||||
else
|
||||
reg &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
|
||||
AR_WRITE(sc, AR_PHY_CCK_DETECT, reg);
|
||||
reg = AR_READ(sc, AR_PHY_CCK_DETECT); /* Flush. */
|
||||
}
|
||||
if (modal->version >= 2) {
|
||||
ob [0] = (modal->ob_01 >> 0) & 0xf;
|
||||
ob [1] = (modal->ob_01 >> 4) & 0xf;
|
||||
ob [2] = (modal->ob_234 >> 0) & 0xf;
|
||||
ob [3] = (modal->ob_234 >> 4) & 0xf;
|
||||
ob [4] = (modal->ob_234 >> 8) & 0xf;
|
||||
|
||||
db1[0] = (modal->db1_01 >> 0) & 0xf;
|
||||
db1[1] = (modal->db1_01 >> 4) & 0xf;
|
||||
db1[2] = (modal->db1_234 >> 0) & 0xf;
|
||||
db1[3] = (modal->db1_234 >> 4) & 0xf;
|
||||
db1[4] = (modal->db1_234 >> 8) & 0xf;
|
||||
|
||||
db2[0] = (modal->db2_01 >> 0) & 0xf;
|
||||
db2[1] = (modal->db2_01 >> 4) & 0xf;
|
||||
db2[2] = (modal->db2_234 >> 0) & 0xf;
|
||||
db2[3] = (modal->db2_234 >> 4) & 0xf;
|
||||
db2[4] = (modal->db2_234 >> 8) & 0xf;
|
||||
|
||||
}
|
||||
else if (modal->version == 1) {
|
||||
ob [0] = (modal->ob_01 >> 0) & 0xf;
|
||||
ob [1] = (modal->ob_01 >> 4) & 0xf;
|
||||
/* Field ob_234 does not exist, use ob_01. */
|
||||
ob [2] = ob [3] = ob [4] = ob [1];
|
||||
|
||||
db1[0] = (modal->db1_01 >> 0) & 0xf;
|
||||
db1[1] = (modal->db1_01 >> 4) & 0xf;
|
||||
/* Field db1_234 does not exist, use db1_01. */
|
||||
db1[2] = db1[3] = db1[4] = db1[1];
|
||||
|
||||
db2[0] = (modal->db2_01 >> 0) & 0xf;
|
||||
db2[1] = (modal->db2_01 >> 4) & 0xf;
|
||||
/* Field db2_234 does not exist, use db2_01. */
|
||||
db2[2] = db2[3] = db2[4] = db2[1];
|
||||
|
||||
}
|
||||
else {
|
||||
ob [0] = modal->ob_01;
|
||||
ob [1] = ob [2] = ob [3] = ob [4] = ob [0];
|
||||
|
||||
db1[0] = modal->db1_01;
|
||||
db1[1] = db1[2] = db1[3] = db1[4] = db1[0];
|
||||
|
||||
/* Field db2_01 does not exist, use db1_01. */
|
||||
db2[0] = modal->db1_01;
|
||||
db2[1] = db2[2] = db2[3] = db2[4] = db2[0];
|
||||
}
|
||||
#if NATHN_USB > 0
|
||||
if (AR_SREV_9271(sc)) {
|
||||
reg = AR_READ(sc, AR9285_AN_RF2G3);
|
||||
reg = RW(reg, AR9271_AN_RF2G3_OB_CCK, ob [0]);
|
||||
reg = RW(reg, AR9271_AN_RF2G3_OB_PSK, ob [1]);
|
||||
reg = RW(reg, AR9271_AN_RF2G3_OB_QAM, ob [2]);
|
||||
reg = RW(reg, AR9271_AN_RF2G3_DB1, db1[0]);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G3, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
reg = AR_READ(sc, AR9285_AN_RF2G4);
|
||||
reg = RW(reg, AR9271_AN_RF2G4_DB2, db2[0]);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G4, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
}
|
||||
else
|
||||
#endif /* ATHN_USB */
|
||||
{
|
||||
reg = AR_READ(sc, AR9285_AN_RF2G3);
|
||||
reg = RW(reg, AR9285_AN_RF2G3_OB_0, ob [0]);
|
||||
reg = RW(reg, AR9285_AN_RF2G3_OB_1, ob [1]);
|
||||
reg = RW(reg, AR9285_AN_RF2G3_OB_2, ob [2]);
|
||||
reg = RW(reg, AR9285_AN_RF2G3_OB_3, ob [3]);
|
||||
reg = RW(reg, AR9285_AN_RF2G3_OB_4, ob [4]);
|
||||
reg = RW(reg, AR9285_AN_RF2G3_DB1_0, db1[0]);
|
||||
reg = RW(reg, AR9285_AN_RF2G3_DB1_1, db1[1]);
|
||||
reg = RW(reg, AR9285_AN_RF2G3_DB1_2, db1[2]);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G3, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
reg = AR_READ(sc, AR9285_AN_RF2G4);
|
||||
reg = RW(reg, AR9285_AN_RF2G4_DB1_3, db1[3]);
|
||||
reg = RW(reg, AR9285_AN_RF2G4_DB1_4, db1[4]);
|
||||
reg = RW(reg, AR9285_AN_RF2G4_DB2_0, db2[0]);
|
||||
reg = RW(reg, AR9285_AN_RF2G4_DB2_1, db2[1]);
|
||||
reg = RW(reg, AR9285_AN_RF2G4_DB2_2, db2[2]);
|
||||
reg = RW(reg, AR9285_AN_RF2G4_DB2_3, db2[3]);
|
||||
reg = RW(reg, AR9285_AN_RF2G4_DB2_4, db2[4]);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G4, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
}
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_SETTLING);
|
||||
reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
|
||||
AR_WRITE(sc, AR_PHY_SETTLING, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
|
||||
reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
|
||||
AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
|
||||
|
||||
reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
|
||||
reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
|
||||
reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
|
||||
reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_RF_CTL3);
|
||||
reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_CCA(0));
|
||||
reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62);
|
||||
AR_WRITE(sc, AR_PHY_CCA(0), reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_EXT_CCA0);
|
||||
reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62);
|
||||
AR_WRITE(sc, AR_PHY_EXT_CCA0, reg);
|
||||
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2) {
|
||||
reg = AR_READ(sc, AR_PHY_RF_CTL2);
|
||||
reg = RW(reg, AR_PHY_TX_END_PA_ON,
|
||||
modal->txFrameToPaOn);
|
||||
reg = RW(reg, AR_PHY_TX_END_DATA_START,
|
||||
modal->txFrameToDataStart);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
|
||||
}
|
||||
#ifndef IEEE80211_NO_HT
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
|
||||
reg = AR_READ(sc, AR_PHY_SETTLING);
|
||||
reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
|
||||
AR_WRITE(sc, AR_PHY_SETTLING, reg);
|
||||
}
|
||||
#endif
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar9285_pa_calib(struct athn_softc *sc)
|
||||
{
|
||||
/* List of registers that need to be saved/restored. */
|
||||
static const uint16_t regs[] = {
|
||||
AR9285_AN_TOP3,
|
||||
AR9285_AN_RXTXBB1,
|
||||
AR9285_AN_RF2G1,
|
||||
AR9285_AN_RF2G2,
|
||||
AR9285_AN_TOP2,
|
||||
AR9285_AN_RF2G8,
|
||||
AR9285_AN_RF2G7
|
||||
};
|
||||
uint32_t svg[7], reg, ccomp_svg;
|
||||
size_t i;
|
||||
|
||||
/* No PA calibration needed for high power solutions. */
|
||||
if (AR_SREV_9285(sc) &&
|
||||
((struct ar9285_base_eep_header *)sc->sc_eep)->txGainType ==
|
||||
AR_EEP_TXGAIN_HIGH_POWER) /* XXX AR9287? */
|
||||
return;
|
||||
|
||||
/* Save registers. */
|
||||
for (i = 0; i < __arraycount(regs); i++)
|
||||
svg[i] = AR_READ(sc, regs[i]);
|
||||
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G6, 1);
|
||||
AR_SETBITS(sc, AR_PHY(2), 1 << 27);
|
||||
|
||||
AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
|
||||
AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
|
||||
AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
|
||||
AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
|
||||
/* Power down PA drivers. */
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
|
||||
|
||||
reg = AR_READ(sc, AR9285_AN_RF2G8);
|
||||
reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G8, reg);
|
||||
|
||||
reg = AR_READ(sc, AR9285_AN_RF2G7);
|
||||
reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G7, reg);
|
||||
|
||||
reg = AR_READ(sc, AR9285_AN_RF2G6);
|
||||
/* Save compensation capacitor value. */
|
||||
ccomp_svg = MS(reg, AR9285_AN_RF2G6_CCOMP);
|
||||
/* Program compensation capacitor for dynamic PA. */
|
||||
reg = RW(reg, AR9285_AN_RF2G6_CCOMP, 0xf);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G6, reg);
|
||||
|
||||
AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(30);
|
||||
|
||||
/* Clear offsets 6-1. */
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS_6_1);
|
||||
/* Clear offset 0. */
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
|
||||
/* Set offsets 6-1. */
|
||||
for (i = 6; i >= 1; i--) {
|
||||
AR_SETBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS(i));
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(1);
|
||||
if (AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9) {
|
||||
AR_SETBITS(sc, AR9285_AN_RF2G6,
|
||||
AR9285_AN_RF2G6_OFFS(i));
|
||||
}
|
||||
else {
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G6,
|
||||
AR9285_AN_RF2G6_OFFS(i));
|
||||
}
|
||||
}
|
||||
/* Set offset 0. */
|
||||
AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(1);
|
||||
if (AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9)
|
||||
AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
|
||||
else
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
|
||||
|
||||
AR_WRITE_BARRIER(sc);
|
||||
|
||||
AR_SETBITS(sc, AR9285_AN_RF2G6, 1);
|
||||
AR_CLRBITS(sc, AR_PHY(2), 1 << 27);
|
||||
|
||||
/* Restore registers. */
|
||||
for (i = 0; i < __arraycount(regs); i++)
|
||||
AR_WRITE(sc, regs[i], svg[i]);
|
||||
|
||||
/* Restore compensation capacitor value. */
|
||||
reg = AR_READ(sc, AR9285_AN_RF2G6);
|
||||
reg = RW(reg, AR9285_AN_RF2G6_CCOMP, ccomp_svg);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G6, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar9271_pa_calib(struct athn_softc *sc)
|
||||
{
|
||||
#if NATHN_USB > 0
|
||||
/* List of registers that need to be saved/restored. */
|
||||
static const uint16_t regs[] = {
|
||||
AR9285_AN_TOP3,
|
||||
AR9285_AN_RXTXBB1,
|
||||
AR9285_AN_RF2G1,
|
||||
AR9285_AN_RF2G2,
|
||||
AR9285_AN_TOP2,
|
||||
AR9285_AN_RF2G8,
|
||||
AR9285_AN_RF2G7
|
||||
};
|
||||
uint32_t svg[7], reg, rf2g3_svg;
|
||||
size_t i;
|
||||
|
||||
/* Save registers. */
|
||||
for (i = 0; i < __arraycount(regs); i++)
|
||||
svg[i] = AR_READ(sc, regs[i]);
|
||||
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G6, 1);
|
||||
AR_SETBITS(sc, AR_PHY(2), 1 << 27);
|
||||
|
||||
AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
|
||||
AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
|
||||
AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
|
||||
AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
|
||||
/* Power down PA drivers. */
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
|
||||
|
||||
reg = AR_READ(sc, AR9285_AN_RF2G8);
|
||||
reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G8, reg);
|
||||
|
||||
reg = AR_READ(sc, AR9285_AN_RF2G7);
|
||||
reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G7, reg);
|
||||
|
||||
/* Save compensation capacitor value. */
|
||||
reg = rf2g3_svg = AR_READ(sc, AR9285_AN_RF2G3);
|
||||
/* Program compensation capacitor for dynamic PA. */
|
||||
reg = RW(reg, AR9271_AN_RF2G3_CCOMP, 0xfff);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G3, reg);
|
||||
|
||||
AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(30);
|
||||
|
||||
/* Clear offsets 6-0. */
|
||||
AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS_6_0);
|
||||
/* Set offsets 6-1. */
|
||||
for (i = 6; i >= 1; i--) {
|
||||
reg = AR_READ(sc, AR9285_AN_RF2G6);
|
||||
reg |= AR9271_AN_RF2G6_OFFS(i);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G6, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(1);
|
||||
if (!(AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9))
|
||||
reg &= ~AR9271_AN_RF2G6_OFFS(i);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G6, reg);
|
||||
}
|
||||
AR_WRITE_BARRIER(sc);
|
||||
|
||||
AR_SETBITS(sc, AR9285_AN_RF2G6, 1);
|
||||
AR_CLRBITS(sc, AR_PHY(2), 1 << 27);
|
||||
|
||||
/* Restore registers. */
|
||||
for (i = 0; i < __arraycount(regs); i++)
|
||||
AR_WRITE(sc, regs[i], svg[i]);
|
||||
|
||||
/* Restore compensation capacitor value. */
|
||||
AR_WRITE(sc, AR9285_AN_RF2G3, rf2g3_svg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
#endif /* NATHN_USB */
|
||||
}
|
||||
|
||||
/*
|
||||
* Carrier Leakage Calibration.
|
||||
*/
|
||||
int
|
||||
ar9285_cl_cal(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
int ntries;
|
||||
|
||||
AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
|
||||
#ifndef IEEE80211_NO_HT
|
||||
if (0 && extc == NULL) { /* XXX IS_CHAN_HT20!! */
|
||||
AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
|
||||
AR_SETBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
|
||||
AR_CLRBITS(sc, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_FLTR_CAL);
|
||||
AR_CLRBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
|
||||
AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
|
||||
for (ntries = 0; ntries < 10000; ntries++) {
|
||||
if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) &
|
||||
AR_PHY_AGC_CONTROL_CAL))
|
||||
break;
|
||||
DELAY(10);
|
||||
}
|
||||
if (ntries == 10000)
|
||||
return ETIMEDOUT;
|
||||
AR_CLRBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
|
||||
AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
|
||||
AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
|
||||
}
|
||||
#endif
|
||||
AR_CLRBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
|
||||
AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
|
||||
AR_SETBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
|
||||
AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
|
||||
for (ntries = 0; ntries < 10000; ntries++) {
|
||||
if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) &
|
||||
AR_PHY_AGC_CONTROL_CAL))
|
||||
break;
|
||||
DELAY(10);
|
||||
}
|
||||
if (ntries == 10000)
|
||||
return ETIMEDOUT;
|
||||
AR_SETBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
|
||||
AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
|
||||
AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar9271_load_ani(struct athn_softc *sc)
|
||||
{
|
||||
|
||||
#if NATHN_USB > 0
|
||||
/* Write ANI registers. */
|
||||
AR_WRITE(sc, AR_PHY_DESIRED_SZ, 0x6d4000e2);
|
||||
AR_WRITE(sc, AR_PHY_AGC_CTL1, 0x3139605e);
|
||||
AR_WRITE(sc, AR_PHY_FIND_SIG, 0x7ec84d2e);
|
||||
AR_WRITE(sc, AR_PHY_SFCORR_LOW, 0x06903881);
|
||||
AR_WRITE(sc, AR_PHY_SFCORR, 0x5ac640d0);
|
||||
AR_WRITE(sc, AR_PHY_CCK_DETECT, 0x803e68c8);
|
||||
AR_WRITE(sc, AR_PHY_TIMING5, 0xd00a8007);
|
||||
AR_WRITE(sc, AR_PHY_SFCORR_EXT, 0x05eea6d4);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
#endif /* NATHN_USB */
|
||||
}
|
||||
|
||||
int
|
||||
ar9285_init_calib(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
uint32_t reg, mask, clcgain, rf2g5_svg;
|
||||
int i, maxgain, nclcs, thresh, error;
|
||||
|
||||
/* Do carrier leakage calibration. */
|
||||
if ((error = ar9285_cl_cal(sc, c, extc)) != 0)
|
||||
return error;
|
||||
|
||||
/* Workaround for high temperature is not applicable on AR9271. */
|
||||
if (AR_SREV_9271(sc))
|
||||
return 0;
|
||||
|
||||
mask = 0;
|
||||
nclcs = 0;
|
||||
reg = AR_READ(sc, AR_PHY_TX_PWRCTRL7);
|
||||
maxgain = MS(reg, AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
|
||||
for (i = 0; i <= maxgain; i++) {
|
||||
reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i));
|
||||
clcgain = MS(reg, AR_PHY_TX_GAIN_CLC);
|
||||
/* NB: clcgain <= 0xf. */
|
||||
if (!(mask & (1 << clcgain))) {
|
||||
mask |= 1 << clcgain;
|
||||
nclcs++;
|
||||
}
|
||||
}
|
||||
thresh = 0;
|
||||
for (i = 0; i < nclcs; i++) {
|
||||
reg = AR_READ(sc, AR_PHY_CLC_TBL(i));
|
||||
if (MS(reg, AR_PHY_CLC_I0) == 0)
|
||||
thresh++;
|
||||
if (MS(reg, AR_PHY_CLC_Q0) == 0)
|
||||
thresh++;
|
||||
}
|
||||
if (thresh <= AR9285_CL_CAL_REDO_THRESH)
|
||||
return 0; /* No need to redo. */
|
||||
|
||||
/* Threshold reached, redo carrier leakage calibration. */
|
||||
DPRINTFN(DBG_INIT, sc, "CLC threshold=%d\n", thresh);
|
||||
rf2g5_svg = reg = AR_READ(sc, AR9285_AN_RF2G5);
|
||||
if ((AR_READ(sc, AR_AN_SYNTH9) & 0x7) == 0x1) /* XE rev. */
|
||||
reg = RW(reg, AR9285_AN_RF2G5_IC50TX, 0x5);
|
||||
else
|
||||
reg = RW(reg, AR9285_AN_RF2G5_IC50TX, 0x4);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G5, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
error = ar9285_cl_cal(sc, c, extc);
|
||||
AR_WRITE(sc, AR9285_AN_RF2G5, rf2g5_svg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
return error;
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9285_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
int nxpdgains, uint8_t overlap, uint8_t *boundaries, uint8_t *pdadcs)
|
||||
{
|
||||
const struct ar9285_eeprom *eep = sc->sc_eep;
|
||||
const struct ar9285_cal_data_per_freq *pierdata;
|
||||
const uint8_t *pierfreq;
|
||||
struct athn_pier lopier, hipier;
|
||||
uint8_t fbin;
|
||||
int i, lo, hi, npiers;
|
||||
|
||||
pierfreq = eep->calFreqPier2G;
|
||||
pierdata = eep->calPierData2G;
|
||||
npiers = AR9285_NUM_2G_CAL_PIERS;
|
||||
|
||||
/* Find channel in ROM pier table. */
|
||||
fbin = athn_chan2fbin(c);
|
||||
athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
|
||||
|
||||
lopier.fbin = pierfreq[lo];
|
||||
hipier.fbin = pierfreq[hi];
|
||||
for (i = 0; i < nxpdgains; i++) {
|
||||
lopier.pwr[i] = pierdata[lo].pwrPdg[i];
|
||||
lopier.vpd[i] = pierdata[lo].vpdPdg[i];
|
||||
hipier.pwr[i] = pierdata[lo].pwrPdg[i];
|
||||
hipier.vpd[i] = pierdata[lo].vpdPdg[i];
|
||||
}
|
||||
ar5008_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains,
|
||||
AR9285_PD_GAIN_ICEPTS, overlap, boundaries, pdadcs);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9285_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
const struct ar9285_eeprom *eep = sc->sc_eep;
|
||||
uint8_t boundaries[AR_PD_GAINS_IN_MASK];
|
||||
uint8_t pdadcs[AR_NUM_PDADC_VALUES];
|
||||
uint8_t xpdgains[AR9285_NUM_PD_GAINS];
|
||||
uint8_t overlap;
|
||||
uint32_t reg;
|
||||
int i, nxpdgains;
|
||||
|
||||
if (sc->sc_eep_rev < AR_EEP_MINOR_VER_2) {
|
||||
overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),
|
||||
AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
|
||||
}
|
||||
else
|
||||
overlap = eep->modalHeader.pdGainOverlap;
|
||||
|
||||
nxpdgains = 0;
|
||||
memset(xpdgains, 0, sizeof(xpdgains));
|
||||
for (i = AR9285_PD_GAINS_IN_MASK - 1; i >= 0; i--) {
|
||||
if (nxpdgains >= AR9285_NUM_PD_GAINS)
|
||||
break;
|
||||
if (eep->modalHeader.xpdGain & (1 << i))
|
||||
xpdgains[nxpdgains++] = i;
|
||||
}
|
||||
reg = AR_READ(sc, AR_PHY_TPCRG1);
|
||||
reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1);
|
||||
reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0]);
|
||||
reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1]);
|
||||
AR_WRITE(sc, AR_PHY_TPCRG1, reg);
|
||||
|
||||
/* NB: No open loop power control for AR9285. */
|
||||
ar9285_get_pdadcs(sc, c, nxpdgains, overlap, boundaries, pdadcs);
|
||||
|
||||
/* Write boundaries. */
|
||||
reg = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP, overlap);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1, boundaries[0]);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2, boundaries[1]);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3, boundaries[2]);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4, boundaries[3]);
|
||||
AR_WRITE(sc, AR_PHY_TPCRG5, reg);
|
||||
|
||||
/* Write PDADC values. */
|
||||
for (i = 0; i < AR_NUM_PDADC_VALUES; i += 4) {
|
||||
AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + i,
|
||||
pdadcs[i + 0] << 0 |
|
||||
pdadcs[i + 1] << 8 |
|
||||
pdadcs[i + 2] << 16 |
|
||||
pdadcs[i + 3] << 24);
|
||||
}
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9285_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
const struct ar9285_eeprom *eep = sc->sc_eep;
|
||||
const struct ar9285_modal_eep_header *modal = &eep->modalHeader;
|
||||
uint8_t tpow_cck[4], tpow_ofdm[4];
|
||||
#ifndef IEEE80211_NO_HT
|
||||
uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4];
|
||||
uint8_t tpow_ht20[8], tpow_ht40[8];
|
||||
uint8_t ht40inc;
|
||||
#endif
|
||||
int16_t max_ant_gain, power[ATHN_POWER_COUNT];
|
||||
int i;
|
||||
|
||||
ar9285_set_power_calib(sc, c);
|
||||
|
||||
/* Compute transmit power reduction due to antenna gain. */
|
||||
max_ant_gain = modal->antennaGain;
|
||||
/* XXX */
|
||||
|
||||
/* Get CCK target powers. */
|
||||
ar5008_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck,
|
||||
AR9285_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
|
||||
|
||||
/* Get OFDM target powers. */
|
||||
ar5008_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G,
|
||||
AR9285_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
|
||||
|
||||
#ifndef IEEE80211_NO_HT
|
||||
/* Get HT-20 target powers. */
|
||||
ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT20, eep->calTargetPower2GHT20,
|
||||
AR9285_NUM_2G_20_TARGET_POWERS, tpow_ht20);
|
||||
|
||||
if (extc != NULL) {
|
||||
/* Get HT-40 target powers. */
|
||||
ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT40,
|
||||
eep->calTargetPower2GHT40, AR9285_NUM_2G_40_TARGET_POWERS,
|
||||
tpow_ht40);
|
||||
|
||||
/* Get secondary channel CCK target powers. */
|
||||
ar5008_get_lg_tpow(sc, extc, AR_CTL_11B,
|
||||
eep->calTargetPowerCck, AR9285_NUM_2G_CCK_TARGET_POWERS,
|
||||
tpow_cck_ext);
|
||||
|
||||
/* Get secondary channel OFDM target powers. */
|
||||
ar5008_get_lg_tpow(sc, extc, AR_CTL_11G,
|
||||
eep->calTargetPower2G, AR9285_NUM_2G_20_TARGET_POWERS,
|
||||
tpow_ofdm_ext);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(power, 0, sizeof(power));
|
||||
/* Shuffle target powers accross transmit rates. */
|
||||
power[ATHN_POWER_OFDM6 ] =
|
||||
power[ATHN_POWER_OFDM9 ] =
|
||||
power[ATHN_POWER_OFDM12 ] =
|
||||
power[ATHN_POWER_OFDM18 ] =
|
||||
power[ATHN_POWER_OFDM24 ] = tpow_ofdm[0];
|
||||
power[ATHN_POWER_OFDM36 ] = tpow_ofdm[1];
|
||||
power[ATHN_POWER_OFDM48 ] = tpow_ofdm[2];
|
||||
power[ATHN_POWER_OFDM54 ] = tpow_ofdm[3];
|
||||
power[ATHN_POWER_XR ] = tpow_ofdm[0];
|
||||
power[ATHN_POWER_CCK1_LP ] = tpow_cck[0];
|
||||
power[ATHN_POWER_CCK2_LP ] =
|
||||
power[ATHN_POWER_CCK2_SP ] = tpow_cck[1];
|
||||
power[ATHN_POWER_CCK55_LP] =
|
||||
power[ATHN_POWER_CCK55_SP] = tpow_cck[2];
|
||||
power[ATHN_POWER_CCK11_LP] =
|
||||
power[ATHN_POWER_CCK11_SP] = tpow_cck[3];
|
||||
#ifndef IEEE80211_NO_HT
|
||||
for (i = 0; i < __arraycount(tpow_ht20); i++)
|
||||
power[ATHN_POWER_HT20(i)] = tpow_ht20[i];
|
||||
if (extc != NULL) {
|
||||
/* Correct PAR difference between HT40 and HT20/Legacy. */
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2)
|
||||
ht40inc = modal->ht40PowerIncForPdadc;
|
||||
else
|
||||
ht40inc = AR_HT40_POWER_INC_FOR_PDADC;
|
||||
for (i = 0; i < __arraycount(tpow_ht40); i++)
|
||||
power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc;
|
||||
power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0];
|
||||
power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0];
|
||||
power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0];
|
||||
power[ATHN_POWER_CCK_EXT ] = tpow_cck_ext[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ATHN_POWER_COUNT; i++) {
|
||||
power[i] -= AR_PWR_TABLE_OFFSET_DB * 2; /* In half dB. */
|
||||
if (power[i] > AR_MAX_RATE_POWER)
|
||||
power[i] = AR_MAX_RATE_POWER;
|
||||
}
|
||||
|
||||
/* Commit transmit power values to hardware. */
|
||||
ar5008_write_txpower(sc, power);
|
||||
}
|
38
sys/dev/ic/arn9285.h
Normal file
38
sys/dev/ic/arn9285.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* $NetBSD: arn9285.h,v 1.1 2013/03/30 02:53:01 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _IF_ARN9285_H_
|
||||
#define _IF_ARN9285_H_
|
||||
|
||||
int ar9285_attach(struct athn_softc *);
|
||||
int ar9285_init_calib(struct athn_softc *, struct ieee80211_channel *,
|
||||
struct ieee80211_channel *);
|
||||
void ar9285_pa_calib(struct athn_softc *);
|
||||
void ar9271_load_ani(struct athn_softc *);
|
||||
void ar9271_pa_calib(struct athn_softc *);
|
||||
|
||||
#endif /* _IF_ARN9285_H_ */
|
1093
sys/dev/ic/arn9285reg.h
Normal file
1093
sys/dev/ic/arn9285reg.h
Normal file
File diff suppressed because it is too large
Load Diff
628
sys/dev/ic/arn9287.c
Normal file
628
sys/dev/ic/arn9287.c
Normal file
@ -0,0 +1,628 @@
|
||||
/* $NetBSD: arn9287.c,v 1.1 2013/03/30 02:53:01 christos Exp $ */
|
||||
/* $OpenBSD: ar9287.c,v 1.17 2012/06/10 21:23:36 kettenis Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Driver for Atheros 802.11a/g/n chipsets.
|
||||
* Routines for AR9227 and AR9287 chipsets.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: arn9287.c,v 1.1 2013/03/30 02:53:01 christos Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/intr.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_amrr.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/ic/athnreg.h>
|
||||
#include <dev/ic/athnvar.h>
|
||||
|
||||
#include <dev/ic/arn5008reg.h>
|
||||
#include <dev/ic/arn9280reg.h>
|
||||
#include <dev/ic/arn9287reg.h>
|
||||
|
||||
#include <dev/ic/arn5008.h>
|
||||
#include <dev/ic/arn9280.h>
|
||||
#include <dev/ic/arn9287.h>
|
||||
|
||||
#define Static static
|
||||
|
||||
Static void ar9287_get_pdadcs(struct athn_softc *,
|
||||
struct ieee80211_channel *, int, int, uint8_t, uint8_t *,
|
||||
uint8_t *);
|
||||
Static const struct ar_spur_chan *
|
||||
ar9287_get_spur_chans(struct athn_softc *, int);
|
||||
Static void ar9287_init_from_rom(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9287_olpc_get_pdgain(struct athn_softc *,
|
||||
struct ieee80211_channel *, int, int8_t *);
|
||||
Static void ar9287_olpc_init(struct athn_softc *);
|
||||
Static void ar9287_olpc_temp_compensation(struct athn_softc *);
|
||||
Static void ar9287_set_power_calib(struct athn_softc *,
|
||||
struct ieee80211_channel *);
|
||||
Static void ar9287_set_txpower(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9287_setup(struct athn_softc *);
|
||||
Static void ar9287_swap_rom(struct athn_softc *);
|
||||
|
||||
PUBLIC int
|
||||
ar9287_attach(struct athn_softc *sc)
|
||||
{
|
||||
|
||||
sc->sc_eep_base = AR9287_EEP_START_LOC;
|
||||
sc->sc_eep_size = sizeof(struct ar9287_eeprom);
|
||||
sc->sc_def_nf = AR9287_PHY_CCA_MAX_GOOD_VALUE;
|
||||
sc->sc_ngpiopins = (sc->sc_flags & ATHN_FLAG_USB) ? 16 : 11;
|
||||
sc->sc_led_pin = 8;
|
||||
sc->sc_workaround = AR9285_WA_DEFAULT;
|
||||
sc->sc_ops.setup = ar9287_setup;
|
||||
sc->sc_ops.swap_rom = ar9287_swap_rom;
|
||||
sc->sc_ops.init_from_rom = ar9287_init_from_rom;
|
||||
sc->sc_ops.set_txpower = ar9287_set_txpower;
|
||||
sc->sc_ops.set_synth = ar9280_set_synth;
|
||||
sc->sc_ops.spur_mitigate = ar9280_spur_mitigate;
|
||||
sc->sc_ops.get_spur_chans = ar9287_get_spur_chans;
|
||||
sc->sc_ops.olpc_init = ar9287_olpc_init;
|
||||
sc->sc_ops.olpc_temp_compensation = ar9287_olpc_temp_compensation;
|
||||
sc->sc_ini = &ar9287_1_1_ini;
|
||||
sc->sc_serdes = &ar9280_2_0_serdes;
|
||||
|
||||
return ar5008_attach(sc);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9287_setup(struct athn_softc *sc)
|
||||
{
|
||||
const struct ar9287_eeprom *eep = sc->sc_eep;
|
||||
|
||||
/* Determine if open loop power control should be used. */
|
||||
if (eep->baseEepHeader.openLoopPwrCntl)
|
||||
sc->sc_flags |= ATHN_FLAG_OLPC;
|
||||
|
||||
sc->sc_rx_gain = &ar9287_1_1_rx_gain;
|
||||
sc->sc_tx_gain = &ar9287_1_1_tx_gain;
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9287_swap_rom(struct athn_softc *sc)
|
||||
{
|
||||
struct ar9287_eeprom *eep = sc->sc_eep;
|
||||
int i;
|
||||
|
||||
eep->modalHeader.antCtrlCommon =
|
||||
bswap32(eep->modalHeader.antCtrlCommon);
|
||||
|
||||
for (i = 0; i < AR9287_MAX_CHAINS; i++) {
|
||||
eep->modalHeader.antCtrlChain[i] =
|
||||
bswap32(eep->modalHeader.antCtrlChain[i]);
|
||||
}
|
||||
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
|
||||
eep->modalHeader.spurChans[i].spurChan =
|
||||
bswap16(eep->modalHeader.spurChans[i].spurChan);
|
||||
}
|
||||
}
|
||||
|
||||
Static const struct ar_spur_chan *
|
||||
ar9287_get_spur_chans(struct athn_softc *sc, int is2ghz)
|
||||
{
|
||||
const struct ar9287_eeprom *eep = sc->sc_eep;
|
||||
|
||||
KASSERT(is2ghz);
|
||||
return eep->modalHeader.spurChans;
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9287_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
const struct ar9287_eeprom *eep = sc->sc_eep;
|
||||
const struct ar9287_modal_eep_header *modal = &eep->modalHeader;
|
||||
uint32_t reg, offset;
|
||||
int i;
|
||||
|
||||
AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon);
|
||||
|
||||
for (i = 0; i < AR9287_MAX_CHAINS; i++) {
|
||||
offset = i * 0x1000;
|
||||
|
||||
AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0 + offset,
|
||||
modal->antCtrlChain[i]);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0 + offset);
|
||||
reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
|
||||
modal->iqCalICh[i]);
|
||||
reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
|
||||
modal->iqCalQCh[i]);
|
||||
AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0 + offset, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
|
||||
modal->bswMargin[i]);
|
||||
reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
|
||||
modal->bswAtten[i]);
|
||||
AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
|
||||
reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN,
|
||||
modal->rxTxMarginCh[i]);
|
||||
reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN,
|
||||
modal->txRxAttenCh[i]);
|
||||
AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
|
||||
}
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_SETTLING);
|
||||
#ifndef IEEE80211_NO_HT
|
||||
if (extc != NULL)
|
||||
reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
|
||||
else
|
||||
#endif
|
||||
reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
|
||||
AR_WRITE(sc, AR_PHY_SETTLING, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
|
||||
reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
|
||||
AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
|
||||
|
||||
reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
|
||||
reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
|
||||
reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
|
||||
reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_RF_CTL3);
|
||||
reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_CCA(0));
|
||||
reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62);
|
||||
AR_WRITE(sc, AR_PHY_CCA(0), reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_EXT_CCA0);
|
||||
reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62);
|
||||
AR_WRITE(sc, AR_PHY_EXT_CCA0, reg);
|
||||
|
||||
reg = AR_READ(sc, AR9287_AN_RF2G3_CH0);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_DB1, modal->db1);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_DB2, modal->db2);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_OB_CCK, modal->ob_cck);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_OB_PSK, modal->ob_psk);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_OB_QAM, modal->ob_qam);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_OB_PAL_OFF, modal->ob_pal_off);
|
||||
AR_WRITE(sc, AR9287_AN_RF2G3_CH0, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
|
||||
reg = AR_READ(sc, AR9287_AN_RF2G3_CH1);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_DB1, modal->db1);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_DB2, modal->db2);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_OB_CCK, modal->ob_cck);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_OB_PSK, modal->ob_psk);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_OB_QAM, modal->ob_qam);
|
||||
reg = RW(reg, AR9287_AN_RF2G3_OB_PAL_OFF, modal->ob_pal_off);
|
||||
AR_WRITE(sc, AR9287_AN_RF2G3_CH1, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_RF_CTL2);
|
||||
reg = RW(reg, AR_PHY_TX_END_DATA_START, modal->txFrameToDataStart);
|
||||
reg = RW(reg, AR_PHY_TX_END_PA_ON, modal->txFrameToPaOn);
|
||||
AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
|
||||
|
||||
reg = AR_READ(sc, AR9287_AN_TOP2);
|
||||
reg = RW(reg, AR9287_AN_TOP2_XPABIAS_LVL, modal->xpaBiasLvl);
|
||||
AR_WRITE(sc, AR9287_AN_TOP2, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9287_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
int chain, int nxpdgains, uint8_t overlap, uint8_t *boundaries,
|
||||
uint8_t *pdadcs)
|
||||
{
|
||||
const struct ar9287_eeprom *eep = sc->sc_eep;
|
||||
const struct ar9287_cal_data_per_freq *pierdata;
|
||||
const uint8_t *pierfreq;
|
||||
struct athn_pier lopier, hipier;
|
||||
int16_t delta;
|
||||
uint8_t fbin;
|
||||
int i, lo, hi, npiers;
|
||||
|
||||
pierfreq = eep->calFreqPier2G;
|
||||
pierdata = (const struct ar9287_cal_data_per_freq *)
|
||||
eep->calPierData2G[chain];
|
||||
npiers = AR9287_NUM_2G_CAL_PIERS;
|
||||
|
||||
/* Find channel in ROM pier table. */
|
||||
fbin = athn_chan2fbin(c);
|
||||
athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
|
||||
|
||||
lopier.fbin = pierfreq[lo];
|
||||
hipier.fbin = pierfreq[hi];
|
||||
for (i = 0; i < nxpdgains; i++) {
|
||||
lopier.pwr[i] = pierdata[lo].pwrPdg[i];
|
||||
lopier.vpd[i] = pierdata[lo].vpdPdg[i];
|
||||
hipier.pwr[i] = pierdata[lo].pwrPdg[i];
|
||||
hipier.vpd[i] = pierdata[lo].vpdPdg[i];
|
||||
}
|
||||
ar5008_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains,
|
||||
AR9287_PD_GAIN_ICEPTS, overlap, boundaries, pdadcs);
|
||||
|
||||
delta = (eep->baseEepHeader.pwrTableOffset -
|
||||
AR_PWR_TABLE_OFFSET_DB) * 2; /* In half dB. */
|
||||
if (delta != 0) {
|
||||
/* Shift the PDADC table to start at the new offset. */
|
||||
/* XXX Our padding value differs from Linux. */
|
||||
for (i = 0; i < AR_NUM_PDADC_VALUES; i++)
|
||||
pdadcs[i] = pdadcs[MIN(i + delta,
|
||||
AR_NUM_PDADC_VALUES - 1)];
|
||||
}
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9287_olpc_get_pdgain(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
int chain, int8_t *pwr)
|
||||
{
|
||||
const struct ar9287_eeprom *eep = sc->sc_eep;
|
||||
const struct ar_cal_data_per_freq_olpc *pierdata;
|
||||
const uint8_t *pierfreq;
|
||||
uint8_t fbin;
|
||||
int lo, hi, npiers;
|
||||
|
||||
pierfreq = eep->calFreqPier2G;
|
||||
pierdata = (const struct ar_cal_data_per_freq_olpc *)
|
||||
eep->calPierData2G[chain];
|
||||
npiers = AR9287_NUM_2G_CAL_PIERS;
|
||||
|
||||
/* Find channel in ROM pier table. */
|
||||
fbin = athn_chan2fbin(c);
|
||||
athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
|
||||
#if 0
|
||||
*pwr = athn_interpolate(fbin,
|
||||
pierfreq[lo], pierdata[lo].pwrPdg[0][0],
|
||||
pierfreq[hi], pierdata[hi].pwrPdg[0][0]);
|
||||
#else
|
||||
*pwr = (pierdata[lo].pwrPdg[0][0] + pierdata[hi].pwrPdg[0][0]) / 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9287_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
const struct ar9287_eeprom *eep = sc->sc_eep;
|
||||
uint8_t boundaries[AR_PD_GAINS_IN_MASK];
|
||||
uint8_t pdadcs[AR_NUM_PDADC_VALUES];
|
||||
uint8_t xpdgains[AR9287_NUM_PD_GAINS];
|
||||
int8_t txpower;
|
||||
uint8_t overlap;
|
||||
uint32_t reg, offset;
|
||||
int i, j, nxpdgains;
|
||||
|
||||
if (sc->sc_eep_rev < AR_EEP_MINOR_VER_2) {
|
||||
overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),
|
||||
AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
|
||||
}
|
||||
else
|
||||
overlap = eep->modalHeader.pdGainOverlap;
|
||||
|
||||
if (sc->sc_flags & ATHN_FLAG_OLPC) {
|
||||
/* XXX not here. */
|
||||
sc->sc_pdadc =
|
||||
((const struct ar_cal_data_per_freq_olpc *)
|
||||
eep->calPierData2G[0])->vpdPdg[0][0];
|
||||
}
|
||||
|
||||
nxpdgains = 0;
|
||||
memset(xpdgains, 0, sizeof(xpdgains));
|
||||
for (i = AR9287_PD_GAINS_IN_MASK - 1; i >= 0; i--) {
|
||||
if (nxpdgains >= AR9287_NUM_PD_GAINS)
|
||||
break; /* Can't happen. */
|
||||
if (eep->modalHeader.xpdGain & (1 << i))
|
||||
xpdgains[nxpdgains++] = i;
|
||||
}
|
||||
reg = AR_READ(sc, AR_PHY_TPCRG1);
|
||||
reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1);
|
||||
reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0]);
|
||||
reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1]);
|
||||
AR_WRITE(sc, AR_PHY_TPCRG1, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
|
||||
for (i = 0; i < AR9287_MAX_CHAINS; i++) {
|
||||
if (!(sc->sc_txchainmask & (1 << i)))
|
||||
continue;
|
||||
|
||||
offset = i * 0x1000;
|
||||
|
||||
if (sc->sc_flags & ATHN_FLAG_OLPC) {
|
||||
ar9287_olpc_get_pdgain(sc, c, i, &txpower);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_0);
|
||||
reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
|
||||
AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_0, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_1);
|
||||
reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
|
||||
AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_1, reg);
|
||||
|
||||
/* NB: txpower is in half dB. */
|
||||
reg = AR_READ(sc, AR_PHY_CH0_TX_PWRCTRL11 + offset);
|
||||
reg = RW(reg, AR_PHY_TX_PWRCTRL_OLPC_PWR, txpower);
|
||||
AR_WRITE(sc, AR_PHY_CH0_TX_PWRCTRL11 + offset, reg);
|
||||
|
||||
AR_WRITE_BARRIER(sc);
|
||||
continue; /* That's it for open loop mode. */
|
||||
}
|
||||
|
||||
/* Closed loop power control. */
|
||||
ar9287_get_pdadcs(sc, c, i, nxpdgains, overlap,
|
||||
boundaries, pdadcs);
|
||||
|
||||
/* Write boundaries. */
|
||||
if (i == 0) {
|
||||
reg = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP,
|
||||
overlap);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1,
|
||||
boundaries[0]);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2,
|
||||
boundaries[1]);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3,
|
||||
boundaries[2]);
|
||||
reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4,
|
||||
boundaries[3]);
|
||||
AR_WRITE(sc, AR_PHY_TPCRG5 + offset, reg);
|
||||
}
|
||||
/* Write PDADC values. */
|
||||
for (j = 0; j < AR_NUM_PDADC_VALUES; j += 4) {
|
||||
AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + offset + j,
|
||||
pdadcs[j + 0] << 0 |
|
||||
pdadcs[j + 1] << 8 |
|
||||
pdadcs[j + 2] << 16 |
|
||||
pdadcs[j + 3] << 24);
|
||||
}
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9287_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
const struct ar9287_eeprom *eep = sc->sc_eep;
|
||||
const struct ar9287_modal_eep_header *modal = &eep->modalHeader;
|
||||
uint8_t tpow_cck[4], tpow_ofdm[4];
|
||||
#ifndef IEEE80211_NO_HT
|
||||
uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4];
|
||||
uint8_t tpow_ht20[8], tpow_ht40[8];
|
||||
uint8_t ht40inc;
|
||||
#endif
|
||||
int16_t pwr = 0, max_ant_gain, power[ATHN_POWER_COUNT];
|
||||
int i;
|
||||
|
||||
ar9287_set_power_calib(sc, c);
|
||||
|
||||
/* Compute transmit power reduction due to antenna gain. */
|
||||
max_ant_gain = MAX(modal->antennaGainCh[0], modal->antennaGainCh[1]);
|
||||
/* XXX */
|
||||
|
||||
/*
|
||||
* Reduce scaled power by number of active chains to get per-chain
|
||||
* transmit power level.
|
||||
*/
|
||||
if (sc->sc_ntxchains == 2)
|
||||
pwr -= AR_PWR_DECREASE_FOR_2_CHAIN;
|
||||
if (pwr < 0)
|
||||
pwr = 0;
|
||||
|
||||
/* Get CCK target powers. */
|
||||
ar5008_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck,
|
||||
AR9287_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
|
||||
|
||||
/* Get OFDM target powers. */
|
||||
ar5008_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G,
|
||||
AR9287_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
|
||||
|
||||
#ifndef IEEE80211_NO_HT
|
||||
/* Get HT-20 target powers. */
|
||||
ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT20, eep->calTargetPower2GHT20,
|
||||
AR9287_NUM_2G_20_TARGET_POWERS, tpow_ht20);
|
||||
|
||||
if (extc != NULL) {
|
||||
/* Get HT-40 target powers. */
|
||||
ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT40,
|
||||
eep->calTargetPower2GHT40, AR9287_NUM_2G_40_TARGET_POWERS,
|
||||
tpow_ht40);
|
||||
|
||||
/* Get secondary channel CCK target powers. */
|
||||
ar5008_get_lg_tpow(sc, extc, AR_CTL_11B,
|
||||
eep->calTargetPowerCck, AR9287_NUM_2G_CCK_TARGET_POWERS,
|
||||
tpow_cck_ext);
|
||||
|
||||
/* Get secondary channel OFDM target powers. */
|
||||
ar5008_get_lg_tpow(sc, extc, AR_CTL_11G,
|
||||
eep->calTargetPower2G, AR9287_NUM_2G_20_TARGET_POWERS,
|
||||
tpow_ofdm_ext);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(power, 0, sizeof(power));
|
||||
/* Shuffle target powers accross transmit rates. */
|
||||
power[ATHN_POWER_OFDM6 ] =
|
||||
power[ATHN_POWER_OFDM9 ] =
|
||||
power[ATHN_POWER_OFDM12 ] =
|
||||
power[ATHN_POWER_OFDM18 ] =
|
||||
power[ATHN_POWER_OFDM24 ] = tpow_ofdm[0];
|
||||
power[ATHN_POWER_OFDM36 ] = tpow_ofdm[1];
|
||||
power[ATHN_POWER_OFDM48 ] = tpow_ofdm[2];
|
||||
power[ATHN_POWER_OFDM54 ] = tpow_ofdm[3];
|
||||
power[ATHN_POWER_XR ] = tpow_ofdm[0];
|
||||
power[ATHN_POWER_CCK1_LP ] = tpow_cck[0];
|
||||
power[ATHN_POWER_CCK2_LP ] =
|
||||
power[ATHN_POWER_CCK2_SP ] = tpow_cck[1];
|
||||
power[ATHN_POWER_CCK55_LP] =
|
||||
power[ATHN_POWER_CCK55_SP] = tpow_cck[2];
|
||||
power[ATHN_POWER_CCK11_LP] =
|
||||
power[ATHN_POWER_CCK11_SP] = tpow_cck[3];
|
||||
#ifndef IEEE80211_NO_HT
|
||||
for (i = 0; i < nitems(tpow_ht20); i++)
|
||||
power[ATHN_POWER_HT20(i)] = tpow_ht20[i];
|
||||
if (extc != NULL) {
|
||||
/* Correct PAR difference between HT40 and HT20/Legacy. */
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2)
|
||||
ht40inc = modal->ht40PowerIncForPdadc;
|
||||
else
|
||||
ht40inc = AR_HT40_POWER_INC_FOR_PDADC;
|
||||
for (i = 0; i < nitems(tpow_ht40); i++)
|
||||
power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc;
|
||||
power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0];
|
||||
power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0];
|
||||
power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0];
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
power[ATHN_POWER_CCK_EXT] = tpow_cck_ext[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ATHN_POWER_COUNT; i++) {
|
||||
power[i] -= AR_PWR_TABLE_OFFSET_DB * 2; /* In half dB. */
|
||||
if (power[i] > AR_MAX_RATE_POWER)
|
||||
power[i] = AR_MAX_RATE_POWER;
|
||||
}
|
||||
/* Commit transmit power values to hardware. */
|
||||
ar5008_write_txpower(sc, power);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9287_olpc_init(struct athn_softc *sc)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
AR_SETBITS(sc, AR_PHY_TX_PWRCTRL9, AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL);
|
||||
|
||||
reg = AR_READ(sc, AR9287_AN_TXPC0);
|
||||
reg = RW(reg, AR9287_AN_TXPC0_TXPCMODE,
|
||||
AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE);
|
||||
AR_WRITE(sc, AR9287_AN_TXPC0, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(100);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9287_olpc_temp_compensation(struct athn_softc *sc)
|
||||
{
|
||||
const struct ar9287_eeprom *eep = sc->sc_eep;
|
||||
int8_t pdadc, slope, tcomp;
|
||||
uint32_t reg;
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TX_PWRCTRL4);
|
||||
pdadc = MS(reg, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
|
||||
DPRINTFN(DBG_RF, sc, "PD Avg Out=%d\n", pdadc);
|
||||
|
||||
if (sc->sc_pdadc == 0 || pdadc == 0)
|
||||
return; /* No frames transmitted yet. */
|
||||
|
||||
/* Compute Tx gain temperature compensation. */
|
||||
if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2)
|
||||
slope = eep->baseEepHeader.tempSensSlope;
|
||||
else
|
||||
slope = 0;
|
||||
if (slope != 0) /* Prevents division by zero. */
|
||||
tcomp = ((pdadc - sc->sc_pdadc) * 4) / slope;
|
||||
else
|
||||
tcomp = 0;
|
||||
DPRINTFN(DBG_RF, sc, "OLPC temp compensation=%d\n", tcomp);
|
||||
|
||||
/* Write compensation value for both Tx chains. */
|
||||
reg = AR_READ(sc, AR_PHY_CH0_TX_PWRCTRL11);
|
||||
reg = RW(reg, AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, tcomp);
|
||||
AR_WRITE(sc, AR_PHY_CH0_TX_PWRCTRL11, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_CH1_TX_PWRCTRL11);
|
||||
reg = RW(reg, AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, tcomp);
|
||||
AR_WRITE(sc, AR_PHY_CH1_TX_PWRCTRL11, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar9287_1_3_enable_async_fifo(struct athn_softc *sc)
|
||||
{
|
||||
|
||||
/* Enable ASYNC FIFO. */
|
||||
AR_SETBITS(sc, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
|
||||
AR_SETBITS(sc, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
|
||||
AR_CLRBITS(sc, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
|
||||
AR_SETBITS(sc, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
ar9287_1_3_setup_async_fifo(struct athn_softc *sc)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/*
|
||||
* MAC runs at 117MHz (instead of 88/44MHz) when ASYNC FIFO is
|
||||
* enabled, so the following counters have to be changed.
|
||||
*/
|
||||
AR_WRITE(sc, AR_D_GBL_IFS_SIFS, AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
|
||||
AR_WRITE(sc, AR_D_GBL_IFS_SLOT, AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
|
||||
AR_WRITE(sc, AR_D_GBL_IFS_EIFS, AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
|
||||
|
||||
AR_WRITE(sc, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
|
||||
AR_WRITE(sc, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
|
||||
|
||||
AR_SETBITS(sc, AR_MAC_PCU_LOGIC_ANALYZER,
|
||||
AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
|
||||
|
||||
reg = AR_READ(sc, AR_AHB_MODE);
|
||||
reg = RW(reg, AR_AHB_CUSTOM_BURST, AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
|
||||
AR_WRITE(sc, AR_AHB_MODE, reg);
|
||||
|
||||
AR_SETBITS(sc, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
35
sys/dev/ic/arn9287.h
Normal file
35
sys/dev/ic/arn9287.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* $NetBSD: arn9287.h,v 1.1 2013/03/30 02:53:01 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _IF_ARN9287_H_
|
||||
#define _IF_ARN9287_H_
|
||||
|
||||
int ar9287_attach(struct athn_softc *);
|
||||
void ar9287_1_3_enable_async_fifo(struct athn_softc *);
|
||||
void ar9287_1_3_setup_async_fifo(struct athn_softc *);
|
||||
|
||||
#endif /* _IF_ARN9287_H_ */
|
539
sys/dev/ic/arn9287reg.h
Normal file
539
sys/dev/ic/arn9287reg.h
Normal file
@ -0,0 +1,539 @@
|
||||
/* $NetBSD: arn9287reg.h,v 1.1 2013/03/30 02:53:02 christos Exp $ */
|
||||
/* $OpenBSD: ar9287reg.h,v 1.3 2010/07/15 19:07:43 damien Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _ARN9287REG_H_
|
||||
#define _ARN9287REG_H_
|
||||
|
||||
#define AR9287_MAX_CHAINS 2
|
||||
|
||||
#define AR9287_PHY_CCA_MAX_GOOD_VALUE (-118)
|
||||
|
||||
/*
|
||||
* Analog registers.
|
||||
*/
|
||||
#define AR9287_AN_RF2G3_CH0 0x7808
|
||||
#define AR9287_AN_RF2G3_CH1 0x785c
|
||||
#define AR9287_AN_TXPC0 0x7898
|
||||
#define AR9287_AN_TOP2 0x78b4
|
||||
|
||||
/* Bits for AR9287_AN_RF2G3_CH[01]. */
|
||||
#define AR9287_AN_RF2G3_OB_PAL_OFF_M 0x0001c000
|
||||
#define AR9287_AN_RF2G3_OB_PAL_OFF_S 14
|
||||
#define AR9287_AN_RF2G3_OB_QAM_M 0x000e0000
|
||||
#define AR9287_AN_RF2G3_OB_QAM_S 17
|
||||
#define AR9287_AN_RF2G3_OB_PSK_M 0x00700000
|
||||
#define AR9287_AN_RF2G3_OB_PSK_S 20
|
||||
#define AR9287_AN_RF2G3_OB_CCK_M 0x03800000
|
||||
#define AR9287_AN_RF2G3_OB_CCK_S 23
|
||||
#define AR9287_AN_RF2G3_DB2_M 0x1c000000
|
||||
#define AR9287_AN_RF2G3_DB2_S 26
|
||||
#define AR9287_AN_RF2G3_DB1_M 0xe0000000
|
||||
#define AR9287_AN_RF2G3_DB1_S 29
|
||||
|
||||
/* Bits for AR9287_AN_TXPC0. */
|
||||
#define AR9287_AN_TXPC0_TXPCMODE_M 0x0000c000
|
||||
#define AR9287_AN_TXPC0_TXPCMODE_S 14
|
||||
#define AR9287_AN_TXPC0_TXPCMODE_NORMAL 0
|
||||
#define AR9287_AN_TXPC0_TXPCMODE_TEST 1
|
||||
#define AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE 2
|
||||
#define AR9287_AN_TXPC0_TXPCMODE_ATBTEST 3
|
||||
|
||||
/* Bits for AR9287_AN_TOP2. */
|
||||
#define AR9287_AN_TOP2_XPABIAS_LVL_M 0xc0000000
|
||||
#define AR9287_AN_TOP2_XPABIAS_LVL_S 30
|
||||
|
||||
/*
|
||||
* ROM layout used by AR9287 (2GHz only).
|
||||
*/
|
||||
#define AR9287_EEP_START_LOC 128
|
||||
#define AR9287_NUM_2G_CAL_PIERS 3
|
||||
#define AR9287_NUM_2G_CCK_TARGET_POWERS 3
|
||||
#define AR9287_NUM_2G_20_TARGET_POWERS 3
|
||||
#define AR9287_NUM_2G_40_TARGET_POWERS 3
|
||||
#define AR9287_NUM_CTLS 12
|
||||
#define AR9287_NUM_BAND_EDGES 4
|
||||
#define AR9287_NUM_PD_GAINS 4
|
||||
#define AR9287_PD_GAINS_IN_MASK 4
|
||||
#define AR9287_PD_GAIN_ICEPTS 1
|
||||
#define AR9287_MAX_RATE_POWER 63
|
||||
#define AR9287_NUM_RATES 16
|
||||
|
||||
struct ar9287_base_eep_header {
|
||||
uint16_t length;
|
||||
uint16_t checksum;
|
||||
uint16_t version;
|
||||
uint8_t opCapFlags;
|
||||
uint8_t eepMisc;
|
||||
#define AR9287_EEPMISC_BIG_ENDIAN 0x01
|
||||
#define AR9287_EEPMISC_WOW 0x02
|
||||
|
||||
uint16_t regDmn[2];
|
||||
uint8_t macAddr[6];
|
||||
uint8_t rxMask;
|
||||
uint8_t txMask;
|
||||
uint16_t rfSilent;
|
||||
uint16_t blueToothOptions;
|
||||
uint16_t deviceCap;
|
||||
uint32_t binBuildNumber;
|
||||
uint8_t deviceType;
|
||||
/* End of common header. */
|
||||
uint8_t openLoopPwrCntl;
|
||||
int8_t pwrTableOffset;
|
||||
int8_t tempSensSlope;
|
||||
int8_t tempSensSlopePalOn;
|
||||
uint8_t futureBase[29];
|
||||
} __packed;
|
||||
|
||||
struct ar9287_modal_eep_header {
|
||||
uint32_t antCtrlChain[AR9287_MAX_CHAINS];
|
||||
uint32_t antCtrlCommon;
|
||||
int8_t antennaGainCh[AR9287_MAX_CHAINS];
|
||||
uint8_t switchSettling;
|
||||
uint8_t txRxAttenCh[AR9287_MAX_CHAINS];
|
||||
uint8_t rxTxMarginCh[AR9287_MAX_CHAINS];
|
||||
int8_t adcDesiredSize;
|
||||
uint8_t txEndToXpaOff;
|
||||
uint8_t txEndToRxOn;
|
||||
uint8_t txFrameToXpaOn;
|
||||
uint8_t thresh62;
|
||||
int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS];
|
||||
uint8_t xpdGain;
|
||||
uint8_t xpd;
|
||||
int8_t iqCalICh[AR9287_MAX_CHAINS];
|
||||
int8_t iqCalQCh[AR9287_MAX_CHAINS];
|
||||
uint8_t pdGainOverlap;
|
||||
uint8_t xpaBiasLvl;
|
||||
uint8_t txFrameToDataStart;
|
||||
uint8_t txFrameToPaOn;
|
||||
uint8_t ht40PowerIncForPdadc;
|
||||
uint8_t bswAtten[AR9287_MAX_CHAINS];
|
||||
uint8_t bswMargin[AR9287_MAX_CHAINS];
|
||||
uint8_t swSettleHt40;
|
||||
uint8_t version;
|
||||
uint8_t db1;
|
||||
uint8_t db2;
|
||||
uint8_t ob_cck;
|
||||
uint8_t ob_psk;
|
||||
uint8_t ob_qam;
|
||||
uint8_t ob_pal_off;
|
||||
uint8_t futureModal[30];
|
||||
struct ar_spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
|
||||
} __packed;
|
||||
|
||||
struct ar9287_cal_data_per_freq {
|
||||
uint8_t pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
|
||||
uint8_t vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
|
||||
} __packed;
|
||||
|
||||
union ar9287_cal_data_per_freq_u {
|
||||
struct ar_cal_data_per_freq_olpc calDataOpen;
|
||||
struct ar9287_cal_data_per_freq calDataClose;
|
||||
} __packed;
|
||||
|
||||
struct ar9287_cal_ctl_data {
|
||||
struct ar_cal_ctl_edges
|
||||
ctlEdges[AR9287_MAX_CHAINS][AR9287_NUM_BAND_EDGES];
|
||||
} __packed;
|
||||
|
||||
struct ar9287_eeprom {
|
||||
struct ar9287_base_eep_header baseEepHeader;
|
||||
uint8_t custData[32];
|
||||
struct ar9287_modal_eep_header modalHeader;
|
||||
uint8_t calFreqPier2G[AR9287_NUM_2G_CAL_PIERS];
|
||||
union ar9287_cal_data_per_freq_u
|
||||
calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS];
|
||||
struct ar_cal_target_power_leg
|
||||
calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS];
|
||||
struct ar_cal_target_power_leg
|
||||
calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS];
|
||||
struct ar_cal_target_power_ht
|
||||
calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS];
|
||||
struct ar_cal_target_power_ht
|
||||
calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS];
|
||||
uint8_t ctlIndex[AR9287_NUM_CTLS];
|
||||
struct ar9287_cal_ctl_data ctlData[AR9287_NUM_CTLS];
|
||||
uint8_t padding;
|
||||
} __packed;
|
||||
|
||||
/* Macro to "pack" registers to 16-bit to save some .rodata space. */
|
||||
#define P(x) (x)
|
||||
|
||||
/*
|
||||
* AR9287 1.1 initialization values.
|
||||
*/
|
||||
static const uint16_t ar9287_1_1_regs[] = {
|
||||
P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
|
||||
P(0x0801c), P(0x08120), P(0x081d0), P(0x08318), P(0x09804),
|
||||
P(0x09820), P(0x09824), P(0x09828), P(0x09834), P(0x09838),
|
||||
P(0x09840), P(0x09844), P(0x09850), P(0x09858), P(0x0985c),
|
||||
P(0x09860), P(0x09864), P(0x09868), P(0x0986c), P(0x09914),
|
||||
P(0x09918), P(0x09924), P(0x09944), P(0x09960), P(0x0a960),
|
||||
P(0x09964), P(0x0c968), P(0x099b8), P(0x099bc), P(0x099c0),
|
||||
P(0x0a204), P(0x0a20c), P(0x0b20c), P(0x0a21c), P(0x0a230),
|
||||
P(0x0a250), P(0x0a358), P(0x0a3d8)
|
||||
};
|
||||
|
||||
#ifndef IEEE80211_NO_HT
|
||||
static const uint32_t ar9287_1_1_vals_2g40[] = {
|
||||
0x000002c0, 0x00000318, 0x00007c70, 0x00000000, 0x10801600,
|
||||
0x12e00057, 0x08f04810, 0x0000320a, 0x00006880, 0x000003c4,
|
||||
0x02020200, 0x01000e0e, 0x3a020001, 0x00000e0e, 0x00000007,
|
||||
0x206a012e, 0x037216a0, 0x6d4000e2, 0x7ec84d2e, 0x3139605e,
|
||||
0x00058d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00001130,
|
||||
0x00000016, 0xd00a8a0d, 0xefbc1010, 0x00000010, 0x00000010,
|
||||
0x00000210, 0x000003ce, 0x0000001c, 0x00000c00, 0x05eea6d4,
|
||||
0x00000444, 0x00000000, 0x00000000, 0x1883800a, 0x00000210,
|
||||
0x0004a000, 0x7999aa0e, 0x00000000
|
||||
};
|
||||
#endif
|
||||
|
||||
static const uint32_t ar9287_1_1_vals_2g20[] = {
|
||||
0x00000160, 0x0000018c, 0x00003e38, 0x00000000, 0x08400b00,
|
||||
0x12e0002b, 0x08f04810, 0x0000320a, 0x00003440, 0x00000300,
|
||||
0x02020200, 0x01000e0e, 0x3a020001, 0x00000e0e, 0x00000007,
|
||||
0x206a012e, 0x037216a0, 0x6c4000e2, 0x7ec84d2e, 0x31395d5e,
|
||||
0x00058d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00000898,
|
||||
0x0000000b, 0xd00a8a0d, 0xefbc1010, 0x00000010, 0x00000010,
|
||||
0x00000210, 0x000003ce, 0x0000001c, 0x00000c00, 0x05eea6d4,
|
||||
0x00000444, 0x00000000, 0x00000000, 0x1883800a, 0x00000108,
|
||||
0x0004a000, 0x7999aa0e, 0x00000000
|
||||
};
|
||||
|
||||
static const uint16_t ar9287_1_1_cm_regs[] = {
|
||||
P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
|
||||
P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
|
||||
P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
|
||||
P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
|
||||
P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
|
||||
P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
|
||||
P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
|
||||
P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
|
||||
P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
|
||||
P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
|
||||
P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
|
||||
P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
|
||||
P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
|
||||
P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
|
||||
P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
|
||||
P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
|
||||
P(0x0147c), P(0x04030), P(0x0403c), P(0x04024), P(0x04060),
|
||||
P(0x04064), P(0x07010), P(0x07020), P(0x07034), P(0x07038),
|
||||
P(0x08004), P(0x08008), P(0x0800c), P(0x08018), P(0x08020),
|
||||
P(0x08038), P(0x0803c), P(0x08048), P(0x08054), P(0x08058),
|
||||
P(0x0805c), P(0x08060), P(0x08064), P(0x08070), P(0x080c0),
|
||||
P(0x080c4), P(0x080c8), P(0x080cc), P(0x080d0), P(0x080d4),
|
||||
P(0x080d8), P(0x080e0), P(0x080e4), P(0x080e8), P(0x080ec),
|
||||
P(0x080f0), P(0x080f4), P(0x080f8), P(0x080fc), P(0x08100),
|
||||
P(0x08104), P(0x08108), P(0x0810c), P(0x08110), P(0x08118),
|
||||
P(0x0811c), P(0x08124), P(0x08128), P(0x0812c), P(0x08130),
|
||||
P(0x08134), P(0x08138), P(0x0813c), P(0x08144), P(0x08168),
|
||||
P(0x0816c), P(0x08170), P(0x08174), P(0x08178), P(0x0817c),
|
||||
P(0x081c0), P(0x081c4), P(0x081d4), P(0x081ec), P(0x081f0),
|
||||
P(0x081f4), P(0x081f8), P(0x081fc), P(0x08200), P(0x08204),
|
||||
P(0x08208), P(0x0820c), P(0x08210), P(0x08214), P(0x08218),
|
||||
P(0x0821c), P(0x08220), P(0x08224), P(0x08228), P(0x0822c),
|
||||
P(0x08230), P(0x08234), P(0x08238), P(0x0823c), P(0x08240),
|
||||
P(0x08244), P(0x08248), P(0x0824c), P(0x08250), P(0x08254),
|
||||
P(0x08258), P(0x0825c), P(0x08260), P(0x08264), P(0x08270),
|
||||
P(0x08274), P(0x08278), P(0x0827c), P(0x08284), P(0x08288),
|
||||
P(0x0828c), P(0x08294), P(0x08298), P(0x0829c), P(0x08300),
|
||||
P(0x08314), P(0x08328), P(0x0832c), P(0x08330), P(0x08334),
|
||||
P(0x08338), P(0x0833c), P(0x08340), P(0x08344), P(0x08360),
|
||||
P(0x08364), P(0x08368), P(0x08370), P(0x08374), P(0x08378),
|
||||
P(0x0837c), P(0x08380), P(0x08384), P(0x08390), P(0x08394),
|
||||
P(0x08398), P(0x0839c), P(0x083a0), P(0x09808), P(0x0980c),
|
||||
P(0x09810), P(0x09814), P(0x0981c), P(0x0982c), P(0x09830),
|
||||
P(0x0983c), P(0x0984c), P(0x0a84c), P(0x09854), P(0x09900),
|
||||
P(0x09904), P(0x09908), P(0x0990c), P(0x09910), P(0x0991c),
|
||||
P(0x09920), P(0x0a920), P(0x09928), P(0x0992c), P(0x09930),
|
||||
P(0x0a930), P(0x09934), P(0x09938), P(0x0993c), P(0x09948),
|
||||
P(0x0994c), P(0x09954), P(0x09958), P(0x09940), P(0x0c95c),
|
||||
P(0x09970), P(0x09974), P(0x09978), P(0x0997c), P(0x099a0),
|
||||
P(0x099a4), P(0x099a8), P(0x099ac), P(0x099b0), P(0x099b4),
|
||||
P(0x099c4), P(0x099c8), P(0x099cc), P(0x099d0), P(0x099dc),
|
||||
P(0x099e0), P(0x099e4), P(0x099e8), P(0x099ec), P(0x099f0),
|
||||
P(0x099fc), P(0x0a208), P(0x0a210), P(0x0a214), P(0x0a218),
|
||||
P(0x0a220), P(0x0a224), P(0x0a228), P(0x0a22c), P(0x0a234),
|
||||
P(0x0a238), P(0x0a23c), P(0x0a240), P(0x0a244), P(0x0a248),
|
||||
P(0x0a24c), P(0x0a254), P(0x0a258), P(0x0a25c), P(0x0a260),
|
||||
P(0x0a264), P(0x0b264), P(0x0a268), P(0x0a26c), P(0x0b26c),
|
||||
P(0x0d270), P(0x0a278), P(0x0a27c), P(0x0d35c), P(0x0d360),
|
||||
P(0x0d364), P(0x0d368), P(0x0d36c), P(0x0d370), P(0x0d374),
|
||||
P(0x0d378), P(0x0d37c), P(0x0d380), P(0x0d384), P(0x0a388),
|
||||
P(0x0a38c), P(0x0a390), P(0x0a394), P(0x0a398), P(0x0b398),
|
||||
P(0x0a39c), P(0x0a3c8), P(0x0a3cc), P(0x0a3d0), P(0x0a3d4),
|
||||
P(0x0a3dc), P(0x0a3e0), P(0x0a3e4), P(0x0a3e8), P(0x0a3ec),
|
||||
P(0x0a3f0), P(0x0a3f4), P(0x0b3f4), P(0x0a7d8), P(0x07800),
|
||||
P(0x07804), P(0x07808), P(0x0780c), P(0x07810), P(0x07814),
|
||||
P(0x07818), P(0x0781c), P(0x07820), P(0x07824), P(0x07828),
|
||||
P(0x0782c), P(0x07830), P(0x07834), P(0x07838), P(0x0783c),
|
||||
P(0x07840), P(0x07844), P(0x07848), P(0x07850), P(0x07854),
|
||||
P(0x07858), P(0x0785c), P(0x07860), P(0x07864), P(0x07868),
|
||||
P(0x0786c), P(0x07870), P(0x07874), P(0x07878), P(0x0787c),
|
||||
P(0x07880), P(0x07884), P(0x07888), P(0x0788c), P(0x07890),
|
||||
P(0x07894), P(0x07898), P(0x0789c), P(0x078a0), P(0x078a4),
|
||||
P(0x078a8), P(0x078ac), P(0x078b0), P(0x078b4), P(0x078b8)
|
||||
};
|
||||
|
||||
static const uint32_t ar9287_1_1_cm_vals[] = {
|
||||
0x00000000, 0x00020015, 0x00000005, 0x00000000, 0x00000008,
|
||||
0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
|
||||
0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
|
||||
0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000002, 0x00000002, 0x0000001f, 0x00000000,
|
||||
0x00000000, 0x00000033, 0x00000000, 0x00000002, 0x000004c2,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000700, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x40000000, 0x00000000, 0x00000000,
|
||||
0x000fc78f, 0x0000000f, 0x00000000, 0x00000000, 0x2a80001a,
|
||||
0x05dc01e0, 0x1f402710, 0x01f40000, 0x00001e00, 0x00000000,
|
||||
0x00400000, 0xffffffff, 0x0000ffff, 0x003f3f3f, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00020000, 0x00020000,
|
||||
0x00000001, 0x00000052, 0x00000000, 0x00000168, 0x000100aa,
|
||||
0x00003210, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000,
|
||||
0x00000000, 0x18487320, 0xfaa4fa50, 0x00000100, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00100000,
|
||||
0x0010f400, 0x00000100, 0x0001e800, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x400000ff, 0x00080922, 0x88a00010, 0x00000000,
|
||||
0x40000000, 0x003e4180, 0x00000000, 0x0000002c, 0x0000002c,
|
||||
0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000040,
|
||||
0x00000000, 0x00000000, 0x00000007, 0x00000302, 0x00000e00,
|
||||
0x00ff0000, 0x00000000, 0x000107ff, 0x01c81043, 0xffffffff,
|
||||
0xffffffff, 0x00000000, 0x00000000, 0x000000ff, 0x00000000,
|
||||
0x00000000, 0xffffffff, 0xffffffff, 0x0fffffff, 0x0fffffff,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xafe68e30,
|
||||
0xfd14e000, 0x9c0a9f6b, 0x00000000, 0x0000a000, 0x00000000,
|
||||
0x00200400, 0x0040233c, 0x0040233c, 0x00000044, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x10002310, 0x10000fff,
|
||||
0x04900000, 0x04900000, 0x00000001, 0x00000004, 0x00000000,
|
||||
0x00000000, 0x1e1f2022, 0x0a0b0c0d, 0x00000000, 0x9280c00a,
|
||||
0x00020028, 0x5f3ca3de, 0x0108ecff, 0x14750604, 0x004b6a8e,
|
||||
0x990bb514, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
|
||||
0x00000001, 0x201fff00, 0x0c6f0000, 0x03051000, 0x00000820,
|
||||
0x06336f77, 0x6af6532f, 0x08f186c8, 0x00046384, 0x00000000,
|
||||
0x00000000, 0xaaaaaaaa, 0x3c466478, 0x0cc80caa, 0x00000000,
|
||||
0x00001042, 0x803e4788, 0x4080a333, 0x40206c10, 0x009c4060,
|
||||
0x01834061, 0x00000400, 0x000003b5, 0x233f7180, 0x20202020,
|
||||
0x20202020, 0x13c889af, 0x38490a20, 0x00000000, 0xfffffffc,
|
||||
0x00000000, 0x00000000, 0x0cdbd380, 0x0f0f0f01, 0xdfa91f01,
|
||||
0x00418a11, 0x00418a11, 0x00000000, 0x0e79e5c6, 0x0e79e5c6,
|
||||
0x00820820, 0x1ce739ce, 0x050701ce, 0x07ffffef, 0x0fffffe7,
|
||||
0x17ffffe5, 0x1fffffe4, 0x37ffffe3, 0x3fffffe3, 0x57ffffe3,
|
||||
0x5fffffe2, 0x7fffffe2, 0x7f3c7bba, 0xf3307ff0, 0x0c000000,
|
||||
0x20202020, 0x20202020, 0x1ce739ce, 0x000001ce, 0x000001ce,
|
||||
0x00000001, 0x00000246, 0x20202020, 0x20202020, 0x20202020,
|
||||
0x1ce739ce, 0x000001ce, 0x00000000, 0x18c43433, 0x00f70081,
|
||||
0x01036a1e, 0x00000000, 0x00000000, 0x000003f1, 0x00000800,
|
||||
0x6c35ffd2, 0x6db6c000, 0x6db6cb30, 0x6db6cb6c, 0x0501e200,
|
||||
0x0094128d, 0x976ee392, 0xf75ff6fc, 0x00040000, 0xdb003012,
|
||||
0x04924914, 0x21084210, 0x00140000, 0x0e4548d8, 0x54214514,
|
||||
0x02025830, 0x71c0d388, 0x934934a8, 0x00000000, 0x00000800,
|
||||
0x6c35ffd2, 0x6db6c000, 0x6db6cb30, 0x6db6cb6c, 0x0501e200,
|
||||
0x0094128d, 0x976ee392, 0xf75ff6fc, 0x00040000, 0xdb003012,
|
||||
0x04924914, 0x21084210, 0x001b6db0, 0x00376b63, 0x06db6db6,
|
||||
0x006d8000, 0x48100000, 0x00000000, 0x08000000, 0x0007ffd8,
|
||||
0x0007ffd8, 0x001c0020, 0x00060aeb, 0x40008080, 0x2a850160
|
||||
};
|
||||
|
||||
static const struct athn_ini ar9287_1_1_ini = {
|
||||
.nregs = __arraycount(ar9287_1_1_regs),
|
||||
.regs = ar9287_1_1_regs,
|
||||
.vals_5g20 = NULL, /* 2GHz only. */
|
||||
#ifndef IEEE80211_NO_HT
|
||||
.vals_5g40 = NULL, /* 2GHz only. */
|
||||
.vals_2g40 = ar9287_1_1_vals_2g40,
|
||||
#endif
|
||||
.vals_2g20 = ar9287_1_1_vals_2g20,
|
||||
.ncmregs = __arraycount(ar9287_1_1_cm_regs),
|
||||
.cmregs = ar9287_1_1_cm_regs,
|
||||
.cmvals = ar9287_1_1_cm_vals
|
||||
};
|
||||
|
||||
/*
|
||||
* AR9287 1.1 Tx gains.
|
||||
*/
|
||||
static const uint16_t ar9287_1_1_tx_gain_regs[] = {
|
||||
P(0x0a300), P(0x0a304), P(0x0a308), P(0x0a30c), P(0x0a310),
|
||||
P(0x0a314), P(0x0a318), P(0x0a31c), P(0x0a320), P(0x0a324),
|
||||
P(0x0a328), P(0x0a32c), P(0x0a330), P(0x0a334), P(0x0a338),
|
||||
P(0x0a33c), P(0x0a340), P(0x0a344), P(0x0a348), P(0x0a34c),
|
||||
P(0x0a350), P(0x0a354), P(0x0a780), P(0x0a784), P(0x0a788),
|
||||
P(0x0a78c), P(0x0a790), P(0x0a794), P(0x0a798), P(0x0a79c),
|
||||
P(0x0a7a0), P(0x0a7a4), P(0x0a7a8), P(0x0a7ac), P(0x0a7b0),
|
||||
P(0x0a7b4), P(0x0a7b8), P(0x0a7bc), P(0x0a7c0), P(0x0a7c4),
|
||||
P(0x0a7c8), P(0x0a7cc), P(0x0a7d0), P(0x0a7d4), P(0x0a274)
|
||||
};
|
||||
|
||||
static const uint32_t ar9287_1_1_tx_gain_vals_2g[] = {
|
||||
0x00000000, 0x00004002, 0x00008004, 0x0000c00a, 0x0001000c,
|
||||
0x0001420b, 0x0001824a, 0x0001c44a, 0x0002064a, 0x0002484a,
|
||||
0x00028a4a, 0x0002cc4a, 0x00030e4a, 0x00034e8a, 0x00038e8c,
|
||||
0x0003cecc, 0x00040ed4, 0x00044edc, 0x00048ede, 0x0004cf1e,
|
||||
0x00050f5e, 0x00054f9e, 0x00000062, 0x00004064, 0x000080a4,
|
||||
0x0000c0aa, 0x000100ac, 0x000140b4, 0x000180f4, 0x0001c134,
|
||||
0x00020174, 0x0002417c, 0x0002817e, 0x0002c1be, 0x000301fe,
|
||||
0x000301fe, 0x000301fe, 0x000301fe, 0x000301fe, 0x000301fe,
|
||||
0x000301fe, 0x000301fe, 0x000301fe, 0x000301fe, 0x0a1aa000
|
||||
};
|
||||
|
||||
static const struct athn_gain ar9287_1_1_tx_gain = {
|
||||
__arraycount(ar9287_1_1_tx_gain_regs),
|
||||
ar9287_1_1_tx_gain_regs,
|
||||
NULL, /* 2GHz only. */
|
||||
ar9287_1_1_tx_gain_vals_2g
|
||||
};
|
||||
|
||||
/*
|
||||
* AR9287 1.1 Rx gains.
|
||||
*/
|
||||
static const uint16_t ar9287_1_1_rx_gain_regs[] = {
|
||||
P(0x09a00), P(0x09a04), P(0x09a08), P(0x09a0c), P(0x09a10),
|
||||
P(0x09a14), P(0x09a18), P(0x09a1c), P(0x09a20), P(0x09a24),
|
||||
P(0x09a28), P(0x09a2c), P(0x09a30), P(0x09a34), P(0x09a38),
|
||||
P(0x09a3c), P(0x09a40), P(0x09a44), P(0x09a48), P(0x09a4c),
|
||||
P(0x09a50), P(0x09a54), P(0x09a58), P(0x09a5c), P(0x09a60),
|
||||
P(0x09a64), P(0x09a68), P(0x09a6c), P(0x09a70), P(0x09a74),
|
||||
P(0x09a78), P(0x09a7c), P(0x09a80), P(0x09a84), P(0x09a88),
|
||||
P(0x09a8c), P(0x09a90), P(0x09a94), P(0x09a98), P(0x09a9c),
|
||||
P(0x09aa0), P(0x09aa4), P(0x09aa8), P(0x09aac), P(0x09ab0),
|
||||
P(0x09ab4), P(0x09ab8), P(0x09abc), P(0x09ac0), P(0x09ac4),
|
||||
P(0x09ac8), P(0x09acc), P(0x09ad0), P(0x09ad4), P(0x09ad8),
|
||||
P(0x09adc), P(0x09ae0), P(0x09ae4), P(0x09ae8), P(0x09aec),
|
||||
P(0x09af0), P(0x09af4), P(0x09af8), P(0x09afc), P(0x09b00),
|
||||
P(0x09b04), P(0x09b08), P(0x09b0c), P(0x09b10), P(0x09b14),
|
||||
P(0x09b18), P(0x09b1c), P(0x09b20), P(0x09b24), P(0x09b28),
|
||||
P(0x09b2c), P(0x09b30), P(0x09b34), P(0x09b38), P(0x09b3c),
|
||||
P(0x09b40), P(0x09b44), P(0x09b48), P(0x09b4c), P(0x09b50),
|
||||
P(0x09b54), P(0x09b58), P(0x09b5c), P(0x09b60), P(0x09b64),
|
||||
P(0x09b68), P(0x09b6c), P(0x09b70), P(0x09b74), P(0x09b78),
|
||||
P(0x09b7c), P(0x09b80), P(0x09b84), P(0x09b88), P(0x09b8c),
|
||||
P(0x09b90), P(0x09b94), P(0x09b98), P(0x09b9c), P(0x09ba0),
|
||||
P(0x09ba4), P(0x09ba8), P(0x09bac), P(0x09bb0), P(0x09bb4),
|
||||
P(0x09bb8), P(0x09bbc), P(0x09bc0), P(0x09bc4), P(0x09bc8),
|
||||
P(0x09bcc), P(0x09bd0), P(0x09bd4), P(0x09bd8), P(0x09bdc),
|
||||
P(0x09be0), P(0x09be4), P(0x09be8), P(0x09bec), P(0x09bf0),
|
||||
P(0x09bf4), P(0x09bf8), P(0x09bfc), P(0x0aa00), P(0x0aa04),
|
||||
P(0x0aa08), P(0x0aa0c), P(0x0aa10), P(0x0aa14), P(0x0aa18),
|
||||
P(0x0aa1c), P(0x0aa20), P(0x0aa24), P(0x0aa28), P(0x0aa2c),
|
||||
P(0x0aa30), P(0x0aa34), P(0x0aa38), P(0x0aa3c), P(0x0aa40),
|
||||
P(0x0aa44), P(0x0aa48), P(0x0aa4c), P(0x0aa50), P(0x0aa54),
|
||||
P(0x0aa58), P(0x0aa5c), P(0x0aa60), P(0x0aa64), P(0x0aa68),
|
||||
P(0x0aa6c), P(0x0aa70), P(0x0aa74), P(0x0aa78), P(0x0aa7c),
|
||||
P(0x0aa80), P(0x0aa84), P(0x0aa88), P(0x0aa8c), P(0x0aa90),
|
||||
P(0x0aa94), P(0x0aa98), P(0x0aa9c), P(0x0aaa0), P(0x0aaa4),
|
||||
P(0x0aaa8), P(0x0aaac), P(0x0aab0), P(0x0aab4), P(0x0aab8),
|
||||
P(0x0aabc), P(0x0aac0), P(0x0aac4), P(0x0aac8), P(0x0aacc),
|
||||
P(0x0aad0), P(0x0aad4), P(0x0aad8), P(0x0aadc), P(0x0aae0),
|
||||
P(0x0aae4), P(0x0aae8), P(0x0aaec), P(0x0aaf0), P(0x0aaf4),
|
||||
P(0x0aaf8), P(0x0aafc), P(0x0ab00), P(0x0ab04), P(0x0ab08),
|
||||
P(0x0ab0c), P(0x0ab10), P(0x0ab14), P(0x0ab18), P(0x0ab1c),
|
||||
P(0x0ab20), P(0x0ab24), P(0x0ab28), P(0x0ab2c), P(0x0ab30),
|
||||
P(0x0ab34), P(0x0ab38), P(0x0ab3c), P(0x0ab40), P(0x0ab44),
|
||||
P(0x0ab48), P(0x0ab4c), P(0x0ab50), P(0x0ab54), P(0x0ab58),
|
||||
P(0x0ab5c), P(0x0ab60), P(0x0ab64), P(0x0ab68), P(0x0ab6c),
|
||||
P(0x0ab70), P(0x0ab74), P(0x0ab78), P(0x0ab7c), P(0x0ab80),
|
||||
P(0x0ab84), P(0x0ab88), P(0x0ab8c), P(0x0ab90), P(0x0ab94),
|
||||
P(0x0ab98), P(0x0ab9c), P(0x0aba0), P(0x0aba4), P(0x0aba8),
|
||||
P(0x0abac), P(0x0abb0), P(0x0abb4), P(0x0abb8), P(0x0abbc),
|
||||
P(0x0abc0), P(0x0abc4), P(0x0abc8), P(0x0abcc), P(0x0abd0),
|
||||
P(0x0abd4), P(0x0abd8), P(0x0abdc), P(0x0abe0), P(0x0abe4),
|
||||
P(0x0abe8), P(0x0abec), P(0x0abf0), P(0x0abf4), P(0x0abf8),
|
||||
P(0x0abfc), P(0x09848), P(0x0a848)
|
||||
};
|
||||
|
||||
static const uint32_t ar9287_1_1_rx_gain_vals_2g[] = {
|
||||
0x0000a120, 0x0000a124, 0x0000a128, 0x0000a12c, 0x0000a130,
|
||||
0x0000a194, 0x0000a198, 0x0000a20c, 0x0000a210, 0x0000a284,
|
||||
0x0000a288, 0x0000a28c, 0x0000a290, 0x0000a294, 0x0000a2a0,
|
||||
0x0000a2a4, 0x0000a2a8, 0x0000a2ac, 0x0000a2b0, 0x0000a2b4,
|
||||
0x0000a2b8, 0x0000a2c4, 0x0000a708, 0x0000a70c, 0x0000a710,
|
||||
0x0000ab04, 0x0000ab08, 0x0000ab0c, 0x0000ab10, 0x0000ab14,
|
||||
0x0000ab18, 0x0000ab8c, 0x0000ab90, 0x0000ab94, 0x0000ab98,
|
||||
0x0000aba4, 0x0000aba8, 0x0000cb04, 0x0000cb08, 0x0000cb0c,
|
||||
0x0000cb10, 0x0000cb14, 0x0000cb18, 0x0000cb8c, 0x0000cb90,
|
||||
0x0000cf18, 0x0000cf24, 0x0000cf28, 0x0000d314, 0x0000d318,
|
||||
0x0000d38c, 0x0000d390, 0x0000d394, 0x0000d398, 0x0000d3a4,
|
||||
0x0000d3a8, 0x0000d3ac, 0x0000d3b0, 0x0000f380, 0x0000f384,
|
||||
0x0000f388, 0x0000f710, 0x0000f714, 0x0000f718, 0x0000fb10,
|
||||
0x0000fb14, 0x0000fb18, 0x0000fb8c, 0x0000fb90, 0x0000fb94,
|
||||
0x0000ff8c, 0x0000ff90, 0x0000ff94, 0x0000ffa0, 0x0000ffa4,
|
||||
0x0000ffa8, 0x0000ffac, 0x0000ffb0, 0x0000ffb4, 0x0000ffa1,
|
||||
0x0000ffa5, 0x0000ffa9, 0x0000ffad, 0x0000ffb1, 0x0000ffb5,
|
||||
0x0000ffb9, 0x0000ffc5, 0x0000ffc9, 0x0000ffcd, 0x0000ffd1,
|
||||
0x0000ffd5, 0x0000ffc2, 0x0000ffc6, 0x0000ffca, 0x0000ffce,
|
||||
0x0000ffd2, 0x0000ffd6, 0x0000ffda, 0x0000ffc7, 0x0000ffcb,
|
||||
0x0000ffcf, 0x0000ffd3, 0x0000ffd7, 0x0000ffdb, 0x0000ffdb,
|
||||
0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
|
||||
0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
|
||||
0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
|
||||
0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
|
||||
0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000a120, 0x0000a124,
|
||||
0x0000a128, 0x0000a12c, 0x0000a130, 0x0000a194, 0x0000a198,
|
||||
0x0000a20c, 0x0000a210, 0x0000a284, 0x0000a288, 0x0000a28c,
|
||||
0x0000a290, 0x0000a294, 0x0000a2a0, 0x0000a2a4, 0x0000a2a8,
|
||||
0x0000a2ac, 0x0000a2b0, 0x0000a2b4, 0x0000a2b8, 0x0000a2c4,
|
||||
0x0000a708, 0x0000a70c, 0x0000a710, 0x0000ab04, 0x0000ab08,
|
||||
0x0000ab0c, 0x0000ab10, 0x0000ab14, 0x0000ab18, 0x0000ab8c,
|
||||
0x0000ab90, 0x0000ab94, 0x0000ab98, 0x0000aba4, 0x0000aba8,
|
||||
0x0000cb04, 0x0000cb08, 0x0000cb0c, 0x0000cb10, 0x0000cb14,
|
||||
0x0000cb18, 0x0000cb8c, 0x0000cb90, 0x0000cf18, 0x0000cf24,
|
||||
0x0000cf28, 0x0000d314, 0x0000d318, 0x0000d38c, 0x0000d390,
|
||||
0x0000d394, 0x0000d398, 0x0000d3a4, 0x0000d3a8, 0x0000d3ac,
|
||||
0x0000d3b0, 0x0000f380, 0x0000f384, 0x0000f388, 0x0000f710,
|
||||
0x0000f714, 0x0000f718, 0x0000fb10, 0x0000fb14, 0x0000fb18,
|
||||
0x0000fb8c, 0x0000fb90, 0x0000fb94, 0x0000ff8c, 0x0000ff90,
|
||||
0x0000ff94, 0x0000ffa0, 0x0000ffa4, 0x0000ffa8, 0x0000ffac,
|
||||
0x0000ffb0, 0x0000ffb4, 0x0000ffa1, 0x0000ffa5, 0x0000ffa9,
|
||||
0x0000ffad, 0x0000ffb1, 0x0000ffb5, 0x0000ffb9, 0x0000ffc5,
|
||||
0x0000ffc9, 0x0000ffcd, 0x0000ffd1, 0x0000ffd5, 0x0000ffc2,
|
||||
0x0000ffc6, 0x0000ffca, 0x0000ffce, 0x0000ffd2, 0x0000ffd6,
|
||||
0x0000ffda, 0x0000ffc7, 0x0000ffcb, 0x0000ffcf, 0x0000ffd3,
|
||||
0x0000ffd7, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
|
||||
0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
|
||||
0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
|
||||
0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
|
||||
0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
|
||||
0x0000ffdb, 0x00001067, 0x00001067
|
||||
};
|
||||
|
||||
static const struct athn_gain ar9287_1_1_rx_gain = {
|
||||
__arraycount(ar9287_1_1_rx_gain_regs),
|
||||
ar9287_1_1_rx_gain_regs,
|
||||
NULL, /* 2GHz only. */
|
||||
ar9287_1_1_rx_gain_vals_2g
|
||||
};
|
||||
|
||||
#endif /* _ARN9287REG_H_ */
|
917
sys/dev/ic/arn9380.c
Normal file
917
sys/dev/ic/arn9380.c
Normal file
@ -0,0 +1,917 @@
|
||||
/* $NetBSD: arn9380.c,v 1.1 2013/03/30 02:53:02 christos Exp $ */
|
||||
/* $OpenBSD: ar9380.c,v 1.17 2012/10/20 09:54:20 stsp Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2010 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Driver for Atheros 802.11a/g/n chipsets.
|
||||
* Routines for AR9380 and AR9485 chipsets.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: arn9380.c,v 1.1 2013/03/30 02:53:02 christos Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_amrr.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/ic/athnreg.h>
|
||||
#include <dev/ic/athnvar.h>
|
||||
|
||||
#include <dev/ic/arn9003reg.h>
|
||||
#include <dev/ic/arn9380reg.h>
|
||||
|
||||
#include <dev/ic/arn9003.h>
|
||||
#include <dev/ic/arn9380.h>
|
||||
|
||||
#define Static static
|
||||
|
||||
Static void ar9380_get_correction(struct athn_softc *,
|
||||
struct ieee80211_channel *, int, int *, int *);
|
||||
Static void ar9380_get_paprd_masks(struct athn_softc *,
|
||||
struct ieee80211_channel *, uint32_t *, uint32_t *);
|
||||
Static const uint8_t *
|
||||
ar9380_get_rom_template(struct athn_softc *, uint8_t);
|
||||
Static void ar9380_init_from_rom(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9380_set_correction(struct athn_softc *,
|
||||
struct ieee80211_channel *);
|
||||
Static int ar9380_set_synth(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9380_set_txpower(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9380_setup(struct athn_softc *);
|
||||
Static void ar9380_spur_mitigate(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9380_spur_mitigate_cck(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9380_spur_mitigate_ofdm(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
Static void ar9380_swap_rom(struct athn_softc *);
|
||||
|
||||
Static void ar9485_init_swreg(struct athn_softc *);
|
||||
#define ar9485_pmu_read AR_READ
|
||||
Static int ar9485_pmu_write(struct athn_softc *, uint32_t, uint32_t);
|
||||
|
||||
#ifdef notused
|
||||
Static void ar9380_init_swreg(struct athn_softc *);
|
||||
#endif /* notused */
|
||||
|
||||
PUBLIC int
|
||||
ar9380_attach(struct athn_softc *sc)
|
||||
{
|
||||
|
||||
sc->sc_ngpiopins = 17;
|
||||
sc->sc_ops.setup = ar9380_setup;
|
||||
sc->sc_ops.get_rom_template = ar9380_get_rom_template;
|
||||
sc->sc_ops.swap_rom = ar9380_swap_rom;
|
||||
sc->sc_ops.init_from_rom = ar9380_init_from_rom;
|
||||
sc->sc_ops.set_txpower = ar9380_set_txpower;
|
||||
sc->sc_ops.set_synth = ar9380_set_synth;
|
||||
sc->sc_ops.spur_mitigate = ar9380_spur_mitigate;
|
||||
sc->sc_ops.get_paprd_masks = ar9380_get_paprd_masks;
|
||||
sc->sc_cca_min_2g = AR9380_PHY_CCA_MIN_GOOD_VAL_2GHZ;
|
||||
sc->sc_cca_max_2g = AR9380_PHY_CCA_MAX_GOOD_VAL_2GHZ;
|
||||
sc->sc_cca_min_5g = AR9380_PHY_CCA_MIN_GOOD_VAL_5GHZ;
|
||||
sc->sc_cca_max_5g = AR9380_PHY_CCA_MAX_GOOD_VAL_5GHZ;
|
||||
if (AR_SREV_9485(sc)) {
|
||||
sc->sc_ini = &ar9485_1_1_ini;
|
||||
sc->sc_serdes = &ar9485_1_1_serdes;
|
||||
}
|
||||
else {
|
||||
sc->sc_ini = &ar9380_2_2_ini;
|
||||
sc->sc_serdes = &ar9380_2_2_serdes;
|
||||
}
|
||||
|
||||
return ar9003_attach(sc);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9380_setup(struct athn_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ar9380_eeprom *eep = sc->sc_eep;
|
||||
struct ar9380_base_eep_hdr *base = &eep->baseEepHeader;
|
||||
uint8_t type;
|
||||
|
||||
if (base->opFlags & AR_OPFLAGS_11A)
|
||||
sc->sc_flags |= ATHN_FLAG_11A;
|
||||
if (base->opFlags & AR_OPFLAGS_11G)
|
||||
sc->sc_flags |= ATHN_FLAG_11G;
|
||||
if (base->opFlags & AR_OPFLAGS_11N)
|
||||
sc->sc_flags |= ATHN_FLAG_11N;
|
||||
|
||||
IEEE80211_ADDR_COPY(ic->ic_myaddr, eep->macAddr);
|
||||
sc->sc_led_pin = base->wlanLedGpio;
|
||||
|
||||
/* Check if we have a hardware radio switch. */
|
||||
if (base->rfSilent & AR_EEP_RFSILENT_ENABLED) {
|
||||
sc->sc_flags |= ATHN_FLAG_RFSILENT;
|
||||
/* Get GPIO pin used by hardware radio switch. */
|
||||
sc->sc_rfsilent_pin = MS(base->rfSilent,
|
||||
AR_EEP_RFSILENT_GPIO_SEL);
|
||||
/* Get polarity of hardware radio switch. */
|
||||
if (base->rfSilent & AR_EEP_RFSILENT_POLARITY)
|
||||
sc->sc_flags |= ATHN_FLAG_RFSILENT_REVERSED;
|
||||
}
|
||||
|
||||
/* Set the number of HW key cache entries. */
|
||||
sc->sc_kc_entries = AR_KEYTABLE_SIZE;
|
||||
|
||||
sc->sc_txchainmask = MS(base->txrxMask, AR_EEP_TX_MASK);
|
||||
sc->sc_rxchainmask = MS(base->txrxMask, AR_EEP_RX_MASK);
|
||||
|
||||
/* Fast PLL clock is always supported. */
|
||||
sc->sc_flags |= ATHN_FLAG_FAST_PLL_CLOCK;
|
||||
|
||||
/* Enable PA predistortion if supported. */
|
||||
if (base->featureEnable & AR_EEP_PAPRD)
|
||||
sc->sc_flags |= ATHN_FLAG_PAPRD;
|
||||
/*
|
||||
* Some 3-stream chips may exceed the PCIe power requirements,
|
||||
* requiring to reduce the number of Tx chains in some cases.
|
||||
*/
|
||||
if ((base->miscConfiguration & AR_EEP_CHAIN_MASK_REDUCE) &&
|
||||
sc->sc_txchainmask == 0x7)
|
||||
sc->sc_flags |= ATHN_FLAG_3TREDUCE_CHAIN;
|
||||
|
||||
/* Select initialization values based on ROM. */
|
||||
type = MS(eep->baseEepHeader.txrxgain, AR_EEP_RX_GAIN);
|
||||
if (!AR_SREV_9485(sc)) {
|
||||
if (type == AR_EEP_RX_GAIN_WO_XLNA)
|
||||
sc->sc_rx_gain = &ar9380_2_2_rx_gain_wo_xlna;
|
||||
else
|
||||
sc->sc_rx_gain = &ar9380_2_2_rx_gain;
|
||||
}
|
||||
else
|
||||
sc->sc_rx_gain = &ar9485_1_1_rx_gain;
|
||||
|
||||
/* Select initialization values based on ROM. */
|
||||
type = MS(eep->baseEepHeader.txrxgain, AR_EEP_TX_GAIN);
|
||||
if (!AR_SREV_9485(sc)) {
|
||||
if (type == AR_EEP_TX_GAIN_HIGH_OB_DB)
|
||||
sc->sc_tx_gain = &ar9380_2_2_tx_gain_high_ob_db;
|
||||
else if (type == AR_EEP_TX_GAIN_LOW_OB_DB)
|
||||
sc->sc_tx_gain = &ar9380_2_2_tx_gain_low_ob_db;
|
||||
else if (type == AR_EEP_TX_GAIN_HIGH_POWER)
|
||||
sc->sc_tx_gain = &ar9380_2_2_tx_gain_high_power;
|
||||
else
|
||||
sc->sc_tx_gain = &ar9380_2_2_tx_gain;
|
||||
}
|
||||
else
|
||||
sc->sc_tx_gain = &ar9485_1_1_tx_gain;
|
||||
}
|
||||
|
||||
Static const uint8_t *
|
||||
ar9380_get_rom_template(struct athn_softc *sc, uint8_t ref)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* Retrieve template ROM image for given reference. */
|
||||
for (i = 0; i < __arraycount(ar9380_rom_templates); i++)
|
||||
if (ar9380_rom_templates[i][1] == ref)
|
||||
return ar9380_rom_templates[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9380_swap_rom(struct athn_softc *sc)
|
||||
{
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
struct ar9380_eeprom *eep = sc->sc_eep;
|
||||
struct ar9380_base_eep_hdr *base = &eep->baseEepHeader;
|
||||
struct ar9380_modal_eep_header *modal;
|
||||
int i;
|
||||
|
||||
base->regDmn[0] = swap16(base->regDmn[0]);
|
||||
base->regDmn[1] = swap16(base->regDmn[1]);
|
||||
base->swreg = swap32(base->swreg);
|
||||
|
||||
modal = &eep->modalHeader2G;
|
||||
modal->antCtrlCommon = swap32(modal->antCtrlCommon);
|
||||
modal->antCtrlCommon2 = swap32(modal->antCtrlCommon2);
|
||||
modal->papdRateMaskHt20 = swap32(modal->papdRateMaskHt20);
|
||||
modal->papdRateMaskHt40 = swap32(modal->papdRateMaskHt40);
|
||||
for (i = 0; i < AR9380_MAX_CHAINS; i++)
|
||||
modal->antCtrlChain[i] = swap16(modal->antCtrlChain[i]);
|
||||
|
||||
modal = &eep->modalHeader5G;
|
||||
modal->antCtrlCommon = swap32(modal->antCtrlCommon);
|
||||
modal->antCtrlCommon2 = swap32(modal->antCtrlCommon2);
|
||||
modal->papdRateMaskHt20 = swap32(modal->papdRateMaskHt20);
|
||||
modal->papdRateMaskHt40 = swap32(modal->papdRateMaskHt40);
|
||||
for (i = 0; i < AR9380_MAX_CHAINS; i++)
|
||||
modal->antCtrlChain[i] = swap16(modal->antCtrlChain[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9380_get_paprd_masks(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
uint32_t *ht20mask, uint32_t *ht40mask)
|
||||
{
|
||||
const struct ar9380_eeprom *eep = sc->sc_eep;
|
||||
const struct ar9380_modal_eep_header *modal;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
modal = &eep->modalHeader2G;
|
||||
else
|
||||
modal = &eep->modalHeader5G;
|
||||
*ht20mask = modal->papdRateMaskHt20;
|
||||
*ht40mask = modal->papdRateMaskHt40;
|
||||
}
|
||||
|
||||
Static int
|
||||
ar9380_set_synth(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
uint32_t freq = c->ic_freq;
|
||||
uint32_t chansel, phy;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
if (AR_SREV_9485(sc))
|
||||
chansel = ((freq << 16) - 215) / 15;
|
||||
else
|
||||
chansel = (freq << 16) / 15;
|
||||
AR_WRITE(sc, AR_PHY_SYNTH_CONTROL, AR9380_BMODE);
|
||||
}
|
||||
else {
|
||||
chansel = (freq << 15) / 15;
|
||||
chansel >>= 1;
|
||||
AR_WRITE(sc, AR_PHY_SYNTH_CONTROL, 0);
|
||||
}
|
||||
|
||||
/* Enable Long Shift Select for synthesizer. */
|
||||
AR_SETBITS(sc, AR_PHY_65NM_CH0_SYNTH4,
|
||||
AR_PHY_SYNTH4_LONG_SHIFT_SELECT);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
|
||||
/* Program synthesizer. */
|
||||
phy = (chansel << 2) | AR9380_FRACMODE;
|
||||
DPRINTFN(DBG_RF, sc, "AR_PHY_65NM_CH0_SYNTH7=0x%08x\n", phy);
|
||||
AR_WRITE(sc, AR_PHY_65NM_CH0_SYNTH7, phy);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
/* Toggle Load Synth Channel bit. */
|
||||
AR_WRITE(sc, AR_PHY_65NM_CH0_SYNTH7, phy | AR9380_LOAD_SYNTH);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9380_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
const struct ar9380_eeprom *eep = sc->sc_eep;
|
||||
const struct ar9380_modal_eep_header *modal;
|
||||
uint8_t db, margin, ant_div_ctrl;
|
||||
uint32_t reg;
|
||||
int i, maxchains;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
modal = &eep->modalHeader2G;
|
||||
else
|
||||
modal = &eep->modalHeader5G;
|
||||
|
||||
/* Apply XPA bias level. */
|
||||
if (AR_SREV_9485(sc)) {
|
||||
reg = AR_READ(sc, AR9485_PHY_65NM_CH0_TOP2);
|
||||
reg = RW(reg, AR9485_PHY_65NM_CH0_TOP2_XPABIASLVL,
|
||||
modal->xpaBiasLvl);
|
||||
AR_WRITE(sc, AR9485_PHY_65NM_CH0_TOP2, reg);
|
||||
}
|
||||
else {
|
||||
reg = AR_READ(sc, AR_PHY_65NM_CH0_TOP);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_TOP_XPABIASLVL,
|
||||
modal->xpaBiasLvl & 0x3);
|
||||
AR_WRITE(sc, AR_PHY_65NM_CH0_TOP, reg);
|
||||
reg = AR_READ(sc, AR_PHY_65NM_CH0_THERM);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_THERM_XPABIASLVL_MSB,
|
||||
modal->xpaBiasLvl >> 2);
|
||||
reg |= AR_PHY_65NM_CH0_THERM_XPASHORT2GND;
|
||||
AR_WRITE(sc, AR_PHY_65NM_CH0_THERM, reg);
|
||||
}
|
||||
|
||||
/* Apply antenna control. */
|
||||
reg = AR_READ(sc, AR_PHY_SWITCH_COM);
|
||||
reg = RW(reg, AR_SWITCH_TABLE_COM_ALL, modal->antCtrlCommon);
|
||||
AR_WRITE(sc, AR_PHY_SWITCH_COM, reg);
|
||||
reg = AR_READ(sc, AR_PHY_SWITCH_COM_2);
|
||||
reg = RW(reg, AR_SWITCH_TABLE_COM_2_ALL, modal->antCtrlCommon2);
|
||||
AR_WRITE(sc, AR_PHY_SWITCH_COM_2, reg);
|
||||
|
||||
maxchains = AR_SREV_9485(sc) ? 1 : AR9380_MAX_CHAINS;
|
||||
for (i = 0; i < maxchains; i++) {
|
||||
reg = AR_READ(sc, AR_PHY_SWITCH_CHAIN(i));
|
||||
reg = RW(reg, AR_SWITCH_TABLE_ALL, modal->antCtrlChain[i]);
|
||||
AR_WRITE(sc, AR_PHY_SWITCH_CHAIN(i), reg);
|
||||
}
|
||||
|
||||
if (AR_SREV_9485(sc)) {
|
||||
ant_div_ctrl = eep->base_ext1.ant_div_control;
|
||||
reg = AR_READ(sc, AR_PHY_MC_GAIN_CTRL);
|
||||
reg = RW(reg, AR_PHY_MC_GAIN_CTRL_ANT_DIV_CTRL_ALL,
|
||||
MS(ant_div_ctrl, AR_EEP_ANT_DIV_CTRL_ALL));
|
||||
if (ant_div_ctrl & AR_EEP_ANT_DIV_CTRL_ANT_DIV)
|
||||
reg |= AR_PHY_MC_GAIN_CTRL_ENABLE_ANT_DIV;
|
||||
else
|
||||
reg &= ~AR_PHY_MC_GAIN_CTRL_ENABLE_ANT_DIV;
|
||||
AR_WRITE(sc, AR_PHY_MC_GAIN_CTRL, reg);
|
||||
reg = AR_READ(sc, AR_PHY_CCK_DETECT);
|
||||
if (ant_div_ctrl & AR_EEP_ANT_DIV_CTRL_FAST_DIV)
|
||||
reg |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
|
||||
else
|
||||
reg &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
|
||||
AR_WRITE(sc, AR_PHY_CCK_DETECT, reg);
|
||||
}
|
||||
|
||||
if (eep->baseEepHeader.miscConfiguration & AR_EEP_DRIVE_STRENGTH) {
|
||||
/* Apply drive strength. */
|
||||
reg = AR_READ(sc, AR_PHY_65NM_CH0_BIAS1);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_0, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_1, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_2, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_3, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_4, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_5, 5);
|
||||
AR_WRITE(sc, AR_PHY_65NM_CH0_BIAS1, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_65NM_CH0_BIAS2);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_0, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_1, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_2, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_3, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_4, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_5, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_6, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_7, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_8, 5);
|
||||
AR_WRITE(sc, AR_PHY_65NM_CH0_BIAS2, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_65NM_CH0_BIAS4);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS4_0, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS4_1, 5);
|
||||
reg = RW(reg, AR_PHY_65NM_CH0_BIAS4_2, 5);
|
||||
AR_WRITE(sc, AR_PHY_65NM_CH0_BIAS4, reg);
|
||||
}
|
||||
|
||||
/* Apply attenuation settings. */
|
||||
maxchains = AR_SREV_9485(sc) ? 1 : AR9380_MAX_CHAINS;
|
||||
for (i = 0; i < maxchains; i++) {
|
||||
if (IEEE80211_IS_CHAN_5GHZ(c) &&
|
||||
eep->base_ext2.xatten1DBLow[i] != 0) {
|
||||
if (c->ic_freq <= 5500) {
|
||||
db = athn_interpolate(c->ic_freq,
|
||||
5180, eep->base_ext2.xatten1DBLow[i],
|
||||
5500, modal->xatten1DB[i]);
|
||||
}
|
||||
else {
|
||||
db = athn_interpolate(c->ic_freq,
|
||||
5500, modal->xatten1DB[i],
|
||||
5785, eep->base_ext2.xatten1DBHigh[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
db = modal->xatten1DB[i];
|
||||
if (IEEE80211_IS_CHAN_5GHZ(c) &&
|
||||
eep->base_ext2.xatten1MarginLow[i] != 0) {
|
||||
if (c->ic_freq <= 5500) {
|
||||
margin = athn_interpolate(c->ic_freq,
|
||||
5180, eep->base_ext2.xatten1MarginLow[i],
|
||||
5500, modal->xatten1Margin[i]);
|
||||
}
|
||||
else {
|
||||
margin = athn_interpolate(c->ic_freq,
|
||||
5500, modal->xatten1Margin[i],
|
||||
5785, eep->base_ext2.xatten1MarginHigh[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
margin = modal->xatten1Margin[i];
|
||||
reg = AR_READ(sc, AR_PHY_EXT_ATTEN_CTL(i));
|
||||
reg = RW(reg, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, db);
|
||||
reg = RW(reg, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, margin);
|
||||
AR_WRITE(sc, AR_PHY_EXT_ATTEN_CTL(i), reg);
|
||||
}
|
||||
|
||||
/* Initialize switching regulator. */
|
||||
if (AR_SREV_9485(sc))
|
||||
ar9485_init_swreg(sc);
|
||||
else
|
||||
ar9485_init_swreg(sc);
|
||||
|
||||
/* Apply tuning capabilities. */
|
||||
if (AR_SREV_9485(sc) &&
|
||||
(eep->baseEepHeader.featureEnable & AR_EEP_TUNING_CAPS)) {
|
||||
reg = AR_READ(sc, AR9485_PHY_CH0_XTAL);
|
||||
reg = RW(reg, AR9485_PHY_CH0_XTAL_CAPINDAC,
|
||||
eep->baseEepHeader.params_for_tuning_caps[0]);
|
||||
reg = RW(reg, AR9485_PHY_CH0_XTAL_CAPOUTDAC,
|
||||
eep->baseEepHeader.params_for_tuning_caps[0]);
|
||||
AR_WRITE(sc, AR9485_PHY_CH0_XTAL, reg);
|
||||
}
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
||||
|
||||
#ifdef notused
|
||||
Static void
|
||||
ar9380_init_swreg(struct athn_softc *sc)
|
||||
{
|
||||
const struct ar9380_eeprom *eep = sc->sc_eep;
|
||||
|
||||
if (eep->baseEepHeader.featureEnable & AR_EEP_INTERNAL_REGULATOR) {
|
||||
/* Internal regulator is ON. */
|
||||
AR_CLRBITS(sc, AR_RTC_REG_CONTROL1,
|
||||
AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
|
||||
AR_WRITE(sc, AR_RTC_REG_CONTROL0, eep->baseEepHeader.swreg);
|
||||
AR_SETBITS(sc, AR_RTC_REG_CONTROL1,
|
||||
AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
|
||||
}
|
||||
else
|
||||
AR_SETBITS(sc, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_SWREG_PRD);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
||||
#endif /* notused */
|
||||
|
||||
Static int
|
||||
ar9485_pmu_write(struct athn_softc *sc, uint32_t addr, uint32_t val)
|
||||
{
|
||||
int ntries;
|
||||
|
||||
AR_WRITE(sc, addr, val);
|
||||
/* Wait for write to complete. */
|
||||
for (ntries = 0; ntries < 100; ntries++) {
|
||||
if (AR_READ(sc, addr) == val)
|
||||
return 0;
|
||||
AR_WRITE(sc, addr, val); /* Insist. */
|
||||
AR_WRITE_BARRIER(sc);
|
||||
DELAY(10);
|
||||
}
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9485_init_swreg(struct athn_softc *sc)
|
||||
{
|
||||
const struct ar9380_eeprom *eep = sc->sc_eep;
|
||||
uint32_t reg;
|
||||
|
||||
ar9485_pmu_write(sc, AR_PHY_PMU2,
|
||||
ar9485_pmu_read(sc, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM);
|
||||
|
||||
if (eep->baseEepHeader.featureEnable & AR_EEP_INTERNAL_REGULATOR) {
|
||||
ar9485_pmu_write(sc, AR_PHY_PMU1, 0x131dc17a);
|
||||
|
||||
reg = ar9485_pmu_read(sc, AR_PHY_PMU2);
|
||||
reg = (reg & ~0xffc00000) | 0x10000000;
|
||||
ar9485_pmu_write(sc, AR_PHY_PMU2, reg);
|
||||
}
|
||||
else {
|
||||
ar9485_pmu_write(sc, AR_PHY_PMU1,
|
||||
ar9485_pmu_read(sc, AR_PHY_PMU1) | AR_PHY_PMU1_PWD);
|
||||
}
|
||||
|
||||
ar9485_pmu_write(sc, AR_PHY_PMU2,
|
||||
ar9485_pmu_read(sc, AR_PHY_PMU2) | AR_PHY_PMU2_PGM);
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: It is safe to call this function for 5GHz channels.
|
||||
*/
|
||||
Static void
|
||||
ar9380_spur_mitigate_cck(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
static const int16_t freqs[] = { 2420, 2440, 2464, 2480 };
|
||||
size_t i;
|
||||
int spur, freq;
|
||||
uint32_t reg;
|
||||
|
||||
for (i = 0; i < __arraycount(freqs); i++) {
|
||||
spur = freqs[i] - c->ic_freq;
|
||||
if (abs(spur) < 10) /* +/- 10MHz range. */
|
||||
break;
|
||||
}
|
||||
if (i == __arraycount(freqs)) {
|
||||
/* Disable CCK spur mitigation. */
|
||||
reg = AR_READ(sc, AR_PHY_AGC_CONTROL);
|
||||
reg = RW(reg, AR_PHY_AGC_CONTROL_YCOK_MAX, 0x5);
|
||||
AR_WRITE(sc, AR_PHY_AGC_CONTROL, reg);
|
||||
reg = AR_READ(sc, AR_PHY_CCK_SPUR_MIT);
|
||||
reg = RW(reg, AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, 0);
|
||||
reg &= ~AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT;
|
||||
AR_WRITE(sc, AR_PHY_CCK_SPUR_MIT, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
return;
|
||||
}
|
||||
freq = (spur * 524288) / 11;
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_AGC_CONTROL);
|
||||
reg = RW(reg, AR_PHY_AGC_CONTROL_YCOK_MAX, 0x7);
|
||||
AR_WRITE(sc, AR_PHY_AGC_CONTROL, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_CCK_SPUR_MIT);
|
||||
reg = RW(reg, AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, freq);
|
||||
reg = RW(reg, AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR, 0x7f);
|
||||
reg = RW(reg, AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE, 0x2);
|
||||
reg |= AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT;
|
||||
AR_WRITE(sc, AR_PHY_CCK_SPUR_MIT, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9380_spur_mitigate_ofdm(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
const struct ar9380_eeprom *eep = sc->sc_eep;
|
||||
const uint8_t *spurchans;
|
||||
uint32_t reg;
|
||||
int idx, spur_delta_phase, spur_off, range, i;
|
||||
int freq, spur, spur_freq_sd, spur_subchannel_sd;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
spurchans = eep->modalHeader2G.spurChans;
|
||||
else
|
||||
spurchans = eep->modalHeader5G.spurChans;
|
||||
if (spurchans[0] == 0)
|
||||
return;
|
||||
|
||||
/* Disable OFDM spur mitigation. */
|
||||
AR_CLRBITS(sc, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_FILTER);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TIMING11);
|
||||
reg = RW(reg, AR_PHY_TIMING11_SPUR_FREQ_SD, 0);
|
||||
reg = RW(reg, AR_PHY_TIMING11_SPUR_DELTA_PHASE, 0);
|
||||
reg &= ~AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC;
|
||||
reg &= ~AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR;
|
||||
AR_WRITE(sc, AR_PHY_TIMING11, reg);
|
||||
|
||||
AR_CLRBITS(sc, AR_PHY_SFCORR_EXT,
|
||||
AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD);
|
||||
|
||||
AR_CLRBITS(sc, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_RSSI);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_SPUR_REG);
|
||||
reg = RW(reg, AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0);
|
||||
reg &= ~AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI;
|
||||
reg &= ~AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT;
|
||||
reg &= ~AR_PHY_SPUR_REG_ENABLE_MASK_PPM;
|
||||
AR_WRITE(sc, AR_PHY_SPUR_REG, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
|
||||
freq = c->ic_freq;
|
||||
#ifndef IEEE80211_NO_HT
|
||||
if (extc != NULL) {
|
||||
range = 19; /* +/- 19MHz range. */
|
||||
if (AR_READ(sc, AR_PHY_GEN_CTRL) & AR_PHY_GC_DYN2040_PRI_CH)
|
||||
freq += 10;
|
||||
else
|
||||
freq -= 10;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
range = 10; /* +/- 10MHz range. */
|
||||
for (i = 0; i < AR9380_EEPROM_MODAL_SPURS; i++) {
|
||||
spur = spurchans[i];
|
||||
if (spur == 0)
|
||||
return;
|
||||
/* Convert to frequency. */
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
spur = 2300 + spur;
|
||||
else
|
||||
spur = 4900 + (spur * 5);
|
||||
spur -= freq;
|
||||
if (abs(spur) < range)
|
||||
break;
|
||||
}
|
||||
if (i == AR9380_EEPROM_MODAL_SPURS)
|
||||
return;
|
||||
|
||||
/* Enable OFDM spur mitigation. */
|
||||
#ifndef IEEE80211_NO_HT
|
||||
if (extc != NULL) {
|
||||
spur_delta_phase = (spur * 131072) / 5;
|
||||
reg = AR_READ(sc, AR_PHY_GEN_CTRL);
|
||||
if (spur < 0) {
|
||||
spur_subchannel_sd =
|
||||
(reg & AR_PHY_GC_DYN2040_PRI_CH) == 0;
|
||||
spur_off = spur + 10;
|
||||
}
|
||||
else {
|
||||
spur_subchannel_sd =
|
||||
(reg & AR_PHY_GC_DYN2040_PRI_CH) != 0;
|
||||
spur_off = spur - 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
spur_delta_phase = (spur * 262144) / 5;
|
||||
spur_subchannel_sd = 0;
|
||||
spur_off = spur;
|
||||
}
|
||||
spur_freq_sd = (spur_off * 512) / 11;
|
||||
|
||||
AR_SETBITS(sc, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_FILTER);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TIMING11);
|
||||
reg = RW(reg, AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd);
|
||||
reg = RW(reg, AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase);
|
||||
reg |= AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC;
|
||||
reg |= AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR;
|
||||
AR_WRITE(sc, AR_PHY_TIMING11, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_SFCORR_EXT);
|
||||
if (spur_subchannel_sd)
|
||||
reg |= AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD;
|
||||
else
|
||||
reg &= ~AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD;
|
||||
AR_WRITE(sc, AR_PHY_SFCORR_EXT, reg);
|
||||
|
||||
AR_SETBITS(sc, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_RSSI);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_SPUR_REG);
|
||||
reg = RW(reg, AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff);
|
||||
reg = RW(reg, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, 34);
|
||||
reg |= AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI;
|
||||
if (AR_READ(sc, AR_PHY_MODE) & AR_PHY_MODE_DYNAMIC)
|
||||
reg |= AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT;
|
||||
reg |= AR_PHY_SPUR_REG_ENABLE_MASK_PPM;
|
||||
AR_WRITE(sc, AR_PHY_SPUR_REG, reg);
|
||||
|
||||
idx = (spur * 16) / 5;
|
||||
if (idx < 0)
|
||||
idx--;
|
||||
|
||||
/* Write pilot mask. */
|
||||
AR_SETBITS(sc, AR_PHY_TIMING4,
|
||||
AR_PHY_TIMING4_ENABLE_PILOT_MASK |
|
||||
AR_PHY_TIMING4_ENABLE_CHAN_MASK);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_PILOT_SPUR_MASK);
|
||||
reg = RW(reg, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, idx);
|
||||
reg = RW(reg, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0x0c);
|
||||
AR_WRITE(sc, AR_PHY_PILOT_SPUR_MASK, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_SPUR_MASK_A);
|
||||
reg = RW(reg, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, idx);
|
||||
reg = RW(reg, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0xa0);
|
||||
AR_WRITE(sc, AR_PHY_SPUR_MASK_A, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_CHAN_SPUR_MASK);
|
||||
reg = RW(reg, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, idx);
|
||||
reg = RW(reg, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0x0c);
|
||||
AR_WRITE(sc, AR_PHY_CHAN_SPUR_MASK, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9380_spur_mitigate(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
|
||||
/* NB: We call spur_mitigate_cck for 5GHz too, just to disable it. */
|
||||
ar9380_spur_mitigate_cck(sc, c, extc);
|
||||
ar9380_spur_mitigate_ofdm(sc, c, extc);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9380_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
const struct ar9380_eeprom *eep = sc->sc_eep;
|
||||
uint8_t tpow_cck[4], tpow_ofdm[4];
|
||||
uint8_t tpow_ht20[14], tpow_ht40[14];
|
||||
int16_t power[ATHN_POWER_COUNT];
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
/* Get CCK target powers. */
|
||||
ar9003_get_lg_tpow(sc, c, AR_CTL_11B,
|
||||
eep->calTargetFbinCck, eep->calTargetPowerCck,
|
||||
AR9380_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
|
||||
|
||||
/* Get OFDM target powers. */
|
||||
ar9003_get_lg_tpow(sc, c, AR_CTL_11G,
|
||||
eep->calTargetFbin2G, eep->calTargetPower2G,
|
||||
AR9380_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
|
||||
|
||||
/* Get HT-20 target powers. */
|
||||
ar9003_get_ht_tpow(sc, c, AR_CTL_2GHT20,
|
||||
eep->calTargetFbin2GHT20, eep->calTargetPower2GHT20,
|
||||
AR9380_NUM_2G_20_TARGET_POWERS, tpow_ht20);
|
||||
|
||||
if (extc != NULL) {
|
||||
/* Get HT-40 target powers. */
|
||||
ar9003_get_ht_tpow(sc, c, AR_CTL_2GHT40,
|
||||
eep->calTargetFbin2GHT40,
|
||||
eep->calTargetPower2GHT40,
|
||||
AR9380_NUM_2G_40_TARGET_POWERS, tpow_ht40);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Get OFDM target powers. */
|
||||
ar9003_get_lg_tpow(sc, c, AR_CTL_11A,
|
||||
eep->calTargetFbin5G, eep->calTargetPower5G,
|
||||
AR9380_NUM_5G_20_TARGET_POWERS, tpow_ofdm);
|
||||
|
||||
/* Get HT-20 target powers. */
|
||||
ar9003_get_ht_tpow(sc, c, AR_CTL_5GHT20,
|
||||
eep->calTargetFbin5GHT20, eep->calTargetPower5GHT20,
|
||||
AR9380_NUM_5G_20_TARGET_POWERS, tpow_ht20);
|
||||
|
||||
if (extc != NULL) {
|
||||
/* Get HT-40 target powers. */
|
||||
ar9003_get_ht_tpow(sc, c, AR_CTL_5GHT40,
|
||||
eep->calTargetFbin5GHT40,
|
||||
eep->calTargetPower5GHT40,
|
||||
AR9380_NUM_5G_40_TARGET_POWERS, tpow_ht40);
|
||||
}
|
||||
}
|
||||
|
||||
memset(power, 0, sizeof(power));
|
||||
/* Shuffle target powers accross transmit rates. */
|
||||
power[ATHN_POWER_OFDM6 ] =
|
||||
power[ATHN_POWER_OFDM9 ] =
|
||||
power[ATHN_POWER_OFDM12] =
|
||||
power[ATHN_POWER_OFDM18] =
|
||||
power[ATHN_POWER_OFDM24] = tpow_ofdm[0];
|
||||
power[ATHN_POWER_OFDM36] = tpow_ofdm[1];
|
||||
power[ATHN_POWER_OFDM48] = tpow_ofdm[2];
|
||||
power[ATHN_POWER_OFDM54] = tpow_ofdm[3];
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
power[ATHN_POWER_CCK1_LP ] =
|
||||
power[ATHN_POWER_CCK2_LP ] =
|
||||
power[ATHN_POWER_CCK2_SP ] =
|
||||
power[ATHN_POWER_CCK55_LP] = tpow_cck[0];
|
||||
power[ATHN_POWER_CCK55_SP] = tpow_cck[1];
|
||||
power[ATHN_POWER_CCK11_LP] = tpow_cck[2];
|
||||
power[ATHN_POWER_CCK11_SP] = tpow_cck[3];
|
||||
}
|
||||
/* Next entry covers MCS0, MCS8 and MCS16. */
|
||||
power[ATHN_POWER_HT20( 0)] = tpow_ht20[ 0];
|
||||
/* Next entry covers MCS1-3, MCS9-11 and MCS17-19. */
|
||||
power[ATHN_POWER_HT20( 1)] = tpow_ht20[ 1];
|
||||
power[ATHN_POWER_HT20( 4)] = tpow_ht20[ 2];
|
||||
power[ATHN_POWER_HT20( 5)] = tpow_ht20[ 3];
|
||||
power[ATHN_POWER_HT20( 6)] = tpow_ht20[ 4];
|
||||
power[ATHN_POWER_HT20( 7)] = tpow_ht20[ 5];
|
||||
power[ATHN_POWER_HT20(12)] = tpow_ht20[ 6];
|
||||
power[ATHN_POWER_HT20(13)] = tpow_ht20[ 7];
|
||||
power[ATHN_POWER_HT20(14)] = tpow_ht20[ 8];
|
||||
power[ATHN_POWER_HT20(15)] = tpow_ht20[ 9];
|
||||
power[ATHN_POWER_HT20(20)] = tpow_ht20[10];
|
||||
power[ATHN_POWER_HT20(21)] = tpow_ht20[11];
|
||||
power[ATHN_POWER_HT20(22)] = tpow_ht20[12];
|
||||
power[ATHN_POWER_HT20(23)] = tpow_ht20[13];
|
||||
if (extc != NULL) {
|
||||
/* Next entry covers MCS0, MCS8 and MCS16. */
|
||||
power[ATHN_POWER_HT40( 0)] = tpow_ht40[ 0];
|
||||
/* Next entry covers MCS1-3, MCS9-11 and MCS17-19. */
|
||||
power[ATHN_POWER_HT40( 1)] = tpow_ht40[ 1];
|
||||
power[ATHN_POWER_HT40( 4)] = tpow_ht40[ 2];
|
||||
power[ATHN_POWER_HT40( 5)] = tpow_ht40[ 3];
|
||||
power[ATHN_POWER_HT40( 6)] = tpow_ht40[ 4];
|
||||
power[ATHN_POWER_HT40( 7)] = tpow_ht40[ 5];
|
||||
power[ATHN_POWER_HT40(12)] = tpow_ht40[ 6];
|
||||
power[ATHN_POWER_HT40(13)] = tpow_ht40[ 7];
|
||||
power[ATHN_POWER_HT40(14)] = tpow_ht40[ 8];
|
||||
power[ATHN_POWER_HT40(15)] = tpow_ht40[ 9];
|
||||
power[ATHN_POWER_HT40(20)] = tpow_ht40[10];
|
||||
power[ATHN_POWER_HT40(21)] = tpow_ht40[11];
|
||||
power[ATHN_POWER_HT40(22)] = tpow_ht40[12];
|
||||
power[ATHN_POWER_HT40(23)] = tpow_ht40[13];
|
||||
}
|
||||
|
||||
/* Write transmit power values to hardware. */
|
||||
ar9003_write_txpower(sc, power);
|
||||
|
||||
/* Apply transmit power correction. */
|
||||
ar9380_set_correction(sc, c);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9380_get_correction(struct athn_softc *sc, struct ieee80211_channel *c,
|
||||
int chain, int *corr, int *temp)
|
||||
{
|
||||
const struct ar9380_eeprom *eep = sc->sc_eep;
|
||||
const struct ar9380_cal_data_per_freq_op_loop *pierdata;
|
||||
const uint8_t *pierfreq;
|
||||
uint8_t fbin;
|
||||
int lo, hi, npiers;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c)) {
|
||||
pierfreq = eep->calFreqPier2G;
|
||||
pierdata = eep->calPierData2G[chain];
|
||||
npiers = AR9380_NUM_2G_CAL_PIERS;
|
||||
}
|
||||
else {
|
||||
pierfreq = eep->calFreqPier5G;
|
||||
pierdata = eep->calPierData5G[chain];
|
||||
npiers = AR9380_NUM_5G_CAL_PIERS;
|
||||
}
|
||||
/* Find channel in ROM pier table. */
|
||||
fbin = athn_chan2fbin(c);
|
||||
athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
|
||||
|
||||
*corr = athn_interpolate(fbin,
|
||||
pierfreq[lo], pierdata[lo].refPower,
|
||||
pierfreq[hi], pierdata[hi].refPower);
|
||||
*temp = athn_interpolate(fbin,
|
||||
pierfreq[lo], pierdata[lo].tempMeas,
|
||||
pierfreq[hi], pierdata[hi].tempMeas);
|
||||
}
|
||||
|
||||
Static void
|
||||
ar9380_set_correction(struct athn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
const struct ar9380_eeprom *eep = sc->sc_eep;
|
||||
const struct ar9380_modal_eep_header *modal;
|
||||
uint32_t reg;
|
||||
int8_t slope;
|
||||
int i, corr, temp, temp0;
|
||||
|
||||
if (IEEE80211_IS_CHAN_2GHZ(c))
|
||||
modal = &eep->modalHeader2G;
|
||||
else
|
||||
modal = &eep->modalHeader5G;
|
||||
|
||||
temp0 = 0; /* XXX: gcc */
|
||||
for (i = 0; i < AR9380_MAX_CHAINS; i++) {
|
||||
ar9380_get_correction(sc, c, i, &corr, &temp);
|
||||
if (i == 0)
|
||||
temp0 = temp;
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TPC_11_B(i));
|
||||
reg = RW(reg, AR_PHY_TPC_11_OLPC_GAIN_DELTA, corr);
|
||||
AR_WRITE(sc, AR_PHY_TPC_11_B(i), reg);
|
||||
|
||||
/* Enable open loop power control. */
|
||||
reg = AR_READ(sc, AR_PHY_TPC_6_B(i));
|
||||
reg = RW(reg, AR_PHY_TPC_6_ERROR_EST_MODE, 3);
|
||||
AR_WRITE(sc, AR_PHY_TPC_6_B(i), reg);
|
||||
}
|
||||
|
||||
/* Enable temperature compensation. */
|
||||
if (IEEE80211_IS_CHAN_5GHZ(c) &&
|
||||
eep->base_ext2.tempSlopeLow != 0) {
|
||||
if (c->ic_freq <= 5500) {
|
||||
slope = athn_interpolate(c->ic_freq,
|
||||
5180, eep->base_ext2.tempSlopeLow,
|
||||
5500, modal->tempSlope);
|
||||
}
|
||||
else {
|
||||
slope = athn_interpolate(c->ic_freq,
|
||||
5500, modal->tempSlope,
|
||||
5785, eep->base_ext2.tempSlopeHigh);
|
||||
}
|
||||
}
|
||||
else
|
||||
slope = modal->tempSlope;
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TPC_19);
|
||||
reg = RW(reg, AR_PHY_TPC_19_ALPHA_THERM, slope);
|
||||
AR_WRITE(sc, AR_PHY_TPC_19, reg);
|
||||
|
||||
reg = AR_READ(sc, AR_PHY_TPC_18);
|
||||
reg = RW(reg, AR_PHY_TPC_18_THERM_CAL, temp0);
|
||||
AR_WRITE(sc, AR_PHY_TPC_18, reg);
|
||||
AR_WRITE_BARRIER(sc);
|
||||
}
|
33
sys/dev/ic/arn9380.h
Normal file
33
sys/dev/ic/arn9380.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* $NetBSD: arn9380.h,v 1.1 2013/03/30 02:53:02 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _IF_ARN9380_H_
|
||||
#define _IF_ARN9380_H_
|
||||
|
||||
int ar9380_attach(struct athn_softc *);
|
||||
|
||||
#endif /* _IF_ARN9380_H_ */
|
1926
sys/dev/ic/arn9380reg.h
Normal file
1926
sys/dev/ic/arn9380reg.h
Normal file
File diff suppressed because it is too large
Load Diff
2969
sys/dev/ic/athn.c
Normal file
2969
sys/dev/ic/athn.c
Normal file
File diff suppressed because it is too large
Load Diff
1489
sys/dev/ic/athnreg.h
Normal file
1489
sys/dev/ic/athnreg.h
Normal file
File diff suppressed because it is too large
Load Diff
674
sys/dev/ic/athnvar.h
Normal file
674
sys/dev/ic/athnvar.h
Normal file
@ -0,0 +1,674 @@
|
||||
/* $NetBSD: athnvar.h,v 1.1 2013/03/30 02:53:02 christos Exp $ */
|
||||
/* $OpenBSD: athnvar.h,v 1.33 2012/10/20 09:54:20 stsp Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
|
||||
*
|
||||
* Permission to use, copy, modify, and 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 _ATHNVAR_H_
|
||||
#define _ATHNVAR_H_
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_athn.h"
|
||||
#endif
|
||||
|
||||
#define PUBLIC
|
||||
|
||||
#define IEEE80211_NO_HT /* XXX: porting artifact */
|
||||
|
||||
#ifdef notyet
|
||||
#define ATHN_BT_COEXISTENCE 1
|
||||
#endif
|
||||
|
||||
#define ATHN_SOFTC(sc) ((struct athn_softc *)(sc))
|
||||
#define ATHN_NODE(ni) ((struct athn_node *)(ni))
|
||||
|
||||
#ifdef ATHN_DEBUG
|
||||
#define DBG_INIT __BIT(0)
|
||||
#define DBG_FN __BIT(1)
|
||||
#define DBG_TX __BIT(2)
|
||||
#define DBG_RX __BIT(3)
|
||||
#define DBG_STM __BIT(4)
|
||||
#define DBG_RF __BIT(5)
|
||||
#define DBG_NODES __BIT(6)
|
||||
#define DBG_INTR __BIT(7)
|
||||
#define DBG_ALL 0xffffffffU
|
||||
#define DPRINTFN(n, s, ...) do { \
|
||||
if (athn_debug & (n)) { \
|
||||
printf("%s: %s: ", \
|
||||
device_xname(ATHN_SOFTC(s)->sc_dev), __func__); \
|
||||
printf(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
extern int athn_debug;
|
||||
#else /* ATHN_DEBUG */
|
||||
#define DPRINTFN(n, s, ...)
|
||||
#endif /* ATHN_DEBUG */
|
||||
|
||||
#define LE_READ_4(p) ((p)[0] | (p)[1] << 8 | (p)[2] << 16 | (p)[3] << 24)
|
||||
#define LE_READ_2(p) ((p)[0] | (p)[1] << 8)
|
||||
|
||||
#define ATHN_RXBUFSZ 3872
|
||||
#define ATHN_TXBUFSZ 4096
|
||||
|
||||
#define ATHN_NRXBUFS 64
|
||||
#define ATHN_NTXBUFS 64 /* Shared between all Tx queues. */
|
||||
|
||||
struct athn_rx_radiotap_header {
|
||||
struct ieee80211_radiotap_header wr_ihdr;
|
||||
uint64_t wr_tsft;
|
||||
uint8_t wr_flags;
|
||||
uint8_t wr_rate;
|
||||
uint16_t wr_chan_freq;
|
||||
uint16_t wr_chan_flags;
|
||||
int8_t wr_dbm_antsignal;
|
||||
uint8_t wr_antenna;
|
||||
} __packed;
|
||||
|
||||
#define ATHN_RX_RADIOTAP_PRESENT \
|
||||
(1 << IEEE80211_RADIOTAP_TSFT | \
|
||||
1 << IEEE80211_RADIOTAP_FLAGS | \
|
||||
1 << IEEE80211_RADIOTAP_RATE | \
|
||||
1 << IEEE80211_RADIOTAP_CHANNEL | \
|
||||
1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL | \
|
||||
1 << IEEE80211_RADIOTAP_ANTENNA)
|
||||
|
||||
struct athn_tx_radiotap_header {
|
||||
struct ieee80211_radiotap_header wt_ihdr;
|
||||
uint8_t wt_flags;
|
||||
uint8_t wt_rate;
|
||||
uint16_t wt_chan_freq;
|
||||
uint16_t wt_chan_flags;
|
||||
} __packed;
|
||||
|
||||
#define ATHN_TX_RADIOTAP_PRESENT \
|
||||
(1 << IEEE80211_RADIOTAP_FLAGS | \
|
||||
1 << IEEE80211_RADIOTAP_RATE | \
|
||||
1 << IEEE80211_RADIOTAP_CHANNEL)
|
||||
|
||||
struct athn_tx_buf {
|
||||
SIMPLEQ_ENTRY(athn_tx_buf) bf_list;
|
||||
|
||||
void *bf_descs;
|
||||
bus_dmamap_t bf_map;
|
||||
bus_addr_t bf_daddr;
|
||||
|
||||
struct mbuf *bf_m;
|
||||
struct ieee80211_node *bf_ni;
|
||||
int bf_txflags;
|
||||
#define ATHN_TXFLAG_PAPRD (1 << 0)
|
||||
#define ATHN_TXFLAG_CAB (1 << 1)
|
||||
};
|
||||
|
||||
struct athn_txq {
|
||||
SIMPLEQ_HEAD(, athn_tx_buf) head;
|
||||
void *lastds;
|
||||
struct athn_tx_buf *wait;
|
||||
int queued;
|
||||
};
|
||||
|
||||
struct athn_rx_buf {
|
||||
SIMPLEQ_ENTRY(athn_rx_buf) bf_list;
|
||||
|
||||
void *bf_desc;
|
||||
bus_dmamap_t bf_map;
|
||||
|
||||
struct mbuf *bf_m;
|
||||
bus_addr_t bf_daddr;
|
||||
};
|
||||
|
||||
struct athn_rxq {
|
||||
struct athn_rx_buf *bf;
|
||||
|
||||
void *descs;
|
||||
void *lastds;
|
||||
bus_dmamap_t map;
|
||||
bus_dma_segment_t seg;
|
||||
int count;
|
||||
|
||||
SIMPLEQ_HEAD(, athn_rx_buf) head;
|
||||
};
|
||||
|
||||
/* Software rate indexes. */
|
||||
#define ATHN_RIDX_CCK1 0
|
||||
#define ATHN_RIDX_CCK2 1
|
||||
#define ATHN_RIDX_OFDM6 4
|
||||
#define ATHN_RIDX_MCS0 12
|
||||
#define ATHN_RIDX_MCS15 27
|
||||
#define ATHN_RIDX_MAX 27
|
||||
#define ATHN_IS_HT_RIDX(ridx) ((ridx) >= ATHN_RIDX_MCS0)
|
||||
|
||||
static const struct athn_rate {
|
||||
uint8_t rate; /* Rate in 500Kbps unit or MCS if 0x80. */
|
||||
uint8_t hwrate; /* HW representation. */
|
||||
uint8_t rspridx; /* Control Response Frame rate index. */
|
||||
enum ieee80211_phytype phy;
|
||||
} athn_rates[] = {
|
||||
{ 2, 0x1b, 0, IEEE80211_T_DS },
|
||||
{ 4, 0x1a, 1, IEEE80211_T_DS },
|
||||
{ 11, 0x19, 1, IEEE80211_T_DS },
|
||||
{ 22, 0x18, 1, IEEE80211_T_DS },
|
||||
{ 12, 0x0b, 4, IEEE80211_T_OFDM },
|
||||
{ 18, 0x0f, 4, IEEE80211_T_OFDM },
|
||||
{ 24, 0x0a, 6, IEEE80211_T_OFDM },
|
||||
{ 36, 0x0e, 6, IEEE80211_T_OFDM },
|
||||
{ 48, 0x09, 8, IEEE80211_T_OFDM },
|
||||
{ 72, 0x0d, 8, IEEE80211_T_OFDM },
|
||||
{ 96, 0x08, 8, IEEE80211_T_OFDM },
|
||||
{ 108, 0x0c, 8, IEEE80211_T_OFDM },
|
||||
{ 0x80, 0x80, 8, IEEE80211_T_OFDM },
|
||||
{ 0x81, 0x81, 8, IEEE80211_T_OFDM },
|
||||
{ 0x82, 0x82, 8, IEEE80211_T_OFDM },
|
||||
{ 0x83, 0x83, 8, IEEE80211_T_OFDM },
|
||||
{ 0x84, 0x84, 8, IEEE80211_T_OFDM },
|
||||
{ 0x85, 0x85, 8, IEEE80211_T_OFDM },
|
||||
{ 0x86, 0x86, 8, IEEE80211_T_OFDM },
|
||||
{ 0x87, 0x87, 8, IEEE80211_T_OFDM },
|
||||
{ 0x88, 0x88, 8, IEEE80211_T_OFDM },
|
||||
{ 0x89, 0x89, 8, IEEE80211_T_OFDM },
|
||||
{ 0x8a, 0x8a, 8, IEEE80211_T_OFDM },
|
||||
{ 0x8b, 0x8b, 8, IEEE80211_T_OFDM },
|
||||
{ 0x8c, 0x8c, 8, IEEE80211_T_OFDM },
|
||||
{ 0x8d, 0x8d, 8, IEEE80211_T_OFDM },
|
||||
{ 0x8e, 0x8e, 8, IEEE80211_T_OFDM },
|
||||
{ 0x8f, 0x8f, 8, IEEE80211_T_OFDM }
|
||||
};
|
||||
|
||||
struct athn_series {
|
||||
uint16_t dur;
|
||||
uint8_t hwrate;
|
||||
};
|
||||
|
||||
struct athn_pier {
|
||||
uint8_t fbin;
|
||||
const uint8_t *pwr[AR_PD_GAINS_IN_MASK];
|
||||
const uint8_t *vpd[AR_PD_GAINS_IN_MASK];
|
||||
};
|
||||
|
||||
/*
|
||||
* Structures used to store initialization values.
|
||||
*/
|
||||
struct athn_ini {
|
||||
int nregs;
|
||||
const uint16_t *regs;
|
||||
const uint32_t *vals_5g20;
|
||||
#ifndef IEEE80211_NO_HT
|
||||
const uint32_t *vals_5g40;
|
||||
const uint32_t *vals_2g40;
|
||||
#endif
|
||||
const uint32_t *vals_2g20;
|
||||
int ncmregs;
|
||||
const uint16_t *cmregs;
|
||||
const uint32_t *cmvals;
|
||||
int nfastregs;
|
||||
const uint16_t *fastregs;
|
||||
const uint32_t *fastvals_5g20;
|
||||
#ifndef IEEE80211_NO_HT
|
||||
const uint32_t *fastvals_5g40;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct athn_gain {
|
||||
int nregs;
|
||||
const uint16_t *regs;
|
||||
const uint32_t *vals_5g;
|
||||
const uint32_t *vals_2g;
|
||||
};
|
||||
|
||||
struct athn_addac {
|
||||
int nvals;
|
||||
const uint32_t *vals;
|
||||
};
|
||||
|
||||
struct athn_serdes {
|
||||
int nvals;
|
||||
const uint32_t *regs;
|
||||
const uint32_t *vals;
|
||||
};
|
||||
|
||||
/* Rx queue software indexes. */
|
||||
#define ATHN_QID_LP 0
|
||||
#define ATHN_QID_HP 0
|
||||
|
||||
/* Tx queue software indexes. */
|
||||
#define ATHN_QID_AC_BE 0
|
||||
#define ATHN_QID_PSPOLL 1
|
||||
#define ATHN_QID_AC_BK 2
|
||||
#define ATHN_QID_AC_VI 3
|
||||
#define ATHN_QID_AC_VO 4
|
||||
#define ATHN_QID_UAPSD 5
|
||||
#define ATHN_QID_CAB 6
|
||||
#define ATHN_QID_BEACON 7
|
||||
#define ATHN_QID_COUNT 8
|
||||
|
||||
/* Map Access Category to Tx queue Id. */
|
||||
static const uint8_t athn_ac2qid[EDCA_NUM_AC] = {
|
||||
ATHN_QID_AC_BE, /* EDCA_AC_BE */
|
||||
ATHN_QID_AC_BK, /* EDCA_AC_BK */
|
||||
ATHN_QID_AC_VI, /* EDCA_AC_VI */
|
||||
ATHN_QID_AC_VO /* EDCA_AC_VO */
|
||||
};
|
||||
|
||||
static const uint8_t athn_5ghz_chans[] = {
|
||||
/* UNII 1. */
|
||||
36, 40, 44, 48,
|
||||
/* UNII 2. */
|
||||
52, 56, 60, 64,
|
||||
/* Middle band. */
|
||||
100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
|
||||
/* UNII 3. */
|
||||
149, 153, 157, 161, 165
|
||||
};
|
||||
|
||||
/* Number of data bits per OFDM symbol for MCS[0-15]. */
|
||||
/* See tables 20-29, 20-30, 20-33, 20-34. */
|
||||
static const uint16_t ar_mcs_ndbps[][2] = {
|
||||
/* 20MHz 40MHz */
|
||||
{ 26, 54 }, /* MCS0 */
|
||||
{ 52, 108 }, /* MCS1 */
|
||||
{ 78, 162 }, /* MCS2 */
|
||||
{ 104, 216 }, /* MCS3 */
|
||||
{ 156, 324 }, /* MCS4 */
|
||||
{ 208, 432 }, /* MCS5 */
|
||||
{ 234, 486 }, /* MCS6 */
|
||||
{ 260, 540 }, /* MCS7 */
|
||||
{ 26, 108 }, /* MCS8 */
|
||||
{ 52, 216 }, /* MCS9 */
|
||||
{ 78, 324 }, /* MCS10 */
|
||||
{ 104, 432 }, /* MCS11 */
|
||||
{ 156, 648 }, /* MCS12 */
|
||||
{ 208, 864 }, /* MCS13 */
|
||||
{ 234, 972 }, /* MCS14 */
|
||||
{ 260, 1080 } /* MCS15 */
|
||||
};
|
||||
|
||||
#define ATHN_POWER_OFDM6 0
|
||||
#define ATHN_POWER_OFDM9 1
|
||||
#define ATHN_POWER_OFDM12 2
|
||||
#define ATHN_POWER_OFDM18 3
|
||||
#define ATHN_POWER_OFDM24 4
|
||||
#define ATHN_POWER_OFDM36 5
|
||||
#define ATHN_POWER_OFDM48 6
|
||||
#define ATHN_POWER_OFDM54 7
|
||||
#define ATHN_POWER_CCK1_LP 8
|
||||
#define ATHN_POWER_CCK2_LP 9
|
||||
#define ATHN_POWER_CCK2_SP 10
|
||||
#define ATHN_POWER_CCK55_LP 11
|
||||
#define ATHN_POWER_CCK55_SP 12
|
||||
#define ATHN_POWER_CCK11_LP 13
|
||||
#define ATHN_POWER_CCK11_SP 14
|
||||
#define ATHN_POWER_XR 15
|
||||
#define ATHN_POWER_HT20(mcs) (16 + (mcs))
|
||||
#define ATHN_POWER_HT40(mcs) (40 + (mcs))
|
||||
#define ATHN_POWER_CCK_DUP 64
|
||||
#define ATHN_POWER_OFDM_DUP 65
|
||||
#define ATHN_POWER_CCK_EXT 66
|
||||
#define ATHN_POWER_OFDM_EXT 67
|
||||
#define ATHN_POWER_COUNT 68
|
||||
|
||||
struct athn_node {
|
||||
struct ieee80211_node ni;
|
||||
struct ieee80211_amrr_node amn;
|
||||
uint8_t ridx[IEEE80211_RATE_MAXSIZE];
|
||||
uint8_t fallback[IEEE80211_RATE_MAXSIZE];
|
||||
uint8_t sta_index;
|
||||
};
|
||||
|
||||
/*
|
||||
* Adaptive noise immunity state.
|
||||
*/
|
||||
#define ATHN_ANI_PERIOD 100
|
||||
#define ATHN_ANI_RSSI_THR_HIGH 40
|
||||
#define ATHN_ANI_RSSI_THR_LOW 7
|
||||
struct athn_ani {
|
||||
uint8_t noise_immunity_level;
|
||||
uint8_t spur_immunity_level;
|
||||
uint8_t firstep_level;
|
||||
uint8_t ofdm_weak_signal;
|
||||
uint8_t cck_weak_signal;
|
||||
|
||||
uint32_t listen_time;
|
||||
|
||||
uint32_t ofdm_trig_high;
|
||||
uint32_t ofdm_trig_low;
|
||||
|
||||
int32_t cck_trig_high;
|
||||
int32_t cck_trig_low;
|
||||
|
||||
uint32_t ofdm_phy_err_base;
|
||||
uint32_t cck_phy_err_base;
|
||||
uint32_t ofdm_phy_err_count;
|
||||
uint32_t cck_phy_err_count;
|
||||
|
||||
uint32_t cyccnt;
|
||||
uint32_t txfcnt;
|
||||
uint32_t rxfcnt;
|
||||
};
|
||||
|
||||
struct athn_iq_cal {
|
||||
uint32_t pwr_meas_i;
|
||||
uint32_t pwr_meas_q;
|
||||
int32_t iq_corr_meas;
|
||||
};
|
||||
|
||||
struct athn_adc_cal {
|
||||
uint32_t pwr_meas_odd_i;
|
||||
uint32_t pwr_meas_even_i;
|
||||
uint32_t pwr_meas_odd_q;
|
||||
uint32_t pwr_meas_even_q;
|
||||
};
|
||||
|
||||
struct athn_calib {
|
||||
int nsamples;
|
||||
struct athn_iq_cal iq[AR_MAX_CHAINS];
|
||||
struct athn_adc_cal adc_gain[AR_MAX_CHAINS];
|
||||
struct athn_adc_cal adc_dc_offset[AR_MAX_CHAINS];
|
||||
};
|
||||
|
||||
#define ATHN_NF_CAL_HIST_MAX 5
|
||||
|
||||
struct athn_softc;
|
||||
|
||||
struct athn_ops {
|
||||
/* Bus callbacks. */
|
||||
uint32_t (*read)(struct athn_softc *, uint32_t);
|
||||
void (*write)(struct athn_softc *, uint32_t, uint32_t);
|
||||
void (*write_barrier)(struct athn_softc *);
|
||||
|
||||
void (*setup)(struct athn_softc *);
|
||||
void (*set_txpower)(struct athn_softc *, struct ieee80211_channel *,
|
||||
struct ieee80211_channel *);
|
||||
void (*spur_mitigate)(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
const struct ar_spur_chan *
|
||||
(*get_spur_chans)(struct athn_softc *, int);
|
||||
void (*init_from_rom)(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
int (*set_synth)(struct athn_softc *, struct ieee80211_channel *,
|
||||
struct ieee80211_channel *);
|
||||
int (*read_rom_data)(struct athn_softc *, uint32_t, void *, int);
|
||||
const uint8_t *
|
||||
(*get_rom_template)(struct athn_softc *, uint8_t);
|
||||
void (*swap_rom)(struct athn_softc *);
|
||||
void (*olpc_init)(struct athn_softc *);
|
||||
void (*olpc_temp_compensation)(struct athn_softc *);
|
||||
|
||||
/* GPIO callbacks. */
|
||||
int (*gpio_read)(struct athn_softc *, int);
|
||||
void (*gpio_write)(struct athn_softc *, int, int);
|
||||
void (*gpio_config_input)(struct athn_softc *, int);
|
||||
void (*gpio_config_output)(struct athn_softc *, int, int);
|
||||
void (*rfsilent_init)(struct athn_softc *);
|
||||
|
||||
/* DMA callbacks. */
|
||||
int (*dma_alloc)(struct athn_softc *);
|
||||
void (*dma_free)(struct athn_softc *);
|
||||
void (*rx_enable)(struct athn_softc *);
|
||||
int (*intr)(struct athn_softc *);
|
||||
int (*tx)(struct athn_softc *, struct mbuf *,
|
||||
struct ieee80211_node *, int);
|
||||
|
||||
/* PHY callbacks. */
|
||||
void (*set_rf_mode)(struct athn_softc *,
|
||||
struct ieee80211_channel *);
|
||||
int (*rf_bus_request)(struct athn_softc *);
|
||||
void (*rf_bus_release)(struct athn_softc *);
|
||||
void (*set_phy)(struct athn_softc *, struct ieee80211_channel *,
|
||||
struct ieee80211_channel *);
|
||||
void (*set_delta_slope)(struct athn_softc *,
|
||||
struct ieee80211_channel *, struct ieee80211_channel *);
|
||||
void (*enable_antenna_diversity)(struct athn_softc *);
|
||||
void (*init_baseband)(struct athn_softc *);
|
||||
void (*disable_phy)(struct athn_softc *);
|
||||
void (*set_rxchains)(struct athn_softc *);
|
||||
void (*noisefloor_calib)(struct athn_softc *);
|
||||
void (*do_calib)(struct athn_softc *);
|
||||
void (*next_calib)(struct athn_softc *);
|
||||
void (*hw_init)(struct athn_softc *, struct ieee80211_channel *,
|
||||
struct ieee80211_channel *);
|
||||
void (*get_paprd_masks)(struct athn_softc *sc,
|
||||
struct ieee80211_channel *, uint32_t *, uint32_t *);
|
||||
|
||||
/* ANI callbacks. */
|
||||
void (*set_noise_immunity_level)(struct athn_softc *, int);
|
||||
void (*enable_ofdm_weak_signal)(struct athn_softc *);
|
||||
void (*disable_ofdm_weak_signal)(struct athn_softc *);
|
||||
void (*set_cck_weak_signal)(struct athn_softc *, int);
|
||||
void (*set_firstep_level)(struct athn_softc *, int);
|
||||
void (*set_spur_immunity_level)(struct athn_softc *, int);
|
||||
};
|
||||
|
||||
struct athn_softc {
|
||||
device_t sc_dev;
|
||||
device_suspensor_t sc_suspensor;
|
||||
pmf_qual_t sc_qual;
|
||||
struct ieee80211com sc_ic;
|
||||
struct ifnet sc_if;
|
||||
|
||||
#if 0
|
||||
int (*sc_enable)(struct athn_softc *);
|
||||
void (*sc_disable)(struct athn_softc *);
|
||||
void (*sc_power)(struct athn_softc *, int);
|
||||
#endif
|
||||
void (*sc_disable_aspm)(struct athn_softc *);
|
||||
void (*sc_enable_extsynch)(
|
||||
struct athn_softc *);
|
||||
|
||||
int (*sc_newstate)(struct ieee80211com *,
|
||||
enum ieee80211_state, int);
|
||||
|
||||
bus_dma_tag_t sc_dmat;
|
||||
|
||||
callout_t sc_scan_to;
|
||||
callout_t sc_calib_to;
|
||||
struct ieee80211_amrr sc_amrr;
|
||||
|
||||
u_int sc_flags;
|
||||
#define ATHN_FLAG_PCIE (1 << 0)
|
||||
#define ATHN_FLAG_USB (1 << 1)
|
||||
#define ATHN_FLAG_OLPC (1 << 2)
|
||||
#define ATHN_FLAG_PAPRD (1 << 3)
|
||||
#define ATHN_FLAG_FAST_PLL_CLOCK (1 << 4)
|
||||
#define ATHN_FLAG_RFSILENT (1 << 5)
|
||||
#define ATHN_FLAG_RFSILENT_REVERSED (1 << 6)
|
||||
#define ATHN_FLAG_BTCOEX2WIRE (1 << 7)
|
||||
#define ATHN_FLAG_BTCOEX3WIRE (1 << 8)
|
||||
/* Shortcut. */
|
||||
#define ATHN_FLAG_BTCOEX (ATHN_FLAG_BTCOEX2WIRE | ATHN_FLAG_BTCOEX3WIRE)
|
||||
#define ATHN_FLAG_11A (1 << 9)
|
||||
#define ATHN_FLAG_11G (1 << 10)
|
||||
#define ATHN_FLAG_11N (1 << 11)
|
||||
#define ATHN_FLAG_AN_TOP2_FIXUP (1 << 12)
|
||||
#define ATHN_FLAG_NON_ENTERPRISE (1 << 13)
|
||||
#define ATHN_FLAG_3TREDUCE_CHAIN (1 << 14)
|
||||
|
||||
uint8_t sc_ngpiopins;
|
||||
int sc_led_pin;
|
||||
int sc_rfsilent_pin;
|
||||
int sc_led_state;
|
||||
uint32_t sc_isync;
|
||||
uint32_t sc_imask;
|
||||
|
||||
uint16_t sc_mac_ver;
|
||||
uint8_t sc_mac_rev;
|
||||
uint8_t sc_rf_rev;
|
||||
uint16_t sc_eep_rev;
|
||||
|
||||
uint8_t sc_txchainmask;
|
||||
uint8_t sc_rxchainmask;
|
||||
uint8_t sc_ntxchains;
|
||||
uint8_t sc_nrxchains;
|
||||
|
||||
uint8_t sc_sup_calib_mask;
|
||||
uint8_t sc_cur_calib_mask;
|
||||
#define ATHN_CAL_IQ (1 << 0)
|
||||
#define ATHN_CAL_ADC_GAIN (1 << 1)
|
||||
#define ATHN_CAL_ADC_DC (1 << 2)
|
||||
#define ATHN_CAL_TEMP (1 << 3)
|
||||
|
||||
struct ieee80211_channel *sc_curchan;
|
||||
struct ieee80211_channel *sc_curchanext;
|
||||
|
||||
/* Open Loop Power Control. */
|
||||
int8_t sc_tx_gain_tbl[AR9280_TX_GAIN_TABLE_SIZE];
|
||||
int8_t sc_pdadc;
|
||||
int8_t sc_tcomp;
|
||||
int sc_olpc_ticks;
|
||||
|
||||
/* PA predistortion. */
|
||||
uint16_t sc_gain1[AR_MAX_CHAINS];
|
||||
uint32_t sc_txgain[AR9003_TX_GAIN_TABLE_SIZE];
|
||||
int16_t sc_pa_in[AR_MAX_CHAINS]
|
||||
[AR9003_PAPRD_MEM_TAB_SIZE];
|
||||
int16_t sc_angle[AR_MAX_CHAINS]
|
||||
[AR9003_PAPRD_MEM_TAB_SIZE];
|
||||
int32_t sc_trainpow;
|
||||
uint8_t sc_paprd_curchain;
|
||||
|
||||
uint32_t sc_rwbuf[64];
|
||||
|
||||
size_t sc_kc_entries;
|
||||
|
||||
void *sc_eep;
|
||||
const void *sc_eep_def;
|
||||
uint32_t sc_eep_base;
|
||||
uint32_t sc_eep_size;
|
||||
|
||||
struct athn_rxq sc_rxq[2];
|
||||
struct athn_txq sc_txq[31];
|
||||
|
||||
void *sc_descs;
|
||||
bus_dmamap_t sc_map;
|
||||
bus_dma_segment_t sc_seg;
|
||||
SIMPLEQ_HEAD(, athn_tx_buf) sc_txbufs;
|
||||
struct athn_tx_buf *sc_bcnbuf;
|
||||
struct athn_tx_buf sc_txpool[ATHN_NTXBUFS];
|
||||
|
||||
bus_dmamap_t sc_txsmap;
|
||||
bus_dma_segment_t sc_txsseg;
|
||||
void *sc_txsring;
|
||||
int sc_txscur;
|
||||
|
||||
int sc_if_flags;
|
||||
int sc_tx_timer;
|
||||
|
||||
const struct athn_ini *sc_ini;
|
||||
const struct athn_gain *sc_rx_gain;
|
||||
const struct athn_gain *sc_tx_gain;
|
||||
const struct athn_addac *sc_addac;
|
||||
const struct athn_serdes *sc_serdes;
|
||||
uint32_t sc_workaround;
|
||||
uint32_t sc_obs_off;
|
||||
uint32_t sc_gpio_input_en_off;
|
||||
|
||||
struct athn_ops sc_ops;
|
||||
|
||||
int sc_fixed_ridx;
|
||||
|
||||
int16_t sc_cca_min_2g;
|
||||
int16_t sc_cca_max_2g;
|
||||
int16_t sc_cca_min_5g;
|
||||
int16_t sc_cca_max_5g;
|
||||
int16_t sc_def_nf;
|
||||
struct {
|
||||
int16_t nf[AR_MAX_CHAINS];
|
||||
int16_t nf_ext[AR_MAX_CHAINS];
|
||||
} sc_nf_hist[ATHN_NF_CAL_HIST_MAX];
|
||||
int sc_nf_hist_cur;
|
||||
int16_t sc_nf_priv[AR_MAX_CHAINS];
|
||||
int16_t sc_nf_ext_priv[AR_MAX_CHAINS];
|
||||
int sc_pa_calib_ticks;
|
||||
|
||||
struct athn_calib sc_calib;
|
||||
struct athn_ani sc_ani;
|
||||
|
||||
struct bpf_if * sc_drvbpf;
|
||||
|
||||
union {
|
||||
struct athn_rx_radiotap_header th;
|
||||
uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
|
||||
} sc_rxtapu;
|
||||
#define sc_rxtap sc_rxtapu.th
|
||||
int sc_rxtap_len;
|
||||
|
||||
union {
|
||||
struct athn_tx_radiotap_header th;
|
||||
uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
|
||||
} sc_txtapu;
|
||||
#define sc_txtap sc_txtapu.th
|
||||
int sc_txtap_len;
|
||||
|
||||
/*
|
||||
* Attach overrides. Set before calling athn_attach().
|
||||
*/
|
||||
int sc_max_aid;
|
||||
int (*sc_media_change)(struct ifnet *);
|
||||
};
|
||||
|
||||
int athn_attach(struct athn_softc *);
|
||||
void athn_detach(struct athn_softc *);
|
||||
void athn_suspend(struct athn_softc *);
|
||||
int athn_resume(struct athn_softc *);
|
||||
int athn_intr(void *);
|
||||
|
||||
/* used by if_athn_usb.c */
|
||||
void athn_btcoex_init(struct athn_softc *);
|
||||
int athn_hw_reset(struct athn_softc *, struct ieee80211_channel *,
|
||||
struct ieee80211_channel *, int);
|
||||
void athn_init_pll(struct athn_softc *, const struct ieee80211_channel *);
|
||||
void athn_led_init(struct athn_softc *);
|
||||
int athn_reset(struct athn_softc *, int);
|
||||
void athn_reset_key(struct athn_softc *, int);
|
||||
void athn_rx_start(struct athn_softc *);
|
||||
void athn_set_bss(struct athn_softc *, struct ieee80211_node *);
|
||||
int athn_set_chan(struct athn_softc *, struct ieee80211_channel *,
|
||||
struct ieee80211_channel *);
|
||||
void athn_set_hostap_timers(struct athn_softc *);
|
||||
void athn_set_led(struct athn_softc *, int);
|
||||
void athn_set_opmode(struct athn_softc *);
|
||||
int athn_set_power_awake(struct athn_softc *);
|
||||
void athn_set_power_sleep(struct athn_softc *);
|
||||
void athn_set_rxfilter(struct athn_softc *, uint32_t);
|
||||
void athn_set_sta_timers(struct athn_softc *);
|
||||
void athn_updateslot(struct ifnet *);
|
||||
|
||||
#ifdef notyet_edca
|
||||
void athn_updateedca(struct ieee80211com *);
|
||||
#endif
|
||||
#ifdef notyet
|
||||
void athn_delete_key(struct ieee80211com *, struct ieee80211_node *,
|
||||
struct ieee80211_key *);
|
||||
int athn_set_key(struct ieee80211com *, struct ieee80211_node *,
|
||||
struct ieee80211_key *);
|
||||
#endif /* notyet */
|
||||
|
||||
/* used by ar9285.c */
|
||||
uint8_t athn_chan2fbin(struct ieee80211_channel *);
|
||||
void athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *);
|
||||
|
||||
/* used by arn5008.c and arn9003.c */
|
||||
void athn_config_nonpcie(struct athn_softc *);
|
||||
void athn_config_pcie(struct athn_softc *);
|
||||
void athn_get_delta_slope(uint32_t, uint32_t *, uint32_t *);
|
||||
void athn_inc_tx_trigger_level(struct athn_softc *);
|
||||
void athn_stop(struct ifnet *, int);
|
||||
void athn_stop_tx_dma(struct athn_softc *, int);
|
||||
int athn_tx_pending(struct athn_softc *, int);
|
||||
int athn_txtime(struct athn_softc *, int, int, u_int);
|
||||
|
||||
/* used by arn5008.c, arn9003.c, arn9287.c, and arn9380.c */
|
||||
int athn_interpolate(int, int, int, int, int);
|
||||
|
||||
#endif /* _ATHNVAR_H_ */
|
339
sys/dev/pci/if_athn_pci.c
Normal file
339
sys/dev/pci/if_athn_pci.c
Normal file
@ -0,0 +1,339 @@
|
||||
/* $NetBSD: if_athn_pci.c,v 1.1 2013/03/30 02:53:02 christos Exp $ */
|
||||
/* $OpenBSD: if_athn_pci.c,v 1.11 2011/01/08 10:02:32 damien Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
|
||||
*
|
||||
* Permission to use, copy, modify, and 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PCI front-end for Atheros 802.11a/g/n chipsets.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_athn_pci.c,v 1.1 2013/03/30 02:53:02 christos Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/intr.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_amrr.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/ic/athnreg.h>
|
||||
#include <dev/ic/athnvar.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcidevs.h>
|
||||
|
||||
#define PCI_SUBSYSID_ATHEROS_COEX2WIRE 0x309b
|
||||
#define PCI_SUBSYSID_ATHEROS_COEX3WIRE_SA 0x30aa
|
||||
#define PCI_SUBSYSID_ATHEROS_COEX3WIRE_DA 0x30ab
|
||||
|
||||
#define ATHN_PCI_MMBA PCI_BAR(0) /* memory mapped base */
|
||||
|
||||
struct athn_pci_softc {
|
||||
struct athn_softc psc_sc;
|
||||
|
||||
/* PCI specific goo. */
|
||||
pci_chipset_tag_t psc_pc;
|
||||
pcitag_t psc_tag;
|
||||
pci_intr_handle_t psc_pih;
|
||||
void *psc_ih;
|
||||
bus_space_tag_t psc_iot;
|
||||
bus_space_handle_t psc_ioh;
|
||||
bus_size_t psc_mapsz;
|
||||
int psc_cap_off;
|
||||
};
|
||||
|
||||
#define Static static
|
||||
|
||||
Static int athn_pci_match(device_t, cfdata_t, void *);
|
||||
Static void athn_pci_attach(device_t, device_t, void *);
|
||||
Static int athn_pci_detach(device_t, int);
|
||||
Static int athn_pci_activate(device_t, enum devact);
|
||||
|
||||
CFATTACH_DECL_NEW(athn_pci, sizeof(struct athn_pci_softc), athn_pci_match,
|
||||
athn_pci_attach, athn_pci_detach, athn_pci_activate);
|
||||
|
||||
Static bool athn_pci_resume(device_t, const pmf_qual_t *);
|
||||
Static bool athn_pci_suspend(device_t, const pmf_qual_t *);
|
||||
Static uint32_t athn_pci_read(struct athn_softc *, uint32_t);
|
||||
Static void athn_pci_write(struct athn_softc *, uint32_t, uint32_t);
|
||||
Static void athn_pci_write_barrier(struct athn_softc *);
|
||||
Static void athn_pci_disable_aspm(struct athn_softc *);
|
||||
|
||||
Static int
|
||||
athn_pci_match(device_t parent, cfdata_t match, void *aux)
|
||||
{
|
||||
static const struct {
|
||||
pci_vendor_id_t apd_vendor;
|
||||
pci_product_id_t apd_product;
|
||||
} athn_pci_devices[] = {
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5416 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5418 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9160 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9280 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9281 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9285 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR2427 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9227 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9287 },
|
||||
{ PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR9300 }
|
||||
};
|
||||
struct pci_attach_args *pa = aux;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < __arraycount(athn_pci_devices); i++) {
|
||||
if (PCI_VENDOR(pa->pa_id) == athn_pci_devices[i].apd_vendor &&
|
||||
PCI_VENDOR(pa->pa_id) == athn_pci_devices[i].apd_product)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Static void
|
||||
athn_pci_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct athn_pci_softc *psc = device_private(self);
|
||||
struct athn_softc *sc = &psc->psc_sc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct pci_attach_args *pa = aux;
|
||||
const char *intrstr;
|
||||
pcireg_t memtype, reg;
|
||||
pci_product_id_t subsysid;
|
||||
int error;
|
||||
|
||||
sc->sc_dmat = pa->pa_dmat;
|
||||
psc->psc_pc = pa->pa_pc;
|
||||
psc->psc_tag = pa->pa_tag;
|
||||
|
||||
sc->sc_ops.read = athn_pci_read;
|
||||
sc->sc_ops.write = athn_pci_write;
|
||||
sc->sc_ops.write_barrier = athn_pci_write_barrier;
|
||||
|
||||
/*
|
||||
* Get the offset of the PCI Express Capability Structure in PCI
|
||||
* Configuration Space (Linux hardcodes it as 0x60.)
|
||||
*/
|
||||
error = pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIEXPRESS,
|
||||
&psc->psc_cap_off, NULL);
|
||||
if (error != 0) { /* Found. */
|
||||
sc->sc_disable_aspm = athn_pci_disable_aspm;
|
||||
sc->sc_flags |= ATHN_FLAG_PCIE;
|
||||
}
|
||||
/*
|
||||
* Noone knows why this shit is necessary but there are claims that
|
||||
* not doing this may cause very frequent PCI FATAL interrupts from
|
||||
* the card: http://bugzilla.kernel.org/show_bug.cgi?id=13483
|
||||
*/
|
||||
reg = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40);
|
||||
if (reg & 0xff00)
|
||||
pci_conf_write(pa->pa_pc, pa->pa_tag, 0x40, reg & ~0xff00);
|
||||
|
||||
/* Change latency timer; default value yields poor results. */
|
||||
reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
|
||||
reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
|
||||
reg |= 168 << PCI_LATTIMER_SHIFT;
|
||||
pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, reg);
|
||||
|
||||
/* Determine if bluetooth is also supported (combo chip.) */
|
||||
reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
|
||||
subsysid = PCI_PRODUCT(reg);
|
||||
if (subsysid == PCI_SUBSYSID_ATHEROS_COEX3WIRE_SA ||
|
||||
subsysid == PCI_SUBSYSID_ATHEROS_COEX3WIRE_DA)
|
||||
sc->sc_flags |= ATHN_FLAG_BTCOEX3WIRE;
|
||||
else if (subsysid == PCI_SUBSYSID_ATHEROS_COEX2WIRE)
|
||||
sc->sc_flags |= ATHN_FLAG_BTCOEX2WIRE;
|
||||
|
||||
/*
|
||||
* Setup memory-mapping of PCI registers.
|
||||
*/
|
||||
memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, ATHN_PCI_MMBA);
|
||||
if (memtype != PCI_MAPREG_TYPE_MEM &&
|
||||
memtype != PCI_MAPREG_MEM_TYPE_64BIT) {
|
||||
aprint_error_dev(self, "bad pci register type %d\n",
|
||||
(int)memtype);
|
||||
goto fail;
|
||||
}
|
||||
error = pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, &psc->psc_iot,
|
||||
&psc->psc_ioh, NULL, &psc->psc_mapsz);
|
||||
if (error != 0) {
|
||||
aprint_error_dev(self, "cannot map register space\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Arrange interrupt line.
|
||||
*/
|
||||
if (pci_intr_map(pa, &psc->psc_pih) != 0) {
|
||||
aprint_error_dev(self, "couldn't map interrupt\n");
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
intrstr = pci_intr_string(psc->psc_pc, psc->psc_pih);
|
||||
psc->psc_ih = pci_intr_establish(psc->psc_pc, psc->psc_pih, IPL_NET,
|
||||
athn_intr, sc);
|
||||
if (psc->psc_ih == NULL) {
|
||||
aprint_error_dev(self, "couldn't map interrupt\n");
|
||||
goto fail1;
|
||||
}
|
||||
aprint_verbose_dev(self, "interrupting at %s\n", intrstr);
|
||||
|
||||
if (athn_attach(sc) != 0)
|
||||
goto fail2;
|
||||
|
||||
if (pmf_device_register(self, athn_pci_suspend, athn_pci_resume)) {
|
||||
pmf_class_network_register(self, &sc->sc_if);
|
||||
pmf_device_suspend(self, &sc->sc_qual);
|
||||
}
|
||||
else
|
||||
aprint_error_dev(self, "couldn't establish power handler\n");
|
||||
|
||||
ieee80211_announce(ic);
|
||||
return;
|
||||
|
||||
fail2:
|
||||
pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
|
||||
psc->psc_ih = NULL;
|
||||
fail1:
|
||||
bus_space_unmap(psc->psc_iot, psc->psc_ioh, psc->psc_mapsz);
|
||||
psc->psc_mapsz = 0;
|
||||
fail:
|
||||
return;
|
||||
}
|
||||
|
||||
Static int
|
||||
athn_pci_detach(device_t self, int flags)
|
||||
{
|
||||
struct athn_pci_softc *psc = device_private(self);
|
||||
struct athn_softc *sc = &psc->psc_sc;
|
||||
|
||||
if (psc->psc_ih != NULL) {
|
||||
athn_detach(sc);
|
||||
pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
|
||||
psc->psc_ih = NULL;
|
||||
}
|
||||
if (psc->psc_mapsz > 0) {
|
||||
bus_space_unmap(psc->psc_iot, psc->psc_ioh, psc->psc_mapsz);
|
||||
psc->psc_mapsz = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Static int
|
||||
athn_pci_activate(device_t self, enum devact act)
|
||||
{
|
||||
struct athn_pci_softc *psc = device_private(self);
|
||||
struct athn_softc *sc = &psc->psc_sc;
|
||||
|
||||
switch (act) {
|
||||
case DVACT_DEACTIVATE:
|
||||
if_deactivate(sc->sc_ic.ic_ifp);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Static bool
|
||||
athn_pci_suspend(device_t self, const pmf_qual_t *qual)
|
||||
{
|
||||
struct athn_pci_softc *psc = device_private(self);
|
||||
struct athn_softc *sc = &psc->psc_sc;
|
||||
|
||||
athn_suspend(sc);
|
||||
if (psc->psc_ih != NULL) {
|
||||
pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
|
||||
psc->psc_ih = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Static bool
|
||||
athn_pci_resume(device_t self, const pmf_qual_t *qual)
|
||||
{
|
||||
struct athn_pci_softc *psc = device_private(self);
|
||||
struct athn_softc *sc = &psc->psc_sc;
|
||||
pcireg_t reg;
|
||||
|
||||
/*
|
||||
* XXX: see comment in athn_attach().
|
||||
*/
|
||||
reg = pci_conf_read(psc->psc_pc, psc->psc_tag, 0x40);
|
||||
if (reg & 0xff00)
|
||||
pci_conf_write(psc->psc_pc, psc->psc_tag, 0x40, reg & ~0xff00);
|
||||
|
||||
psc->psc_ih = pci_intr_establish(psc->psc_pc, psc->psc_pih, IPL_NET,
|
||||
athn_intr, sc);
|
||||
if (psc->psc_ih == NULL) {
|
||||
aprint_error_dev(self, "couldn't map interrupt\n");
|
||||
return false;
|
||||
}
|
||||
return athn_resume(sc);
|
||||
}
|
||||
|
||||
Static uint32_t
|
||||
athn_pci_read(struct athn_softc *sc, uint32_t addr)
|
||||
{
|
||||
struct athn_pci_softc *psc = (struct athn_pci_softc *)sc;
|
||||
|
||||
return bus_space_read_4(psc->psc_iot, psc->psc_ioh, addr);
|
||||
}
|
||||
|
||||
Static void
|
||||
athn_pci_write(struct athn_softc *sc, uint32_t addr, uint32_t val)
|
||||
{
|
||||
struct athn_pci_softc *psc = (struct athn_pci_softc *)sc;
|
||||
|
||||
bus_space_write_4(psc->psc_iot, psc->psc_ioh, addr, val);
|
||||
}
|
||||
|
||||
Static void
|
||||
athn_pci_write_barrier(struct athn_softc *sc)
|
||||
{
|
||||
struct athn_pci_softc *psc = (struct athn_pci_softc *)sc;
|
||||
|
||||
bus_space_barrier(psc->psc_iot, psc->psc_ioh, 0, psc->psc_mapsz,
|
||||
BUS_SPACE_BARRIER_WRITE);
|
||||
}
|
||||
|
||||
Static void
|
||||
athn_pci_disable_aspm(struct athn_softc *sc)
|
||||
{
|
||||
struct athn_pci_softc *psc = (struct athn_pci_softc *)sc;
|
||||
pcireg_t reg;
|
||||
|
||||
/* Disable PCIe Active State Power Management (ASPM). */
|
||||
reg = pci_conf_read(psc->psc_pc, psc->psc_tag,
|
||||
psc->psc_cap_off + PCI_PCIE_LCSR);
|
||||
reg &= ~(PCI_PCIE_LCSR_ASPM_L0S | PCI_PCIE_LCSR_ASPM_L1);
|
||||
pci_conf_write(psc->psc_pc, psc->psc_tag,
|
||||
psc->psc_cap_off + PCI_PCIE_LCSR, reg);
|
||||
}
|
2815
sys/dev/usb/if_athn_usb.c
Normal file
2815
sys/dev/usb/if_athn_usb.c
Normal file
File diff suppressed because it is too large
Load Diff
493
sys/dev/usb/if_athn_usb.h
Normal file
493
sys/dev/usb/if_athn_usb.h
Normal file
@ -0,0 +1,493 @@
|
||||
/* $NetBSD: if_athn_usb.h,v 1.1 2013/03/30 02:53:02 christos Exp $ */
|
||||
/* $OpenBSD: if_athn_usb.h,v 1.3 2012/11/10 14:35:06 mikeb Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 Damien Bergamini <damien.bergamini@free.fr>
|
||||
*
|
||||
* Permission to use, copy, modify, and 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 _IF_ATHN_USB_H_
|
||||
#define _IF_ATHN_USB_H_
|
||||
|
||||
/* Maximum number of STAs firmware can handle. */
|
||||
#define AR_USB_MAX_STA 8
|
||||
|
||||
#define AR_USB_DEFAULT_NF (-95)
|
||||
|
||||
/* USB requests. */
|
||||
#define AR_FW_DOWNLOAD 0x30
|
||||
#define AR_FW_DOWNLOAD_COMP 0x31
|
||||
|
||||
/* USB endpoints addresses. */
|
||||
#define AR_PIPE_TX_DATA (UE_DIR_OUT | 1)
|
||||
#define AR_PIPE_RX_DATA (UE_DIR_IN | 2)
|
||||
#define AR_PIPE_RX_INTR (UE_DIR_IN | 3)
|
||||
#define AR_PIPE_TX_INTR (UE_DIR_OUT | 4)
|
||||
|
||||
/* Wireless module interface commands. */
|
||||
#define AR_WMI_CMD_ECHO 0x001
|
||||
#define AR_WMI_CMD_ACCESS_MEMORY 0x002
|
||||
#define AR_WMI_CMD_DISABLE_INTR 0x003
|
||||
#define AR_WMI_CMD_ENABLE_INTR 0x004
|
||||
#define AR_WMI_CMD_RX_LINK 0x005
|
||||
#define AR_WMI_CMD_ATH_INIT 0x006
|
||||
#define AR_WMI_CMD_ABORT_TXQ 0x007
|
||||
#define AR_WMI_CMD_STOP_TX_DMA 0x008
|
||||
#define AR_WMI_CMD_STOP_DMA_RECV 0x009
|
||||
#define AR_WMI_CMD_ABORT_TX_DMA 0x00a
|
||||
#define AR_WMI_CMD_DRAIN_TXQ 0x00b
|
||||
#define AR_WMI_CMD_DRAIN_TXQ_ALL 0x00c
|
||||
#define AR_WMI_CMD_START_RECV 0x00d
|
||||
#define AR_WMI_CMD_STOP_RECV 0x00e
|
||||
#define AR_WMI_CMD_FLUSH_RECV 0x00f
|
||||
#define AR_WMI_CMD_SET_MODE 0x010
|
||||
#define AR_WMI_CMD_RESET 0x011
|
||||
#define AR_WMI_CMD_NODE_CREATE 0x012
|
||||
#define AR_WMI_CMD_NODE_REMOVE 0x013
|
||||
#define AR_WMI_CMD_VAP_REMOVE 0x014
|
||||
#define AR_WMI_CMD_VAP_CREATE 0x015
|
||||
#define AR_WMI_CMD_BEACON_UPDATE 0x016
|
||||
#define AR_WMI_CMD_REG_READ 0x017
|
||||
#define AR_WMI_CMD_REG_WRITE 0x018
|
||||
#define AR_WMI_CMD_RC_STATE_CHANGE 0x019
|
||||
#define AR_WMI_CMD_RC_RATE_UPDATE 0x01a
|
||||
#define AR_WMI_CMD_DEBUG_INFO 0x01b
|
||||
#define AR_WMI_CMD_HOST_ATTACH 0x01c
|
||||
#define AR_WMI_CMD_TARGET_IC_UPDATE 0x01d
|
||||
#define AR_WMI_CMD_TGT_STATS 0x01e
|
||||
#define AR_WMI_CMD_TX_AGGR_ENABLE 0x01f
|
||||
#define AR_WMI_CMD_TGT_DETACH 0x020
|
||||
#define AR_WMI_CMD_TGT_TXQ_ENABLE 0x021
|
||||
#define AR_WMI_CMD_AGGR_LIMIT 0x026
|
||||
/* Wireless module interface events. */
|
||||
/*
|
||||
* XXX: the 3.7.4 Linux kernel differs with this. This matches the
|
||||
* 2.6.36 kernel.
|
||||
*/
|
||||
#if 1 /* Linux 2.6.26 */
|
||||
#define AR_WMI_EVT_TGT_RDY 0x001
|
||||
#define AR_WMI_EVT_SWBA 0x002
|
||||
#define AR_WMI_EVT_FATAL 0x003
|
||||
#define AR_WMI_EVT_TXTO 0x004
|
||||
#define AR_WMI_EVT_BMISS 0x005
|
||||
#define AR_WMI_EVT_WLAN_TXCOMP 0x006
|
||||
#define AR_WMI_EVT_DELBA 0x007
|
||||
#define AR_WMI_EVT_TXRATE 0x008
|
||||
#else /* Linux 3.7.4 */
|
||||
#define AR_WMI_EVT_TGT_RDY 0x001
|
||||
#define AR_WMI_EVT_SWBA 0x002
|
||||
#define AR_WMI_EVT_FATAL 0x003
|
||||
#define AR_WMI_EVT_TXTO 0x004
|
||||
#define AR_WMI_EVT_BMISS 0x005
|
||||
#define AR_WMI_EVT_DELBA 0x006
|
||||
#define AR_WMI_EVT_TXSTATUS 0x007
|
||||
#endif
|
||||
|
||||
/* Structure for service AR_SVC_WMI_CONTROL. */
|
||||
struct ar_wmi_cmd_hdr {
|
||||
uint16_t cmd_id;
|
||||
#define AR_WMI_EVT_FLAG 0x1000
|
||||
|
||||
uint16_t seq_no;
|
||||
} __packed;
|
||||
|
||||
/* Values for AR_WMI_CMD_SET_MODE. */
|
||||
#define AR_HTC_MODE_AUTO 0
|
||||
#define AR_HTC_MODE_11A 1
|
||||
#define AR_HTC_MODE_11B 2
|
||||
#define AR_HTC_MODE_11G 3
|
||||
#define AR_HTC_MODE_FH 4
|
||||
#define AR_HTC_MODE_TURBO_A 5
|
||||
#define AR_HTC_MODE_TURBO_G 6
|
||||
#define AR_HTC_MODE_11NA 7
|
||||
#define AR_HTC_MODE_11NG 8
|
||||
|
||||
#define AR_MAX_WRITE_COUNT 32
|
||||
/* Structure for command AR_WMI_CMD_REG_WRITE. */
|
||||
struct ar_wmi_cmd_reg_write {
|
||||
uint32_t addr;
|
||||
uint32_t val;
|
||||
} __packed;
|
||||
|
||||
/* Structure for command AR_WMI_CMD_NODE_{CREATE,REMOVE}. */
|
||||
struct ar_htc_target_sta {
|
||||
uint16_t associd;
|
||||
uint16_t txpower;
|
||||
uint32_t pariwisekey;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
uint8_t bssid[IEEE80211_ADDR_LEN];
|
||||
uint8_t sta_index;
|
||||
uint8_t vif_index;
|
||||
uint8_t vif_sta;
|
||||
uint16_t flags;
|
||||
#define AR_HTC_STA_AUTH 0x0001
|
||||
#define AR_HTC_STA_QOS 0x0002
|
||||
#define AR_HTC_STA_ERP 0x0004
|
||||
#define AR_HTC_STA_HT 0x0008
|
||||
|
||||
uint16_t htcap;
|
||||
uint8_t valid;
|
||||
uint16_t capinfo;
|
||||
uint32_t reserved[2];
|
||||
uint16_t txseqmgmt;
|
||||
uint8_t is_vif_sta;
|
||||
uint16_t maxampdu;
|
||||
uint16_t iv16;
|
||||
uint32_t iv32;
|
||||
} __packed;
|
||||
|
||||
/* Structures for command AR_WMI_CMD_RC_RATE_UPDATE. */
|
||||
#define AR_HTC_RATE_MAX 30
|
||||
struct ar_htc_rateset {
|
||||
uint8_t rs_nrates;
|
||||
uint8_t rs_rates[AR_HTC_RATE_MAX];
|
||||
} __packed;
|
||||
|
||||
struct ar_htc_target_rate {
|
||||
uint8_t sta_index;
|
||||
uint8_t isnew;
|
||||
uint32_t capflags;
|
||||
#define AR_RC_DS_FLAG 0x00000001
|
||||
#define AR_RC_TS_FLAG 0x00000002
|
||||
#define AR_RC_40_FLAG 0x00000004
|
||||
#define AR_RC_SGI_FLAG 0x00000008
|
||||
#define AR_RC_HT_FLAG 0x00000010
|
||||
|
||||
struct ar_htc_rateset lg_rates;
|
||||
struct ar_htc_rateset ht_rates;
|
||||
} __packed;
|
||||
|
||||
/* Structure for command AR_WMI_CMD_TX_AGGR_ENABLE. */
|
||||
struct ar_htc_target_aggr {
|
||||
uint8_t sta_index;
|
||||
uint8_t tidno;
|
||||
uint8_t aggr_enable;
|
||||
uint8_t padding;
|
||||
} __packed;
|
||||
|
||||
/* Structure for command AR_WMI_CMD_VAP_CREATE. */
|
||||
struct ar_htc_target_vif {
|
||||
uint8_t index;
|
||||
uint8_t des_bssid[IEEE80211_ADDR_LEN];
|
||||
uint32_t opmode;
|
||||
#define AR_HTC_M_IBSS 0
|
||||
#define AR_HTC_M_STA 1
|
||||
#define AR_HTC_M_WDS 2
|
||||
#define AR_HTC_M_AHDEMO 3
|
||||
#define AR_HTC_M_HOSTAP 6
|
||||
#define AR_HTC_M_MONITOR 8
|
||||
|
||||
uint8_t myaddr[IEEE80211_ADDR_LEN];
|
||||
uint8_t bssid[IEEE80211_ADDR_LEN];
|
||||
uint32_t flags;
|
||||
uint32_t flags_ext;
|
||||
uint16_t ps_sta;
|
||||
uint16_t rtsthreshold;
|
||||
uint8_t ath_cap;
|
||||
int8_t mcast_rate;
|
||||
} __packed;
|
||||
|
||||
/* Structure for command AM_WMI_CMD_TARGET_IC_UPDATE. */
|
||||
struct ar_htc_cap_target {
|
||||
uint32_t flags;
|
||||
uint32_t flags_ext;
|
||||
uint32_t ampdu_limit;
|
||||
uint8_t ampdu_subframes;
|
||||
uint8_t ht_txchainmask;
|
||||
uint8_t lg_txchainmask;
|
||||
uint8_t rtscts_ratecode;
|
||||
uint8_t protmode;
|
||||
} __packed;
|
||||
|
||||
/* Structure for event AR_WMI_EVT_TXRATE. */
|
||||
struct ar_wmi_evt_txrate {
|
||||
uint32_t txrate;
|
||||
uint8_t rssi_thresh;
|
||||
uint8_t per;
|
||||
} __packed;
|
||||
|
||||
/* HTC header. */
|
||||
struct ar_htc_frame_hdr {
|
||||
uint8_t endpoint_id;
|
||||
uint8_t flags;
|
||||
#define AR_HTC_FLAG_TRAILER 0x02
|
||||
|
||||
uint16_t payload_len;
|
||||
uint8_t control[4];
|
||||
} __packed;
|
||||
|
||||
/* Structure for HTC enpoint id 0. */
|
||||
struct ar_htc_msg_hdr {
|
||||
uint16_t msg_id;
|
||||
#define AR_HTC_MSG_READY 0x0001
|
||||
#define AR_HTC_MSG_CONN_SVC 0x0002
|
||||
#define AR_HTC_MSG_CONN_SVC_RSP 0x0003
|
||||
#define AR_HTC_MSG_SETUP_COMPLETE 0x0004
|
||||
#define AR_HTC_MSG_CONF_PIPE 0x0005
|
||||
#define AR_HTC_MSG_CONF_PIPE_RSP 0x0006
|
||||
} __packed;
|
||||
|
||||
/* Structure for services AR_SVC_WMI_DATA_{VO,VI,BE,BK}. */
|
||||
struct ar_tx_frame {
|
||||
uint8_t data_type;
|
||||
#define AR_HTC_AMPDU 1
|
||||
#define AR_HTC_NORMAL 2
|
||||
|
||||
uint8_t node_idx;
|
||||
uint8_t vif_idx;
|
||||
uint8_t tid;
|
||||
uint32_t flags;
|
||||
#define AR_HTC_TX_CTSONLY 0x00000001
|
||||
#define AR_HTC_TX_RTSCTS 0x00000002
|
||||
#define AR_HTC_TX_USE_MIN_RATE 0x00000100
|
||||
|
||||
uint8_t key_type;
|
||||
uint8_t key_idx;
|
||||
uint8_t reserved[26];
|
||||
} __packed;
|
||||
|
||||
/* Structure for service AR_SVC_WMI_MGMT. */
|
||||
struct ar_tx_mgmt {
|
||||
uint8_t node_idx;
|
||||
uint8_t vif_idx;
|
||||
uint8_t tid;
|
||||
uint8_t flags;
|
||||
uint8_t key_type;
|
||||
uint8_t key_idx;
|
||||
uint16_t reserved;
|
||||
} __packed;
|
||||
|
||||
/* Structure for service AR_SVC_WMI_BEACON. */
|
||||
struct ar_tx_bcn {
|
||||
uint8_t len_changed;
|
||||
uint8_t vif_idx;
|
||||
uint16_t rev;
|
||||
} __packed;
|
||||
|
||||
/* Structure for message AR_HTC_MSG_READY. */
|
||||
struct ar_htc_msg_ready {
|
||||
uint16_t credits;
|
||||
uint16_t credits_size;
|
||||
uint8_t max_endpoints;
|
||||
uint8_t reserved;
|
||||
} __packed;
|
||||
|
||||
/* Structure for message AR_HTC_MSG_CONF_PIPE. */
|
||||
struct ar_htc_msg_config_pipe {
|
||||
uint8_t pipe_id;
|
||||
uint8_t credits;
|
||||
} __packed;
|
||||
|
||||
/* Structure for message AR_HTC_MSG_CONN_SVC. */
|
||||
struct ar_htc_msg_conn_svc {
|
||||
uint16_t svc_id;
|
||||
uint16_t conn_flags;
|
||||
uint8_t dl_pipeid;
|
||||
uint8_t ul_pipeid;
|
||||
uint8_t svc_meta_len;
|
||||
uint8_t reserved;
|
||||
} __packed;
|
||||
|
||||
/* Structure for message AR_HTC_MSG_CONN_SVC_RSP. */
|
||||
struct ar_htc_msg_conn_svc_rsp {
|
||||
uint16_t svc_id;
|
||||
uint8_t status;
|
||||
#define AR_HTC_SVC_SUCCESS 0
|
||||
#define AR_HTC_SVC_NOT_FOUND 1
|
||||
#define AR_HTC_SVC_FAILED 2
|
||||
#define AR_HTC_SVC_NO_RESOURCES 3
|
||||
#define AR_HTC_SVC_NO_MORE_EP 4
|
||||
|
||||
uint8_t endpoint_id;
|
||||
uint16_t max_msg_len;
|
||||
uint8_t svc_meta_len;
|
||||
uint8_t reserved;
|
||||
} __packed;
|
||||
|
||||
#define AR_SVC(grp, idx) ((grp) << 8 | (idx))
|
||||
#define AR_SVC_IDX(svc) ((svc) & 0xff)
|
||||
/* Service groups. */
|
||||
#define AR_SVC_GRP_RSVD 0
|
||||
#define AR_SVC_GRP_WMI 1
|
||||
/* Service identifiers for WMI group. */
|
||||
#define AR_SVC_WMI_CONTROL AR_SVC(AR_SVC_GRP_WMI, 0)
|
||||
#define AR_SVC_WMI_BEACON AR_SVC(AR_SVC_GRP_WMI, 1)
|
||||
#define AR_SVC_WMI_CAB AR_SVC(AR_SVC_GRP_WMI, 2)
|
||||
#define AR_SVC_WMI_UAPSD AR_SVC(AR_SVC_GRP_WMI, 3)
|
||||
#define AR_SVC_WMI_MGMT AR_SVC(AR_SVC_GRP_WMI, 4)
|
||||
#define AR_SVC_WMI_DATA_VO AR_SVC(AR_SVC_GRP_WMI, 5)
|
||||
#define AR_SVC_WMI_DATA_VI AR_SVC(AR_SVC_GRP_WMI, 6)
|
||||
#define AR_SVC_WMI_DATA_BE AR_SVC(AR_SVC_GRP_WMI, 7)
|
||||
#define AR_SVC_WMI_DATA_BK AR_SVC(AR_SVC_GRP_WMI, 8)
|
||||
|
||||
struct ar_stream_hdr {
|
||||
uint16_t len;
|
||||
uint16_t tag;
|
||||
#define AR_USB_RX_STREAM_TAG 0x4e00
|
||||
#define AR_USB_TX_STREAM_TAG 0x697e
|
||||
} __packed __attribute__((aligned(4)));
|
||||
|
||||
#define AR_MAX_CHAINS 3
|
||||
|
||||
/* Rx descriptor. */
|
||||
struct ar_rx_status {
|
||||
uint64_t rs_tstamp;
|
||||
uint16_t rs_datalen;
|
||||
uint8_t rs_status;
|
||||
uint8_t rs_phyerr;
|
||||
int8_t rs_rssi;
|
||||
int8_t rs_rssi_ctl[AR_MAX_CHAINS];
|
||||
int8_t rs_rssi_ext[AR_MAX_CHAINS];
|
||||
uint8_t rs_keyix;
|
||||
uint8_t rs_rate;
|
||||
uint8_t rs_antenna;
|
||||
uint8_t rs_more;
|
||||
uint8_t rs_isaggr;
|
||||
uint8_t rs_moreaggr;
|
||||
uint8_t rs_num_delims;
|
||||
uint8_t rs_flags;
|
||||
#define AR_RXS_FLAG_GI 0x04
|
||||
#define AR_RXS_FLAG_2040 0x08
|
||||
|
||||
uint8_t rs_dummy;
|
||||
uint32_t rs_evm[AR_MAX_CHAINS];
|
||||
} __packed __attribute__((aligned(4)));
|
||||
|
||||
|
||||
/*
|
||||
* Driver definitions.
|
||||
*/
|
||||
#define ATHN_USB_RX_LIST_COUNT 1
|
||||
#define ATHN_USB_TX_LIST_COUNT (8 + 1) /* NB: +1 for beacons. */
|
||||
|
||||
#define ATHN_USB_HOST_CMD_RING_COUNT 32
|
||||
|
||||
#define ATHN_USB_RXBUFSZ (8 * 1024) /* XXX Linux 16K */
|
||||
#define ATHN_USB_TXBUFSZ \
|
||||
((sizeof(struct ar_stream_hdr) + \
|
||||
sizeof(struct ar_htc_frame_hdr) + \
|
||||
sizeof(struct ar_tx_frame) + \
|
||||
IEEE80211_MAX_LEN + 3) & ~3)
|
||||
#define ATHN_USB_TXCMDSZ 512
|
||||
|
||||
#define ATHN_USB_TX_TIMEOUT 5000 /* ms */
|
||||
#define ATHN_USB_CMD_TIMEOUT 1000 /* ms */
|
||||
|
||||
struct athn_usb_softc;
|
||||
|
||||
struct athn_usb_rx_stream {
|
||||
struct mbuf *m;
|
||||
int moff;
|
||||
int left;
|
||||
};
|
||||
|
||||
struct athn_usb_rx_data {
|
||||
struct athn_usb_softc *sc;
|
||||
usbd_xfer_handle xfer;
|
||||
uint8_t *buf;
|
||||
};
|
||||
|
||||
struct athn_usb_tx_data {
|
||||
struct athn_usb_softc *sc;
|
||||
usbd_xfer_handle xfer;
|
||||
uint8_t *buf;
|
||||
TAILQ_ENTRY(athn_usb_tx_data) next;
|
||||
};
|
||||
|
||||
struct athn_usb_host_cmd {
|
||||
void (*cb)(struct athn_usb_softc *, void *);
|
||||
uint8_t data[256];
|
||||
};
|
||||
|
||||
struct athn_usb_cmd_newstate {
|
||||
enum ieee80211_state state;
|
||||
int arg;
|
||||
};
|
||||
|
||||
struct athn_usb_cmd_key {
|
||||
struct ieee80211_node *ni;
|
||||
struct ieee80211_key *key;
|
||||
};
|
||||
|
||||
struct athn_usb_aggr_cmd {
|
||||
uint8_t sta_index;
|
||||
uint8_t tid;
|
||||
};
|
||||
|
||||
struct athn_usb_host_cmd_ring {
|
||||
struct athn_usb_host_cmd cmd[ATHN_USB_HOST_CMD_RING_COUNT];
|
||||
int cur;
|
||||
int next;
|
||||
int queued;
|
||||
};
|
||||
|
||||
struct athn_usb_node {
|
||||
struct athn_node aun_an;
|
||||
/* our stuff */
|
||||
};
|
||||
|
||||
struct athn_usb_softc {
|
||||
struct athn_softc usc_sc;
|
||||
#define usc_dev usc_sc.sc_dev
|
||||
|
||||
int usc_athn_attached;
|
||||
|
||||
kmutex_t usc_task_mtx;
|
||||
kmutex_t usc_tx_mtx;
|
||||
|
||||
/* USB specific goo. */
|
||||
usbd_device_handle usc_udev;
|
||||
usbd_interface_handle usc_iface;
|
||||
struct usb_task usc_task;
|
||||
int usc_dying;
|
||||
|
||||
u_int usc_flags;
|
||||
#define ATHN_USB_FLAG_NONE 0x00
|
||||
#define ATHN_USB_FLAG_AR7010 0x01
|
||||
|
||||
struct athn_usb_rx_stream usc_rx_stream;
|
||||
|
||||
usbd_pipe_handle usc_tx_data_pipe;
|
||||
usbd_pipe_handle usc_rx_data_pipe;
|
||||
usbd_pipe_handle usc_rx_intr_pipe;
|
||||
usbd_pipe_handle usc_tx_intr_pipe;
|
||||
uint8_t *usc_ibuf;
|
||||
|
||||
struct ar_wmi_cmd_reg_write usc_wbuf[AR_MAX_WRITE_COUNT];
|
||||
int usc_wcount;
|
||||
|
||||
int usc_wmi_done;
|
||||
uint16_t usc_wmi_seq_no;
|
||||
uint16_t usc_wait_cmd_id;
|
||||
uint16_t usc_wait_msg_id;
|
||||
void *usc_obuf;
|
||||
struct ar_htc_msg_conn_svc_rsp *usc_msg_conn_svc_rsp;
|
||||
|
||||
struct athn_usb_host_cmd_ring usc_cmdq;
|
||||
struct athn_usb_rx_data usc_rx_data[ATHN_USB_RX_LIST_COUNT];
|
||||
struct athn_usb_tx_data usc_tx_data[ATHN_USB_TX_LIST_COUNT];
|
||||
TAILQ_HEAD(, athn_usb_tx_data) usc_tx_free_list;
|
||||
struct athn_usb_tx_data usc_tx_cmd;
|
||||
struct athn_usb_tx_data *usc_tx_bcn;
|
||||
|
||||
uint8_t usc_ep_ctrl;
|
||||
uint8_t usc_ep_bcn;
|
||||
uint8_t usc_ep_cab;
|
||||
uint8_t usc_ep_uapsd;
|
||||
uint8_t usc_ep_mgmt;
|
||||
uint8_t usc_ep_data[EDCA_NUM_AC];
|
||||
void (*usc_node_cleanup)(struct ieee80211_node *);
|
||||
};
|
||||
|
||||
#endif /* _IF_ATHN_USB_H_ */
|
Loading…
Reference in New Issue
Block a user