b43: HT-PHY: implement switching analog
[pandora-kernel.git] / drivers / net / wireless / b43 / phy_ht.c
1 /*
2
3   Broadcom B43 wireless driver
4   IEEE 802.11n HT-PHY support
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; see the file COPYING.  If not, write to
18   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
19   Boston, MA 02110-1301, USA.
20
21 */
22
23 #include <linux/slab.h>
24
25 #include "b43.h"
26 #include "phy_ht.h"
27 #include "main.h"
28
29 /**************************************************
30  * Basic PHY ops.
31  **************************************************/
32
33 static int b43_phy_ht_op_allocate(struct b43_wldev *dev)
34 {
35         struct b43_phy_ht *phy_ht;
36
37         phy_ht = kzalloc(sizeof(*phy_ht), GFP_KERNEL);
38         if (!phy_ht)
39                 return -ENOMEM;
40         dev->phy.ht = phy_ht;
41
42         return 0;
43 }
44
45 static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev)
46 {
47         struct b43_phy *phy = &dev->phy;
48         struct b43_phy_ht *phy_ht = phy->ht;
49
50         memset(phy_ht, 0, sizeof(*phy_ht));
51 }
52
53 static void b43_phy_ht_op_free(struct b43_wldev *dev)
54 {
55         struct b43_phy *phy = &dev->phy;
56         struct b43_phy_ht *phy_ht = phy->ht;
57
58         kfree(phy_ht);
59         phy->ht = NULL;
60 }
61
62 static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on)
63 {
64         if (on) {
65                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00cd);
66                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x0000);
67                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00cd);
68                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x0000);
69                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00cd);
70                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x0000);
71         } else {
72                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x07ff);
73                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00fd);
74                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x07ff);
75                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00fd);
76                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x07ff);
77                 b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00fd);
78         }
79 }
80
81 static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev)
82 {
83         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
84                 return 1;
85         return 36;
86 }
87
88 /**************************************************
89  * R/W ops.
90  **************************************************/
91
92 static u16 b43_phy_ht_op_read(struct b43_wldev *dev, u16 reg)
93 {
94         b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
95         return b43_read16(dev, B43_MMIO_PHY_DATA);
96 }
97
98 static void b43_phy_ht_op_write(struct b43_wldev *dev, u16 reg, u16 value)
99 {
100         b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
101         b43_write16(dev, B43_MMIO_PHY_DATA, value);
102 }
103
104 static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
105                                  u16 set)
106 {
107         b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
108         b43_write16(dev, B43_MMIO_PHY_DATA,
109                     (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
110 }
111
112 static u16 b43_phy_ht_op_radio_read(struct b43_wldev *dev, u16 reg)
113 {
114         /* HT-PHY needs 0x200 for read access */
115         reg |= 0x200;
116
117         b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
118         return b43_read16(dev, B43_MMIO_RADIO24_DATA);
119 }
120
121 static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg,
122                                       u16 value)
123 {
124         b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
125         b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
126 }
127
128 /**************************************************
129  * PHY ops struct.
130  **************************************************/
131
132 const struct b43_phy_operations b43_phyops_ht = {
133         .allocate               = b43_phy_ht_op_allocate,
134         .free                   = b43_phy_ht_op_free,
135         .prepare_structs        = b43_phy_ht_op_prepare_structs,
136         /*
137         .init                   = b43_phy_ht_op_init,
138         */
139         .phy_read               = b43_phy_ht_op_read,
140         .phy_write              = b43_phy_ht_op_write,
141         .phy_maskset            = b43_phy_ht_op_maskset,
142         .radio_read             = b43_phy_ht_op_radio_read,
143         .radio_write            = b43_phy_ht_op_radio_write,
144         /*
145         .software_rfkill        = b43_phy_ht_op_software_rfkill,
146         */
147         .switch_analog          = b43_phy_ht_op_switch_analog,
148         /*
149         .switch_channel         = b43_phy_ht_op_switch_channel,
150         */
151         .get_default_chan       = b43_phy_ht_op_get_default_chan,
152         /*
153         .recalc_txpower         = b43_phy_ht_op_recalc_txpower,
154         .adjust_txpower         = b43_phy_ht_op_adjust_txpower,
155         */
156 };