aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt73usb.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-11-10 13:41:40 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-11-25 16:32:53 -0500
commitc9c3b1a5deac4297503145840fffcd122b253db5 (patch)
tree7d5e0cf6510c1687ef6b18d32ba9009a5692fbfd /drivers/net/wireless/rt2x00/rt73usb.c
parent9764f3f9c3700620f9f8a1f9af57f58758e835da (diff)
rt2x00: Cleanup indirect register access
All code which accessed indirect registers was similar in respect to the for-loop, the given timeout, etc. Move it into a seperate function, which for PCI drivers can be moved into rt2x00pci. This allows us to cleanup the cleanup the code further by removing the goto statementsand making the codepath look a bit nicer. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt73usb.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c147
1 files changed, 64 insertions, 83 deletions
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index d1a63e0017da..b4ca8488beff 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -63,7 +63,7 @@ static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev,
63 __le32 reg; 63 __le32 reg;
64 rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, 64 rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
65 USB_VENDOR_REQUEST_IN, offset, 65 USB_VENDOR_REQUEST_IN, offset,
66 &reg, sizeof(u32), REGISTER_TIMEOUT); 66 &reg, sizeof(reg), REGISTER_TIMEOUT);
67 *value = le32_to_cpu(reg); 67 *value = le32_to_cpu(reg);
68} 68}
69 69
@@ -73,7 +73,7 @@ static inline void rt73usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
73 __le32 reg; 73 __le32 reg;
74 rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, 74 rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
75 USB_VENDOR_REQUEST_IN, offset, 75 USB_VENDOR_REQUEST_IN, offset,
76 &reg, sizeof(u32), REGISTER_TIMEOUT); 76 &reg, sizeof(reg), REGISTER_TIMEOUT);
77 *value = le32_to_cpu(reg); 77 *value = le32_to_cpu(reg);
78} 78}
79 79
@@ -93,7 +93,7 @@ static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev,
93 __le32 reg = cpu_to_le32(value); 93 __le32 reg = cpu_to_le32(value);
94 rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, 94 rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
95 USB_VENDOR_REQUEST_OUT, offset, 95 USB_VENDOR_REQUEST_OUT, offset,
96 &reg, sizeof(u32), REGISTER_TIMEOUT); 96 &reg, sizeof(reg), REGISTER_TIMEOUT);
97} 97}
98 98
99static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev, 99static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
@@ -102,7 +102,7 @@ static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
102 __le32 reg = cpu_to_le32(value); 102 __le32 reg = cpu_to_le32(value);
103 rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, 103 rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
104 USB_VENDOR_REQUEST_OUT, offset, 104 USB_VENDOR_REQUEST_OUT, offset,
105 &reg, sizeof(u32), REGISTER_TIMEOUT); 105 &reg, sizeof(reg), REGISTER_TIMEOUT);
106} 106}
107 107
108static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, 108static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
@@ -115,21 +115,32 @@ static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
115 REGISTER_TIMEOUT32(length)); 115 REGISTER_TIMEOUT32(length));
116} 116}
117 117
118static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev) 118static int rt73usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
119 const unsigned int offset,
120 struct rt2x00_field32 field,
121 u32 *reg)
119{ 122{
120 u32 reg;
121 unsigned int i; 123 unsigned int i;
122 124
123 for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 125 for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
124 rt73usb_register_read_lock(rt2x00dev, PHY_CSR3, &reg); 126 rt73usb_register_read_lock(rt2x00dev, offset, reg);
125 if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY)) 127 if (!rt2x00_get_field32(*reg, field))
126 break; 128 return 1;
127 udelay(REGISTER_BUSY_DELAY); 129 udelay(REGISTER_BUSY_DELAY);
128 } 130 }
129 131
130 return reg; 132 ERROR(rt2x00dev, "Indirect register access failed: "
133 "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
134 *reg = ~0;
135
136 return 0;
131} 137}
132 138
139#define WAIT_FOR_BBP(__dev, __reg) \
140 rt73usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
141#define WAIT_FOR_RF(__dev, __reg) \
142 rt73usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
143
133static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, 144static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
134 const unsigned int word, const u8 value) 145 const unsigned int word, const u8 value)
135{ 146{
@@ -138,30 +149,20 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
138 mutex_lock(&rt2x00dev->csr_mutex); 149 mutex_lock(&rt2x00dev->csr_mutex);
139 150
140 /* 151 /*
141 * Wait until the BBP becomes ready. 152 * Wait until the BBP becomes available, afterwards we
153 * can safely write the new data into the register.
142 */ 154 */
143 reg = rt73usb_bbp_check(rt2x00dev); 155 if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
144 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) 156 reg = 0;
145 goto exit_fail; 157 rt2x00_set_field32(&reg, PHY_CSR3_VALUE, value);
146 158 rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
147 /* 159 rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
148 * Write the data into the BBP. 160 rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
149 */ 161
150 reg = 0; 162 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
151 rt2x00_set_field32(&reg, PHY_CSR3_VALUE, value); 163 }
152 rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
153 rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
154 rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
155
156 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
157 mutex_unlock(&rt2x00dev->csr_mutex);
158
159 return;
160 164
161exit_fail:
162 mutex_unlock(&rt2x00dev->csr_mutex); 165 mutex_unlock(&rt2x00dev->csr_mutex);
163
164 ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
165} 166}
166 167
167static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, 168static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -172,79 +173,59 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
172 mutex_lock(&rt2x00dev->csr_mutex); 173 mutex_lock(&rt2x00dev->csr_mutex);
173 174
174 /* 175 /*
175 * Wait until the BBP becomes ready. 176 * Wait until the BBP becomes available, afterwards we
177 * can safely write the read request into the register.
178 * After the data has been written, we wait until hardware
179 * returns the correct value, if at any time the register
180 * doesn't become available in time, reg will be 0xffffffff
181 * which means we return 0xff to the caller.
176 */ 182 */
177 reg = rt73usb_bbp_check(rt2x00dev); 183 if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
178 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) 184 reg = 0;
179 goto exit_fail; 185 rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
186 rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
187 rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
180 188
181 /* 189 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
182 * Write the request into the BBP.
183 */
184 reg = 0;
185 rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
186 rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
187 rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
188 190
189 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); 191 WAIT_FOR_BBP(rt2x00dev, &reg);
190 192 }
191 /*
192 * Wait until the BBP becomes ready.
193 */
194 reg = rt73usb_bbp_check(rt2x00dev);
195 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
196 goto exit_fail;
197 193
198 *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); 194 *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
199 mutex_unlock(&rt2x00dev->csr_mutex);
200
201 return;
202 195
203exit_fail:
204 mutex_unlock(&rt2x00dev->csr_mutex); 196 mutex_unlock(&rt2x00dev->csr_mutex);
205
206 ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
207 *value = 0xff;
208} 197}
209 198
210static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, 199static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
211 const unsigned int word, const u32 value) 200 const unsigned int word, const u32 value)
212{ 201{
213 u32 reg; 202 u32 reg;
214 unsigned int i;
215 203
216 if (!word) 204 if (!word)
217 return; 205 return;
218 206
219 mutex_lock(&rt2x00dev->csr_mutex); 207 mutex_lock(&rt2x00dev->csr_mutex);
220 208
221 for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
222 rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, &reg);
223 if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY))
224 goto rf_write;
225 udelay(REGISTER_BUSY_DELAY);
226 }
227
228 mutex_unlock(&rt2x00dev->csr_mutex);
229 ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n");
230 return;
231
232rf_write:
233 reg = 0;
234 rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
235
236 /* 209 /*
237 * RF5225 and RF2527 contain 21 bits per RF register value, 210 * Wait until the RF becomes available, afterwards we
238 * all others contain 20 bits. 211 * can safely write the new data into the register.
239 */ 212 */
240 rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS, 213 if (WAIT_FOR_RF(rt2x00dev, &reg)) {
241 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || 214 reg = 0;
242 rt2x00_rf(&rt2x00dev->chip, RF2527))); 215 rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
243 rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0); 216 /*
244 rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1); 217 * RF5225 and RF2527 contain 21 bits per RF register value,
245 218 * all others contain 20 bits.
246 rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); 219 */
247 rt2x00_rf_write(rt2x00dev, word, value); 220 rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS,
221 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
222 rt2x00_rf(&rt2x00dev->chip, RF2527)));
223 rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
224 rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
225
226 rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
227 rt2x00_rf_write(rt2x00dev, word, value);
228 }
248 229
249 mutex_unlock(&rt2x00dev->csr_mutex); 230 mutex_unlock(&rt2x00dev->csr_mutex);
250} 231}