]> Pileus Git - ~andy/linux/blob - drivers/net/wireless/b43/phy_lcn.c
604a3a66e5a63488facce4be80084588e67b1434
[~andy/linux] / drivers / net / wireless / b43 / phy_lcn.c
1 /*
2
3   Broadcom B43 wireless driver
4   IEEE 802.11n LCN-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_lcn.h"
27 #include "tables_phy_lcn.h"
28 #include "main.h"
29
30 /**************************************************
31  * Various PHY ops
32  **************************************************/
33
34 static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
35 {
36         u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2);
37         u16 afe_ctl1 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL1);
38
39         b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 | 0x1);
40         b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 | 0x1);
41
42         b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 & ~0x1);
43         b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 & ~0x1);
44
45         b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2);
46         b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1);
47 }
48
49 static void b43_phy_lcn_clean_0x18_table(struct b43_wldev *dev)
50 {
51         u8 i;
52
53         for (i = 0; i < 0x80; i++)
54                 b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000);
55 }
56
57 static void b43_phy_lcn_clear_0x07_table(struct b43_wldev *dev)
58 {
59         u8 i;
60
61         b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340);
62         for (i = 0; i < 30; i++) {
63                 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
64                 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
65         }
66
67         b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80);
68         for (i = 0; i < 64; i++) {
69                 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
70                 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
71         }
72 }
73
74 /**************************************************
75  * Basic PHY ops.
76  **************************************************/
77
78 static int b43_phy_lcn_op_allocate(struct b43_wldev *dev)
79 {
80         struct b43_phy_lcn *phy_lcn;
81
82         phy_lcn = kzalloc(sizeof(*phy_lcn), GFP_KERNEL);
83         if (!phy_lcn)
84                 return -ENOMEM;
85         dev->phy.lcn = phy_lcn;
86
87         return 0;
88 }
89
90 static void b43_phy_lcn_op_free(struct b43_wldev *dev)
91 {
92         struct b43_phy *phy = &dev->phy;
93         struct b43_phy_lcn *phy_lcn = phy->lcn;
94
95         kfree(phy_lcn);
96         phy->lcn = NULL;
97 }
98
99 static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
100 {
101         struct b43_phy *phy = &dev->phy;
102         struct b43_phy_lcn *phy_lcn = phy->lcn;
103
104         memset(phy_lcn, 0, sizeof(*phy_lcn));
105 }
106
107 static int b43_phy_lcn_op_init(struct b43_wldev *dev)
108 {
109         b43_phy_set(dev, 0x44a, 0x80);
110         b43_phy_mask(dev, 0x44a, 0x7f);
111         b43_phy_set(dev, 0x6d1, 0x80);
112         b43_phy_write(dev, 0x6d0, 0x7);
113
114         b43_phy_lcn_afe_set_unset(dev);
115
116         b43_phy_write(dev, 0x60a, 0xa0);
117         b43_phy_write(dev, 0x46a, 0x19);
118         b43_phy_maskset(dev, 0x663, 0xFF00, 0x64);
119
120         b43_phy_lcn_tables_init(dev);
121         /* TODO: various tables ops here */
122         b43_phy_lcn_clean_0x18_table(dev);
123
124         /* TODO: some ops here */
125
126         b43_phy_lcn_clear_0x07_table(dev);
127
128         return 0;
129 }
130
131 static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev,
132                                         bool blocked)
133 {
134         if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
135                 b43err(dev->wl, "MAC not suspended\n");
136
137         if (blocked) {
138                 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00);
139                 b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00);
140
141                 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00);
142                 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2);
143                 b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808);
144
145                 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8);
146                 b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8);
147         } else {
148                 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL1, ~0x1f00);
149                 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL3, ~0x808);
150                 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL6, ~0x8);
151         }
152 }
153
154 static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
155 {
156         if (on) {
157                 b43_phy_mask(dev, B43_PHY_LCN_AFE_CTL1, ~0x7);
158         } else {
159                 b43_phy_set(dev, B43_PHY_LCN_AFE_CTL2, 0x7);
160                 b43_phy_set(dev, B43_PHY_LCN_AFE_CTL1, 0x7);
161         }
162 }
163
164 static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
165 {
166         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
167                 return 1;
168         return 36;
169 }
170
171 static enum b43_txpwr_result
172 b43_phy_lcn_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
173 {
174         return B43_TXPWR_RES_DONE;
175 }
176
177 static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev)
178 {
179 }
180
181 /**************************************************
182  * PHY ops struct.
183  **************************************************/
184
185 const struct b43_phy_operations b43_phyops_lcn = {
186         .allocate               = b43_phy_lcn_op_allocate,
187         .free                   = b43_phy_lcn_op_free,
188         .prepare_structs        = b43_phy_lcn_op_prepare_structs,
189         .init                   = b43_phy_lcn_op_init,
190         /*
191         .phy_read               = b43_phy_lcn_op_read,
192         .phy_write              = b43_phy_lcn_op_write,
193         .phy_maskset            = b43_phy_lcn_op_maskset,
194         .radio_read             = b43_phy_lcn_op_radio_read,
195         .radio_write            = b43_phy_lcn_op_radio_write,
196         */
197         .software_rfkill        = b43_phy_lcn_op_software_rfkill,
198         .switch_analog          = b43_phy_lcn_op_switch_analog,
199         /*
200         .switch_channel         = b43_phy_lcn_op_switch_channel,
201         */
202         .get_default_chan       = b43_phy_lcn_op_get_default_chan,
203         .recalc_txpower         = b43_phy_lcn_op_recalc_txpower,
204         .adjust_txpower         = b43_phy_lcn_op_adjust_txpower,
205 };