summaryrefslogtreecommitdiff
path: root/package/mac80211/patches/860-brcmsmac-implement-ieee80211_ops-get_tsf-and-set_tsf.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/mac80211/patches/860-brcmsmac-implement-ieee80211_ops-get_tsf-and-set_tsf.patch')
-rw-r--r--package/mac80211/patches/860-brcmsmac-implement-ieee80211_ops-get_tsf-and-set_tsf.patch121
1 files changed, 121 insertions, 0 deletions
diff --git a/package/mac80211/patches/860-brcmsmac-implement-ieee80211_ops-get_tsf-and-set_tsf.patch b/package/mac80211/patches/860-brcmsmac-implement-ieee80211_ops-get_tsf-and-set_tsf.patch
new file mode 100644
index 0000000..33991bc
--- /dev/null
+++ b/package/mac80211/patches/860-brcmsmac-implement-ieee80211_ops-get_tsf-and-set_tsf.patch
@@ -0,0 +1,121 @@
+--- a/drivers/net/wireless/brcm80211/brcmsmac/d11.h
++++ b/drivers/net/wireless/brcm80211/brcmsmac/d11.h
+@@ -457,6 +457,7 @@ struct d11regs {
+ /*== maccontrol register ==*/
+ #define MCTL_GMODE (1U << 31)
+ #define MCTL_DISCARD_PMQ (1 << 30)
++#define MCTL_TBTTHOLD (1 << 28)
+ #define MCTL_WAKE (1 << 26)
+ #define MCTL_HPS (1 << 25)
+ #define MCTL_PROMISC (1 << 24)
+--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+@@ -741,6 +741,28 @@ static void brcms_ops_flush(struct ieee8
+ "ret=%d\n", jiffies_to_msecs(ret));
+ }
+
++static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
++{
++ struct brcms_info *wl = hw->priv;
++ u64 tsf;
++
++ spin_lock_bh(&wl->lock);
++ tsf = brcms_c_tsf_get(wl->wlc);
++ spin_unlock_bh(&wl->lock);
++
++ return tsf;
++}
++
++static void brcms_ops_set_tsf(struct ieee80211_hw *hw,
++ struct ieee80211_vif *vif, u64 tsf)
++{
++ struct brcms_info *wl = hw->priv;
++
++ spin_lock_bh(&wl->lock);
++ brcms_c_tsf_set(wl->wlc, tsf);
++ spin_unlock_bh(&wl->lock);
++}
++
+ static const struct ieee80211_ops brcms_ops = {
+ .tx = brcms_ops_tx,
+ .start = brcms_ops_start,
+@@ -757,6 +779,8 @@ static const struct ieee80211_ops brcms_
+ .ampdu_action = brcms_ops_ampdu_action,
+ .rfkill_poll = brcms_ops_rfkill_poll,
+ .flush = brcms_ops_flush,
++ .get_tsf = brcms_ops_get_tsf,
++ .set_tsf = brcms_ops_set_tsf,
+ };
+
+ void brcms_dpc(unsigned long data)
+--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
+@@ -5545,6 +5545,20 @@ int brcms_c_set_rateset(struct brcms_c_i
+ return bcmerror;
+ }
+
++static void brcms_c_time_lock(struct brcms_c_info *wlc)
++{
++ bcma_set32(wlc->hw->d11core, D11REGOFFS(maccontrol), MCTL_TBTTHOLD);
++ /* Commit the write */
++ bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
++}
++
++static void brcms_c_time_unlock(struct brcms_c_info *wlc)
++{
++ bcma_mask32(wlc->hw->d11core, D11REGOFFS(maccontrol), ~MCTL_TBTTHOLD);
++ /* Commit the write */
++ bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
++}
++
+ int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
+ {
+ if (period == 0)
+@@ -7530,6 +7544,36 @@ void brcms_c_set_beacon_listen_interval(
+ brcms_c_bcn_li_upd(wlc);
+ }
+
++u64 brcms_c_tsf_get(struct brcms_c_info *wlc)
++{
++ u32 tsf_h, tsf_l;
++ u64 tsf;
++
++ brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h);
++
++ tsf = tsf_h;
++ tsf <<= 32;
++ tsf |= tsf_l;
++
++ return tsf;
++}
++
++void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf)
++{
++ u32 tsf_h, tsf_l;
++
++ brcms_c_time_lock(wlc);
++
++ tsf_l = tsf;
++ tsf_h = (tsf >> 32);
++
++ /* read the tsf timer low, then high to get an atomic read */
++ bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerlow), tsf_l);
++ bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerhigh), tsf_h);
++
++ brcms_c_time_unlock(wlc);
++}
++
+ int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr)
+ {
+ uint qdbm;
+--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
++++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
+@@ -326,6 +326,8 @@ extern void brcms_c_set_shortslot_overri
+ s8 sslot_override);
+ extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
+ u8 interval);
++extern u64 brcms_c_tsf_get(struct brcms_c_info *wlc);
++extern void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf);
+ extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
+ extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
+ extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);