diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2500usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 140 |
1 files changed, 60 insertions, 80 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index e6bae4ae4c47..40eb64358821 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -57,7 +57,7 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, | |||
57 | __le16 reg; | 57 | __le16 reg; |
58 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | 58 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, |
59 | USB_VENDOR_REQUEST_IN, offset, | 59 | USB_VENDOR_REQUEST_IN, offset, |
60 | ®, sizeof(u16), REGISTER_TIMEOUT); | 60 | ®, sizeof(reg), REGISTER_TIMEOUT); |
61 | *value = le16_to_cpu(reg); | 61 | *value = le16_to_cpu(reg); |
62 | } | 62 | } |
63 | 63 | ||
@@ -68,7 +68,7 @@ static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev, | |||
68 | __le16 reg; | 68 | __le16 reg; |
69 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, | 69 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, |
70 | USB_VENDOR_REQUEST_IN, offset, | 70 | USB_VENDOR_REQUEST_IN, offset, |
71 | ®, sizeof(u16), REGISTER_TIMEOUT); | 71 | ®, sizeof(reg), REGISTER_TIMEOUT); |
72 | *value = le16_to_cpu(reg); | 72 | *value = le16_to_cpu(reg); |
73 | } | 73 | } |
74 | 74 | ||
@@ -89,7 +89,7 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, | |||
89 | __le16 reg = cpu_to_le16(value); | 89 | __le16 reg = cpu_to_le16(value); |
90 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, | 90 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, |
91 | USB_VENDOR_REQUEST_OUT, offset, | 91 | USB_VENDOR_REQUEST_OUT, offset, |
92 | ®, sizeof(u16), REGISTER_TIMEOUT); | 92 | ®, sizeof(reg), REGISTER_TIMEOUT); |
93 | } | 93 | } |
94 | 94 | ||
95 | static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, | 95 | static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, |
@@ -99,7 +99,7 @@ static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, | |||
99 | __le16 reg = cpu_to_le16(value); | 99 | __le16 reg = cpu_to_le16(value); |
100 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, | 100 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, |
101 | USB_VENDOR_REQUEST_OUT, offset, | 101 | USB_VENDOR_REQUEST_OUT, offset, |
102 | ®, sizeof(u16), REGISTER_TIMEOUT); | 102 | ®, sizeof(reg), REGISTER_TIMEOUT); |
103 | } | 103 | } |
104 | 104 | ||
105 | static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, | 105 | static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, |
@@ -112,21 +112,32 @@ static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, | |||
112 | REGISTER_TIMEOUT16(length)); | 112 | REGISTER_TIMEOUT16(length)); |
113 | } | 113 | } |
114 | 114 | ||
115 | static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev) | 115 | static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev, |
116 | const unsigned int offset, | ||
117 | struct rt2x00_field16 field, | ||
118 | u16 *reg) | ||
116 | { | 119 | { |
117 | u16 reg; | ||
118 | unsigned int i; | 120 | unsigned int i; |
119 | 121 | ||
120 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 122 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
121 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, ®); | 123 | rt2500usb_register_read_lock(rt2x00dev, offset, reg); |
122 | if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY)) | 124 | if (!rt2x00_get_field16(*reg, field)) |
123 | break; | 125 | return 1; |
124 | udelay(REGISTER_BUSY_DELAY); | 126 | udelay(REGISTER_BUSY_DELAY); |
125 | } | 127 | } |
126 | 128 | ||
127 | return reg; | 129 | ERROR(rt2x00dev, "Indirect register access failed: " |
130 | "offset=0x%.08x, value=0x%.08x\n", offset, *reg); | ||
131 | *reg = ~0; | ||
132 | |||
133 | return 0; | ||
128 | } | 134 | } |
129 | 135 | ||
136 | #define WAIT_FOR_BBP(__dev, __reg) \ | ||
137 | rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg)) | ||
138 | #define WAIT_FOR_RF(__dev, __reg) \ | ||
139 | rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg)) | ||
140 | |||
130 | static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, | 141 | static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, |
131 | const unsigned int word, const u8 value) | 142 | const unsigned int word, const u8 value) |
132 | { | 143 | { |
@@ -135,30 +146,19 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
135 | mutex_lock(&rt2x00dev->csr_mutex); | 146 | mutex_lock(&rt2x00dev->csr_mutex); |
136 | 147 | ||
137 | /* | 148 | /* |
138 | * Wait until the BBP becomes ready. | 149 | * Wait until the BBP becomes available, afterwards we |
139 | */ | 150 | * can safely write the new data into the register. |
140 | reg = rt2500usb_bbp_check(rt2x00dev); | ||
141 | if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) | ||
142 | goto exit_fail; | ||
143 | |||
144 | /* | ||
145 | * Write the data into the BBP. | ||
146 | */ | 151 | */ |
147 | reg = 0; | 152 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
148 | rt2x00_set_field16(®, PHY_CSR7_DATA, value); | 153 | reg = 0; |
149 | rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); | 154 | rt2x00_set_field16(®, PHY_CSR7_DATA, value); |
150 | rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); | 155 | rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); |
151 | 156 | rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); | |
152 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); | ||
153 | |||
154 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
155 | 157 | ||
156 | return; | 158 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); |
159 | } | ||
157 | 160 | ||
158 | exit_fail: | ||
159 | mutex_unlock(&rt2x00dev->csr_mutex); | 161 | mutex_unlock(&rt2x00dev->csr_mutex); |
160 | |||
161 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); | ||
162 | } | 162 | } |
163 | 163 | ||
164 | static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, | 164 | static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, |
@@ -169,77 +169,57 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
169 | mutex_lock(&rt2x00dev->csr_mutex); | 169 | mutex_lock(&rt2x00dev->csr_mutex); |
170 | 170 | ||
171 | /* | 171 | /* |
172 | * Wait until the BBP becomes ready. | 172 | * Wait until the BBP becomes available, afterwards we |
173 | */ | 173 | * can safely write the read request into the register. |
174 | reg = rt2500usb_bbp_check(rt2x00dev); | 174 | * After the data has been written, we wait until hardware |
175 | if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) | 175 | * returns the correct value, if at any time the register |
176 | goto exit_fail; | 176 | * doesn't become available in time, reg will be 0xffffffff |
177 | 177 | * which means we return 0xff to the caller. | |
178 | /* | ||
179 | * Write the request into the BBP. | ||
180 | */ | 178 | */ |
181 | reg = 0; | 179 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
182 | rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); | 180 | reg = 0; |
183 | rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); | 181 | rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); |
182 | rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); | ||
184 | 183 | ||
185 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); | 184 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); |
186 | 185 | ||
187 | /* | 186 | if (WAIT_FOR_BBP(rt2x00dev, ®)) |
188 | * Wait until the BBP becomes ready. | 187 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); |
189 | */ | 188 | } |
190 | reg = rt2500usb_bbp_check(rt2x00dev); | ||
191 | if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) | ||
192 | goto exit_fail; | ||
193 | 189 | ||
194 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); | ||
195 | *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); | 190 | *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); |
196 | 191 | ||
197 | mutex_unlock(&rt2x00dev->csr_mutex); | 192 | mutex_unlock(&rt2x00dev->csr_mutex); |
198 | |||
199 | return; | ||
200 | |||
201 | exit_fail: | ||
202 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
203 | |||
204 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); | ||
205 | *value = 0xff; | ||
206 | } | 193 | } |
207 | 194 | ||
208 | static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, | 195 | static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, |
209 | const unsigned int word, const u32 value) | 196 | const unsigned int word, const u32 value) |
210 | { | 197 | { |
211 | u16 reg; | 198 | u16 reg; |
212 | unsigned int i; | ||
213 | 199 | ||
214 | if (!word) | 200 | if (!word) |
215 | return; | 201 | return; |
216 | 202 | ||
217 | mutex_lock(&rt2x00dev->csr_mutex); | 203 | mutex_lock(&rt2x00dev->csr_mutex); |
218 | 204 | ||
219 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 205 | /* |
220 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®); | 206 | * Wait until the RF becomes available, afterwards we |
221 | if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY)) | 207 | * can safely write the new data into the register. |
222 | goto rf_write; | 208 | */ |
223 | udelay(REGISTER_BUSY_DELAY); | 209 | if (WAIT_FOR_RF(rt2x00dev, ®)) { |
224 | } | 210 | reg = 0; |
225 | 211 | rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value); | |
226 | mutex_unlock(&rt2x00dev->csr_mutex); | 212 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg); |
227 | ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n"); | ||
228 | return; | ||
229 | |||
230 | rf_write: | ||
231 | reg = 0; | ||
232 | rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value); | ||
233 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg); | ||
234 | 213 | ||
235 | reg = 0; | 214 | reg = 0; |
236 | rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16); | 215 | rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16); |
237 | rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20); | 216 | rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20); |
238 | rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0); | 217 | rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0); |
239 | rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); | 218 | rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); |
240 | 219 | ||
241 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); | 220 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); |
242 | rt2x00_rf_write(rt2x00dev, word, value); | 221 | rt2x00_rf_write(rt2x00dev, word, value); |
222 | } | ||
243 | 223 | ||
244 | mutex_unlock(&rt2x00dev->csr_mutex); | 224 | mutex_unlock(&rt2x00dev->csr_mutex); |
245 | } | 225 | } |