blob: 42ae61014522d03805d3659e565e4cee1d583316 [file] [log] [blame]
Pekka Enberg80aba532008-10-30 13:04:29 +02001#include "wb35reg_f.h"
2
3#include <linux/usb.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +09004#include <linux/slab.h>
Pavel Machek66101de2008-10-01 14:36:56 +02005
Pekka Enberg8e41b4b2009-01-12 18:02:47 +02006extern void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency);
Pavel Machek66101de2008-10-01 14:36:56 +02007
Lars Lindleyfa448c12010-03-25 14:44:53 +01008/*
9 * true : read command process successfully
10 * false : register not support
11 * RegisterNo : start base
12 * pRegisterData : data point
13 * NumberOfData : number of register data
14 * Flag : AUTO_INCREMENT - RegisterNo will auto increment 4
15 * NO_INCREMENT - Function will write data into the same register
16 */
17unsigned char Wb35Reg_BurstWrite(struct hw_data *pHwData, u16 RegisterNo, u32 *pRegisterData, u8 NumberOfData, u8 Flag)
Pavel Machek66101de2008-10-01 14:36:56 +020018{
Lars Lindleyfa448c12010-03-25 14:44:53 +010019 struct wb35_reg *reg = &pHwData->reg;
20 struct urb *urb = NULL;
21 struct wb35_reg_queue *reg_queue = NULL;
22 u16 UrbSize;
23 struct usb_ctrlrequest *dr;
24 u16 i, DataSize = NumberOfData * 4;
Pavel Machek66101de2008-10-01 14:36:56 +020025
Lars Lindleyfa448c12010-03-25 14:44:53 +010026 /* Module shutdown */
Pavel Machek66101de2008-10-01 14:36:56 +020027 if (pHwData->SurpriseRemove)
Pekka Enberg279b6cc2008-10-27 22:46:39 +020028 return false;
Pavel Machek66101de2008-10-01 14:36:56 +020029
Lars Lindleyfa448c12010-03-25 14:44:53 +010030 /* Trying to use burst write function if use new hardware */
Pekka Enbergf37435c2008-10-22 11:01:47 +030031 UrbSize = sizeof(struct wb35_reg_queue) + DataSize + sizeof(struct usb_ctrlrequest);
Pekka Enbergc8b2b702008-10-27 22:47:12 +020032 reg_queue = kzalloc(UrbSize, GFP_ATOMIC);
Greg Kroah-Hartmanf3d20182008-10-27 14:21:24 -070033 urb = usb_alloc_urb(0, GFP_ATOMIC);
Lars Lindleyfa448c12010-03-25 14:44:53 +010034 if (urb && reg_queue) {
35 reg_queue->DIRECT = 2; /* burst write register */
Pekka Enbergf37435c2008-10-22 11:01:47 +030036 reg_queue->INDEX = RegisterNo;
37 reg_queue->pBuffer = (u32 *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue));
Lars Lindleyfa448c12010-03-25 14:44:53 +010038 memcpy(reg_queue->pBuffer, pRegisterData, DataSize);
39 /* the function for reversing register data from little endian to big endian */
40 for (i = 0; i < NumberOfData ; i++)
41 reg_queue->pBuffer[i] = cpu_to_le32(reg_queue->pBuffer[i]);
Pavel Machek66101de2008-10-01 14:36:56 +020042
Pekka Enbergf37435c2008-10-22 11:01:47 +030043 dr = (struct usb_ctrlrequest *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue) + DataSize);
Pavel Machek66101de2008-10-01 14:36:56 +020044 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE;
Lars Lindleyfa448c12010-03-25 14:44:53 +010045 dr->bRequest = 0x04; /* USB or vendor-defined request code, burst mode */
46 dr->wValue = cpu_to_le16(Flag); /* 0: Register number auto-increment, 1: No auto increment */
47 dr->wIndex = cpu_to_le16(RegisterNo);
48 dr->wLength = cpu_to_le16(DataSize);
Pekka Enbergf37435c2008-10-22 11:01:47 +030049 reg_queue->Next = NULL;
50 reg_queue->pUsbReq = dr;
51 reg_queue->urb = urb;
Pavel Machek66101de2008-10-01 14:36:56 +020052
Lars Lindleyfa448c12010-03-25 14:44:53 +010053 spin_lock_irq(&reg->EP0VM_spin_lock);
Pekka Enberg65144de2008-10-22 11:02:37 +030054 if (reg->reg_first == NULL)
55 reg->reg_first = reg_queue;
Pavel Machek66101de2008-10-01 14:36:56 +020056 else
Pekka Enberg65144de2008-10-22 11:02:37 +030057 reg->reg_last->Next = reg_queue;
58 reg->reg_last = reg_queue;
Pavel Machek66101de2008-10-01 14:36:56 +020059
Lars Lindleyfa448c12010-03-25 14:44:53 +010060 spin_unlock_irq(&reg->EP0VM_spin_lock);
Pavel Machek66101de2008-10-01 14:36:56 +020061
Lars Lindleyfa448c12010-03-25 14:44:53 +010062 /* Start EP0VM */
Pavel Machek66101de2008-10-01 14:36:56 +020063 Wb35Reg_EP0VM_start(pHwData);
64
Pekka Enberg279b6cc2008-10-27 22:46:39 +020065 return true;
Pavel Machek66101de2008-10-01 14:36:56 +020066 } else {
Pekka Enberga55a89b2008-10-22 11:01:16 +030067 if (urb)
68 usb_free_urb(urb);
Pekka Enbergf37435c2008-10-22 11:01:47 +030069 if (reg_queue)
70 kfree(reg_queue);
Pekka Enberg279b6cc2008-10-27 22:46:39 +020071 return false;
Pavel Machek66101de2008-10-01 14:36:56 +020072 }
Pekka Enberg279b6cc2008-10-27 22:46:39 +020073 return false;
Pavel Machek66101de2008-10-01 14:36:56 +020074}
75
Lars Lindleyfa448c12010-03-25 14:44:53 +010076void Wb35Reg_Update(struct hw_data *pHwData, u16 RegisterNo, u32 RegisterValue)
Pavel Machek66101de2008-10-01 14:36:56 +020077{
Pekka Enberg65144de2008-10-22 11:02:37 +030078 struct wb35_reg *reg = &pHwData->reg;
Pavel Machek66101de2008-10-01 14:36:56 +020079 switch (RegisterNo) {
Pekka Enberg65144de2008-10-22 11:02:37 +030080 case 0x3b0: reg->U1B0 = RegisterValue; break;
81 case 0x3bc: reg->U1BC_LEDConfigure = RegisterValue; break;
82 case 0x400: reg->D00_DmaControl = RegisterValue; break;
83 case 0x800: reg->M00_MacControl = RegisterValue; break;
84 case 0x804: reg->M04_MulticastAddress1 = RegisterValue; break;
85 case 0x808: reg->M08_MulticastAddress2 = RegisterValue; break;
86 case 0x824: reg->M24_MacControl = RegisterValue; break;
87 case 0x828: reg->M28_MacControl = RegisterValue; break;
88 case 0x82c: reg->M2C_MacControl = RegisterValue; break;
89 case 0x838: reg->M38_MacControl = RegisterValue; break;
90 case 0x840: reg->M40_MacControl = RegisterValue; break;
91 case 0x844: reg->M44_MacControl = RegisterValue; break;
92 case 0x848: reg->M48_MacControl = RegisterValue; break;
93 case 0x84c: reg->M4C_MacStatus = RegisterValue; break;
94 case 0x860: reg->M60_MacControl = RegisterValue; break;
95 case 0x868: reg->M68_MacControl = RegisterValue; break;
96 case 0x870: reg->M70_MacControl = RegisterValue; break;
97 case 0x874: reg->M74_MacControl = RegisterValue; break;
98 case 0x878: reg->M78_ERPInformation = RegisterValue; break;
99 case 0x87C: reg->M7C_MacControl = RegisterValue; break;
100 case 0x880: reg->M80_MacControl = RegisterValue; break;
101 case 0x884: reg->M84_MacControl = RegisterValue; break;
102 case 0x888: reg->M88_MacControl = RegisterValue; break;
103 case 0x898: reg->M98_MacControl = RegisterValue; break;
104 case 0x100c: reg->BB0C = RegisterValue; break;
105 case 0x102c: reg->BB2C = RegisterValue; break;
106 case 0x1030: reg->BB30 = RegisterValue; break;
107 case 0x103c: reg->BB3C = RegisterValue; break;
108 case 0x1048: reg->BB48 = RegisterValue; break;
109 case 0x104c: reg->BB4C = RegisterValue; break;
110 case 0x1050: reg->BB50 = RegisterValue; break;
111 case 0x1054: reg->BB54 = RegisterValue; break;
112 case 0x1058: reg->BB58 = RegisterValue; break;
113 case 0x105c: reg->BB5C = RegisterValue; break;
114 case 0x1060: reg->BB60 = RegisterValue; break;
Pavel Machek66101de2008-10-01 14:36:56 +0200115 }
116}
117
Lars Lindleyfa448c12010-03-25 14:44:53 +0100118/*
119 * true : read command process successfully
120 * false : register not support
121 */
122unsigned char Wb35Reg_WriteSync(struct hw_data *pHwData, u16 RegisterNo, u32 RegisterValue)
Pavel Machek66101de2008-10-01 14:36:56 +0200123{
Pekka Enberg65144de2008-10-22 11:02:37 +0300124 struct wb35_reg *reg = &pHwData->reg;
Pavel Machek66101de2008-10-01 14:36:56 +0200125 int ret = -1;
126
Lars Lindleyfa448c12010-03-25 14:44:53 +0100127 /* Module shutdown */
Pavel Machek66101de2008-10-01 14:36:56 +0200128 if (pHwData->SurpriseRemove)
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200129 return false;
Pavel Machek66101de2008-10-01 14:36:56 +0200130
131 RegisterValue = cpu_to_le32(RegisterValue);
132
Lars Lindleyfa448c12010-03-25 14:44:53 +0100133 /* update the register by send usb message */
Pekka Enberg65144de2008-10-22 11:02:37 +0300134 reg->SyncIoPause = 1;
Pavel Machek66101de2008-10-01 14:36:56 +0200135
Lars Lindleyfa448c12010-03-25 14:44:53 +0100136 /* Wait until EP0VM stop */
Pekka Enberg65144de2008-10-22 11:02:37 +0300137 while (reg->EP0vm_state != VM_STOP)
Pekka Enberg34222e02008-10-22 19:07:03 +0300138 msleep(10);
Pavel Machek66101de2008-10-01 14:36:56 +0200139
Lars Lindleyfa448c12010-03-25 14:44:53 +0100140 /* Sync IoCallDriver */
Pekka Enberg65144de2008-10-22 11:02:37 +0300141 reg->EP0vm_state = VM_RUNNING;
Pekka Enberg2894c6c2010-11-28 23:00:08 +0200142 ret = usb_control_msg(pHwData->udev,
143 usb_sndctrlpipe(pHwData->udev, 0),
Pavel Machek66101de2008-10-01 14:36:56 +0200144 0x03, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
Lars Lindleyfa448c12010-03-25 14:44:53 +0100145 0x0, RegisterNo, &RegisterValue, 4, HZ * 100);
Pekka Enberg65144de2008-10-22 11:02:37 +0300146 reg->EP0vm_state = VM_STOP;
147 reg->SyncIoPause = 0;
Pavel Machek66101de2008-10-01 14:36:56 +0200148
149 Wb35Reg_EP0VM_start(pHwData);
150
151 if (ret < 0) {
Pekka Enberg2855bb72010-11-28 23:00:00 +0200152 pr_debug("EP0 Write register usb message sending error\n");
Lars Lindleyfa448c12010-03-25 14:44:53 +0100153 pHwData->SurpriseRemove = 1;
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200154 return false;
Pavel Machek66101de2008-10-01 14:36:56 +0200155 }
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200156 return true;
Pavel Machek66101de2008-10-01 14:36:56 +0200157}
158
Lars Lindleyfa448c12010-03-25 14:44:53 +0100159/*
160 * true : read command process successfully
161 * false : register not support
162 */
163unsigned char Wb35Reg_Write(struct hw_data *pHwData, u16 RegisterNo, u32 RegisterValue)
Pavel Machek66101de2008-10-01 14:36:56 +0200164{
Lars Lindleyfa448c12010-03-25 14:44:53 +0100165 struct wb35_reg *reg = &pHwData->reg;
166 struct usb_ctrlrequest *dr;
167 struct urb *urb = NULL;
168 struct wb35_reg_queue *reg_queue = NULL;
169 u16 UrbSize;
Pavel Machek66101de2008-10-01 14:36:56 +0200170
Lars Lindleyfa448c12010-03-25 14:44:53 +0100171 /* Module shutdown */
Pavel Machek66101de2008-10-01 14:36:56 +0200172 if (pHwData->SurpriseRemove)
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200173 return false;
Pavel Machek66101de2008-10-01 14:36:56 +0200174
Lars Lindleyfa448c12010-03-25 14:44:53 +0100175 /* update the register by send urb request */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300176 UrbSize = sizeof(struct wb35_reg_queue) + sizeof(struct usb_ctrlrequest);
Pekka Enbergc8b2b702008-10-27 22:47:12 +0200177 reg_queue = kzalloc(UrbSize, GFP_ATOMIC);
Greg Kroah-Hartmanf3d20182008-10-27 14:21:24 -0700178 urb = usb_alloc_urb(0, GFP_ATOMIC);
Pekka Enbergf37435c2008-10-22 11:01:47 +0300179 if (urb && reg_queue) {
Lars Lindleyfa448c12010-03-25 14:44:53 +0100180 reg_queue->DIRECT = 1; /* burst write register */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300181 reg_queue->INDEX = RegisterNo;
182 reg_queue->VALUE = cpu_to_le32(RegisterValue);
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200183 reg_queue->RESERVED_VALID = false;
Pekka Enbergf37435c2008-10-22 11:01:47 +0300184 dr = (struct usb_ctrlrequest *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue));
Lars Lindleyfa448c12010-03-25 14:44:53 +0100185 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE;
186 dr->bRequest = 0x03; /* USB or vendor-defined request code, burst mode */
Pavel Machek66101de2008-10-01 14:36:56 +0200187 dr->wValue = cpu_to_le16(0x0);
188 dr->wIndex = cpu_to_le16(RegisterNo);
189 dr->wLength = cpu_to_le16(4);
190
Lars Lindleyfa448c12010-03-25 14:44:53 +0100191 /* Enter the sending queue */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300192 reg_queue->Next = NULL;
193 reg_queue->pUsbReq = dr;
194 reg_queue->urb = urb;
Pavel Machek66101de2008-10-01 14:36:56 +0200195
Lars Lindleyfa448c12010-03-25 14:44:53 +0100196 spin_lock_irq(&reg->EP0VM_spin_lock);
Pekka Enberg65144de2008-10-22 11:02:37 +0300197 if (reg->reg_first == NULL)
198 reg->reg_first = reg_queue;
Pavel Machek66101de2008-10-01 14:36:56 +0200199 else
Pekka Enberg65144de2008-10-22 11:02:37 +0300200 reg->reg_last->Next = reg_queue;
201 reg->reg_last = reg_queue;
Pavel Machek66101de2008-10-01 14:36:56 +0200202
Lars Lindleyfa448c12010-03-25 14:44:53 +0100203 spin_unlock_irq(&reg->EP0VM_spin_lock);
Pavel Machek66101de2008-10-01 14:36:56 +0200204
Lars Lindleyfa448c12010-03-25 14:44:53 +0100205 /* Start EP0VM */
Pavel Machek66101de2008-10-01 14:36:56 +0200206 Wb35Reg_EP0VM_start(pHwData);
207
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200208 return true;
Pavel Machek66101de2008-10-01 14:36:56 +0200209 } else {
Pekka Enberga55a89b2008-10-22 11:01:16 +0300210 if (urb)
211 usb_free_urb(urb);
Pekka Enbergf37435c2008-10-22 11:01:47 +0300212 kfree(reg_queue);
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200213 return false;
Pavel Machek66101de2008-10-01 14:36:56 +0200214 }
215}
216
Lars Lindleyfa448c12010-03-25 14:44:53 +0100217/*
218 * This command will be executed with a user defined value. When it completes,
219 * this value is useful. For example, hal_set_current_channel will use it.
220 * true : read command process successfully
221 * false : register not support
222 */
223unsigned char Wb35Reg_WriteWithCallbackValue(struct hw_data *pHwData,
224 u16 RegisterNo,
225 u32 RegisterValue,
226 s8 *pValue,
227 s8 Len)
Pavel Machek66101de2008-10-01 14:36:56 +0200228{
Lars Lindleyfa448c12010-03-25 14:44:53 +0100229 struct wb35_reg *reg = &pHwData->reg;
230 struct usb_ctrlrequest *dr;
231 struct urb *urb = NULL;
232 struct wb35_reg_queue *reg_queue = NULL;
233 u16 UrbSize;
Pavel Machek66101de2008-10-01 14:36:56 +0200234
Lars Lindleyfa448c12010-03-25 14:44:53 +0100235 /* Module shutdown */
Pavel Machek66101de2008-10-01 14:36:56 +0200236 if (pHwData->SurpriseRemove)
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200237 return false;
Pavel Machek66101de2008-10-01 14:36:56 +0200238
Lars Lindleyfa448c12010-03-25 14:44:53 +0100239 /* update the register by send urb request */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300240 UrbSize = sizeof(struct wb35_reg_queue) + sizeof(struct usb_ctrlrequest);
Pekka Enbergc8b2b702008-10-27 22:47:12 +0200241 reg_queue = kzalloc(UrbSize, GFP_ATOMIC);
Greg Kroah-Hartmanf3d20182008-10-27 14:21:24 -0700242 urb = usb_alloc_urb(0, GFP_ATOMIC);
Pekka Enbergf37435c2008-10-22 11:01:47 +0300243 if (urb && reg_queue) {
Lars Lindleyfa448c12010-03-25 14:44:53 +0100244 reg_queue->DIRECT = 1; /* burst write register */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300245 reg_queue->INDEX = RegisterNo;
246 reg_queue->VALUE = cpu_to_le32(RegisterValue);
Lars Lindleyfa448c12010-03-25 14:44:53 +0100247 /* NOTE : Users must guarantee the size of value will not exceed the buffer size. */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300248 memcpy(reg_queue->RESERVED, pValue, Len);
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200249 reg_queue->RESERVED_VALID = true;
Pekka Enbergf37435c2008-10-22 11:01:47 +0300250 dr = (struct usb_ctrlrequest *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue));
Lars Lindleyfa448c12010-03-25 14:44:53 +0100251 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE;
252 dr->bRequest = 0x03; /* USB or vendor-defined request code, burst mode */
Pavel Machek66101de2008-10-01 14:36:56 +0200253 dr->wValue = cpu_to_le16(0x0);
254 dr->wIndex = cpu_to_le16(RegisterNo);
255 dr->wLength = cpu_to_le16(4);
256
Lars Lindleyfa448c12010-03-25 14:44:53 +0100257 /* Enter the sending queue */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300258 reg_queue->Next = NULL;
259 reg_queue->pUsbReq = dr;
260 reg_queue->urb = urb;
Lars Lindleyfa448c12010-03-25 14:44:53 +0100261 spin_lock_irq(&reg->EP0VM_spin_lock);
262 if (reg->reg_first == NULL)
Pekka Enberg65144de2008-10-22 11:02:37 +0300263 reg->reg_first = reg_queue;
Pavel Machek66101de2008-10-01 14:36:56 +0200264 else
Pekka Enberg65144de2008-10-22 11:02:37 +0300265 reg->reg_last->Next = reg_queue;
266 reg->reg_last = reg_queue;
Pavel Machek66101de2008-10-01 14:36:56 +0200267
Lars Lindleyfa448c12010-03-25 14:44:53 +0100268 spin_unlock_irq(&reg->EP0VM_spin_lock);
Pavel Machek66101de2008-10-01 14:36:56 +0200269
Lars Lindleyfa448c12010-03-25 14:44:53 +0100270 /* Start EP0VM */
Pavel Machek66101de2008-10-01 14:36:56 +0200271 Wb35Reg_EP0VM_start(pHwData);
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200272 return true;
Pavel Machek66101de2008-10-01 14:36:56 +0200273 } else {
Pekka Enberga55a89b2008-10-22 11:01:16 +0300274 if (urb)
275 usb_free_urb(urb);
Pekka Enbergf37435c2008-10-22 11:01:47 +0300276 kfree(reg_queue);
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200277 return false;
Pavel Machek66101de2008-10-01 14:36:56 +0200278 }
279}
280
Lars Lindleyfa448c12010-03-25 14:44:53 +0100281/*
282 * true : read command process successfully
283 * false : register not support
284 * pRegisterValue : It must be a resident buffer due to
285 * asynchronous read register.
286 */
287unsigned char Wb35Reg_ReadSync(struct hw_data *pHwData, u16 RegisterNo, u32 *pRegisterValue)
Pavel Machek66101de2008-10-01 14:36:56 +0200288{
Pekka Enberg65144de2008-10-22 11:02:37 +0300289 struct wb35_reg *reg = &pHwData->reg;
Lars Lindleyfa448c12010-03-25 14:44:53 +0100290 u32 *pltmp = pRegisterValue;
291 int ret = -1;
Pavel Machek66101de2008-10-01 14:36:56 +0200292
Lars Lindleyfa448c12010-03-25 14:44:53 +0100293 /* Module shutdown */
Pavel Machek66101de2008-10-01 14:36:56 +0200294 if (pHwData->SurpriseRemove)
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200295 return false;
Pavel Machek66101de2008-10-01 14:36:56 +0200296
Lars Lindleyfa448c12010-03-25 14:44:53 +0100297 /* Read the register by send usb message */
Pekka Enberg65144de2008-10-22 11:02:37 +0300298 reg->SyncIoPause = 1;
Pavel Machek66101de2008-10-01 14:36:56 +0200299
Lars Lindleyfa448c12010-03-25 14:44:53 +0100300 /* Wait until EP0VM stop */
Pekka Enberg65144de2008-10-22 11:02:37 +0300301 while (reg->EP0vm_state != VM_STOP)
Pekka Enberg34222e02008-10-22 19:07:03 +0300302 msleep(10);
Pavel Machek66101de2008-10-01 14:36:56 +0200303
Pekka Enberg65144de2008-10-22 11:02:37 +0300304 reg->EP0vm_state = VM_RUNNING;
Pekka Enberg2894c6c2010-11-28 23:00:08 +0200305 ret = usb_control_msg(pHwData->udev,
306 usb_rcvctrlpipe(pHwData->udev, 0),
Lars Lindleyfa448c12010-03-25 14:44:53 +0100307 0x01, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
308 0x0, RegisterNo, pltmp, 4, HZ * 100);
Pavel Machek66101de2008-10-01 14:36:56 +0200309
310 *pRegisterValue = cpu_to_le32(*pltmp);
311
Pekka Enberg65144de2008-10-22 11:02:37 +0300312 reg->EP0vm_state = VM_STOP;
Pavel Machek66101de2008-10-01 14:36:56 +0200313
Lars Lindleyfa448c12010-03-25 14:44:53 +0100314 Wb35Reg_Update(pHwData, RegisterNo, *pRegisterValue);
Pekka Enberg65144de2008-10-22 11:02:37 +0300315 reg->SyncIoPause = 0;
Pavel Machek66101de2008-10-01 14:36:56 +0200316
Lars Lindleyfa448c12010-03-25 14:44:53 +0100317 Wb35Reg_EP0VM_start(pHwData);
Pavel Machek66101de2008-10-01 14:36:56 +0200318
319 if (ret < 0) {
Pekka Enberg2855bb72010-11-28 23:00:00 +0200320 pr_debug("EP0 Read register usb message sending error\n");
Lars Lindleyfa448c12010-03-25 14:44:53 +0100321 pHwData->SurpriseRemove = 1;
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200322 return false;
Pavel Machek66101de2008-10-01 14:36:56 +0200323 }
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200324 return true;
Pavel Machek66101de2008-10-01 14:36:56 +0200325}
326
Lars Lindleyfa448c12010-03-25 14:44:53 +0100327/*
328 * true : read command process successfully
329 * false : register not support
330 * pRegisterValue : It must be a resident buffer due to
331 * asynchronous read register.
332 */
333unsigned char Wb35Reg_Read(struct hw_data *pHwData, u16 RegisterNo, u32 *pRegisterValue)
Pavel Machek66101de2008-10-01 14:36:56 +0200334{
Lars Lindleyfa448c12010-03-25 14:44:53 +0100335 struct wb35_reg *reg = &pHwData->reg;
336 struct usb_ctrlrequest *dr;
337 struct urb *urb;
338 struct wb35_reg_queue *reg_queue;
339 u16 UrbSize;
Pavel Machek66101de2008-10-01 14:36:56 +0200340
Lars Lindleyfa448c12010-03-25 14:44:53 +0100341 /* Module shutdown */
Pavel Machek66101de2008-10-01 14:36:56 +0200342 if (pHwData->SurpriseRemove)
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200343 return false;
Pavel Machek66101de2008-10-01 14:36:56 +0200344
Lars Lindleyfa448c12010-03-25 14:44:53 +0100345 /* update the variable by send Urb to read register */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300346 UrbSize = sizeof(struct wb35_reg_queue) + sizeof(struct usb_ctrlrequest);
Pekka Enbergc8b2b702008-10-27 22:47:12 +0200347 reg_queue = kzalloc(UrbSize, GFP_ATOMIC);
Greg Kroah-Hartmanf3d20182008-10-27 14:21:24 -0700348 urb = usb_alloc_urb(0, GFP_ATOMIC);
Lars Lindleyfa448c12010-03-25 14:44:53 +0100349 if (urb && reg_queue) {
350 reg_queue->DIRECT = 0; /* read register */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300351 reg_queue->INDEX = RegisterNo;
352 reg_queue->pBuffer = pRegisterValue;
353 dr = (struct usb_ctrlrequest *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue));
Lars Lindleyfa448c12010-03-25 14:44:53 +0100354 dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN;
355 dr->bRequest = 0x01; /* USB or vendor-defined request code, burst mode */
Pavel Machek66101de2008-10-01 14:36:56 +0200356 dr->wValue = cpu_to_le16(0x0);
Lars Lindleyfa448c12010-03-25 14:44:53 +0100357 dr->wIndex = cpu_to_le16(RegisterNo);
358 dr->wLength = cpu_to_le16(4);
Pavel Machek66101de2008-10-01 14:36:56 +0200359
Lars Lindleyfa448c12010-03-25 14:44:53 +0100360 /* Enter the sending queue */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300361 reg_queue->Next = NULL;
362 reg_queue->pUsbReq = dr;
363 reg_queue->urb = urb;
Lars Lindleyfa448c12010-03-25 14:44:53 +0100364 spin_lock_irq(&reg->EP0VM_spin_lock);
365 if (reg->reg_first == NULL)
Pekka Enberg65144de2008-10-22 11:02:37 +0300366 reg->reg_first = reg_queue;
Pavel Machek66101de2008-10-01 14:36:56 +0200367 else
Pekka Enberg65144de2008-10-22 11:02:37 +0300368 reg->reg_last->Next = reg_queue;
369 reg->reg_last = reg_queue;
Pavel Machek66101de2008-10-01 14:36:56 +0200370
Lars Lindleyfa448c12010-03-25 14:44:53 +0100371 spin_unlock_irq(&reg->EP0VM_spin_lock);
Pavel Machek66101de2008-10-01 14:36:56 +0200372
Lars Lindleyfa448c12010-03-25 14:44:53 +0100373 /* Start EP0VM */
374 Wb35Reg_EP0VM_start(pHwData);
Pavel Machek66101de2008-10-01 14:36:56 +0200375
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200376 return true;
Pavel Machek66101de2008-10-01 14:36:56 +0200377 } else {
Pekka Enberga55a89b2008-10-22 11:01:16 +0300378 if (urb)
Lars Lindleyfa448c12010-03-25 14:44:53 +0100379 usb_free_urb(urb);
Pekka Enbergf37435c2008-10-22 11:01:47 +0300380 kfree(reg_queue);
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200381 return false;
Pavel Machek66101de2008-10-01 14:36:56 +0200382 }
383}
384
385
Lars Lindleyfa448c12010-03-25 14:44:53 +0100386void Wb35Reg_EP0VM_start(struct hw_data *pHwData)
Pavel Machek66101de2008-10-01 14:36:56 +0200387{
Pekka Enberg65144de2008-10-22 11:02:37 +0300388 struct wb35_reg *reg = &pHwData->reg;
Pavel Machek66101de2008-10-01 14:36:56 +0200389
Pekka Enberg44e85412008-10-29 20:10:32 +0200390 if (atomic_inc_return(&reg->RegFireCount) == 1) {
Pekka Enberg65144de2008-10-22 11:02:37 +0300391 reg->EP0vm_state = VM_RUNNING;
Pavel Machek66101de2008-10-01 14:36:56 +0200392 Wb35Reg_EP0VM(pHwData);
393 } else
Pekka Enberg44e85412008-10-29 20:10:32 +0200394 atomic_dec(&reg->RegFireCount);
Pavel Machek66101de2008-10-01 14:36:56 +0200395}
396
Lars Lindleyfa448c12010-03-25 14:44:53 +0100397void Wb35Reg_EP0VM(struct hw_data *pHwData)
Pavel Machek66101de2008-10-01 14:36:56 +0200398{
Lars Lindleyfa448c12010-03-25 14:44:53 +0100399 struct wb35_reg *reg = &pHwData->reg;
400 struct urb *urb;
401 struct usb_ctrlrequest *dr;
402 u32 *pBuffer;
Pavel Machek66101de2008-10-01 14:36:56 +0200403 int ret = -1;
Lars Lindleyfa448c12010-03-25 14:44:53 +0100404 struct wb35_reg_queue *reg_queue;
Pavel Machek66101de2008-10-01 14:36:56 +0200405
406
Pekka Enberg65144de2008-10-22 11:02:37 +0300407 if (reg->SyncIoPause)
Pavel Machek66101de2008-10-01 14:36:56 +0200408 goto cleanup;
409
410 if (pHwData->SurpriseRemove)
411 goto cleanup;
412
Lars Lindleyfa448c12010-03-25 14:44:53 +0100413 /* Get the register data and send to USB through Irp */
414 spin_lock_irq(&reg->EP0VM_spin_lock);
Pekka Enberg65144de2008-10-22 11:02:37 +0300415 reg_queue = reg->reg_first;
Lars Lindleyfa448c12010-03-25 14:44:53 +0100416 spin_unlock_irq(&reg->EP0VM_spin_lock);
Pavel Machek66101de2008-10-01 14:36:56 +0200417
Pekka Enbergf37435c2008-10-22 11:01:47 +0300418 if (!reg_queue)
Pavel Machek66101de2008-10-01 14:36:56 +0200419 goto cleanup;
420
Lars Lindleyfa448c12010-03-25 14:44:53 +0100421 /* Get an Urb, send it */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300422 urb = (struct urb *)reg_queue->urb;
Pavel Machek66101de2008-10-01 14:36:56 +0200423
Pekka Enbergf37435c2008-10-22 11:01:47 +0300424 dr = reg_queue->pUsbReq;
425 urb = reg_queue->urb;
426 pBuffer = reg_queue->pBuffer;
Lars Lindleyfa448c12010-03-25 14:44:53 +0100427 if (reg_queue->DIRECT == 1) /* output */
Pekka Enbergf37435c2008-10-22 11:01:47 +0300428 pBuffer = &reg_queue->VALUE;
Pavel Machek66101de2008-10-01 14:36:56 +0200429
Pekka Enberg2894c6c2010-11-28 23:00:08 +0200430 usb_fill_control_urb(urb, pHwData->udev,
431 REG_DIRECTION(pHwData->udev, reg_queue),
Lars Lindleyfa448c12010-03-25 14:44:53 +0100432 (u8 *)dr, pBuffer, cpu_to_le16(dr->wLength),
433 Wb35Reg_EP0VM_complete, (void *)pHwData);
Pavel Machek66101de2008-10-01 14:36:56 +0200434
Pekka Enberg65144de2008-10-22 11:02:37 +0300435 reg->EP0vm_state = VM_RUNNING;
Pavel Machek66101de2008-10-01 14:36:56 +0200436
Greg Kroah-Hartman7c126042008-10-27 14:21:24 -0700437 ret = usb_submit_urb(urb, GFP_ATOMIC);
Pavel Machek66101de2008-10-01 14:36:56 +0200438
439 if (ret < 0) {
Pekka Enberg2855bb72010-11-28 23:00:00 +0200440 pr_debug("EP0 Irp sending error\n");
Pavel Machek66101de2008-10-01 14:36:56 +0200441 goto cleanup;
442 }
Pavel Machek66101de2008-10-01 14:36:56 +0200443 return;
444
445 cleanup:
Pekka Enberg65144de2008-10-22 11:02:37 +0300446 reg->EP0vm_state = VM_STOP;
Pekka Enberg44e85412008-10-29 20:10:32 +0200447 atomic_dec(&reg->RegFireCount);
Pavel Machek66101de2008-10-01 14:36:56 +0200448}
449
450
Lars Lindleyfa448c12010-03-25 14:44:53 +0100451void Wb35Reg_EP0VM_complete(struct urb *urb)
Pavel Machek66101de2008-10-01 14:36:56 +0200452{
Lars Lindleyfa448c12010-03-25 14:44:53 +0100453 struct hw_data *pHwData = (struct hw_data *)urb->context;
454 struct wb35_reg *reg = &pHwData->reg;
455 struct wb35_reg_queue *reg_queue;
Pavel Machek66101de2008-10-01 14:36:56 +0200456
457
Lars Lindleyfa448c12010-03-25 14:44:53 +0100458 /* Variable setting */
Pekka Enberg65144de2008-10-22 11:02:37 +0300459 reg->EP0vm_state = VM_COMPLETED;
460 reg->EP0VM_status = urb->status;
Pavel Machek66101de2008-10-01 14:36:56 +0200461
Lars Lindleyfa448c12010-03-25 14:44:53 +0100462 if (pHwData->SurpriseRemove) { /* Let WbWlanHalt to handle surprise remove */
Pekka Enberg65144de2008-10-22 11:02:37 +0300463 reg->EP0vm_state = VM_STOP;
Pekka Enberg44e85412008-10-29 20:10:32 +0200464 atomic_dec(&reg->RegFireCount);
Pavel Machek66101de2008-10-01 14:36:56 +0200465 } else {
Lars Lindleyfa448c12010-03-25 14:44:53 +0100466 /* Complete to send, remove the URB from the first */
467 spin_lock_irq(&reg->EP0VM_spin_lock);
Pekka Enberg65144de2008-10-22 11:02:37 +0300468 reg_queue = reg->reg_first;
469 if (reg_queue == reg->reg_last)
470 reg->reg_last = NULL;
471 reg->reg_first = reg->reg_first->Next;
Lars Lindleyfa448c12010-03-25 14:44:53 +0100472 spin_unlock_irq(&reg->EP0VM_spin_lock);
Pavel Machek66101de2008-10-01 14:36:56 +0200473
Pekka Enberg65144de2008-10-22 11:02:37 +0300474 if (reg->EP0VM_status) {
Pekka Enberg2855bb72010-11-28 23:00:00 +0200475 pr_debug("EP0 IoCompleteRoutine return error\n");
Pekka Enberg65144de2008-10-22 11:02:37 +0300476 reg->EP0vm_state = VM_STOP;
Pavel Machek66101de2008-10-01 14:36:56 +0200477 pHwData->SurpriseRemove = 1;
478 } else {
Lars Lindleyfa448c12010-03-25 14:44:53 +0100479 /* Success. Update the result */
Pavel Machek66101de2008-10-01 14:36:56 +0200480
Lars Lindleyfa448c12010-03-25 14:44:53 +0100481 /* Start the next send */
Pavel Machek66101de2008-10-01 14:36:56 +0200482 Wb35Reg_EP0VM(pHwData);
483 }
484
Lars Lindleyfa448c12010-03-25 14:44:53 +0100485 kfree(reg_queue);
Pavel Machek66101de2008-10-01 14:36:56 +0200486 }
487
Pekka Enberga55a89b2008-10-22 11:01:16 +0300488 usb_free_urb(urb);
Pavel Machek66101de2008-10-01 14:36:56 +0200489}
490
491
Lars Lindleyfa448c12010-03-25 14:44:53 +0100492void Wb35Reg_destroy(struct hw_data *pHwData)
Pavel Machek66101de2008-10-01 14:36:56 +0200493{
Lars Lindleyfa448c12010-03-25 14:44:53 +0100494 struct wb35_reg *reg = &pHwData->reg;
495 struct urb *urb;
496 struct wb35_reg_queue *reg_queue;
Pavel Machek66101de2008-10-01 14:36:56 +0200497
498 Uxx_power_off_procedure(pHwData);
499
Lars Lindleyfa448c12010-03-25 14:44:53 +0100500 /* Wait for Reg operation completed */
Pavel Machek66101de2008-10-01 14:36:56 +0200501 do {
Lars Lindleyfa448c12010-03-25 14:44:53 +0100502 msleep(10); /* Delay for waiting function enter */
Pekka Enberg65144de2008-10-22 11:02:37 +0300503 } while (reg->EP0vm_state != VM_STOP);
Lars Lindleyfa448c12010-03-25 14:44:53 +0100504 msleep(10); /* Delay for waiting function enter */
Pavel Machek66101de2008-10-01 14:36:56 +0200505
Lars Lindleyfa448c12010-03-25 14:44:53 +0100506 /* Release all the data in RegQueue */
507 spin_lock_irq(&reg->EP0VM_spin_lock);
Pekka Enberg65144de2008-10-22 11:02:37 +0300508 reg_queue = reg->reg_first;
Pekka Enbergf37435c2008-10-22 11:01:47 +0300509 while (reg_queue) {
Pekka Enberg65144de2008-10-22 11:02:37 +0300510 if (reg_queue == reg->reg_last)
511 reg->reg_last = NULL;
512 reg->reg_first = reg->reg_first->Next;
Pavel Machek66101de2008-10-01 14:36:56 +0200513
Pekka Enbergf37435c2008-10-22 11:01:47 +0300514 urb = reg_queue->urb;
Lars Lindleyfa448c12010-03-25 14:44:53 +0100515 spin_unlock_irq(&reg->EP0VM_spin_lock);
Pekka Enberga55a89b2008-10-22 11:01:16 +0300516 if (urb) {
517 usb_free_urb(urb);
Pekka Enbergf37435c2008-10-22 11:01:47 +0300518 kfree(reg_queue);
Pavel Machek66101de2008-10-01 14:36:56 +0200519 } else {
Pekka Enberg2855bb72010-11-28 23:00:00 +0200520 pr_debug("EP0 queue release error\n");
Pavel Machek66101de2008-10-01 14:36:56 +0200521 }
Lars Lindleyfa448c12010-03-25 14:44:53 +0100522 spin_lock_irq(&reg->EP0VM_spin_lock);
Pavel Machek66101de2008-10-01 14:36:56 +0200523
Pekka Enberg65144de2008-10-22 11:02:37 +0300524 reg_queue = reg->reg_first;
Pavel Machek66101de2008-10-01 14:36:56 +0200525 }
Lars Lindleyfa448c12010-03-25 14:44:53 +0100526 spin_unlock_irq(&reg->EP0VM_spin_lock);
Pavel Machek66101de2008-10-01 14:36:56 +0200527}
528
Lars Lindleyfa448c12010-03-25 14:44:53 +0100529/*
530 * =======================================================================
531 * The function can be run in passive-level only.
532 * =========================================================================
533 */
534unsigned char Wb35Reg_initial(struct hw_data *pHwData)
Pavel Machek66101de2008-10-01 14:36:56 +0200535{
Lars Lindleyfa448c12010-03-25 14:44:53 +0100536 struct wb35_reg *reg = &pHwData->reg;
Pavel Machek66101de2008-10-01 14:36:56 +0200537 u32 ltmp;
538 u32 SoftwareSet, VCO_trim, TxVga, Region_ScanInterval;
539
Lars Lindleyfa448c12010-03-25 14:44:53 +0100540 /* Spin lock is acquired for read and write IRP command */
541 spin_lock_init(&reg->EP0VM_spin_lock);
Pavel Machek66101de2008-10-01 14:36:56 +0200542
Lars Lindleyfa448c12010-03-25 14:44:53 +0100543 /* Getting RF module type from EEPROM */
544 Wb35Reg_WriteSync(pHwData, 0x03b4, 0x080d0000); /* Start EEPROM access + Read + address(0x0d) */
545 Wb35Reg_ReadSync(pHwData, 0x03b4, &ltmp);
Pavel Machek66101de2008-10-01 14:36:56 +0200546
Lars Lindleyfa448c12010-03-25 14:44:53 +0100547 /* Update RF module type and determine the PHY type by inf or EEPROM */
548 reg->EEPROMPhyType = (u8)(ltmp & 0xff);
549 /*
550 * 0 V MAX2825, 1 V MAX2827, 2 V MAX2828, 3 V MAX2829
551 * 16V AL2230, 17 - AL7230, 18 - AL2230S
552 * 32 Reserved
553 * 33 - W89RF242(TxVGA 0~19), 34 - W89RF242(TxVGA 0~34)
554 */
Pekka Enberg65144de2008-10-22 11:02:37 +0300555 if (reg->EEPROMPhyType != RF_DECIDE_BY_INF) {
Lars Lindleyfa448c12010-03-25 14:44:53 +0100556 if ((reg->EEPROMPhyType == RF_MAXIM_2825) ||
Pekka Enberg65144de2008-10-22 11:02:37 +0300557 (reg->EEPROMPhyType == RF_MAXIM_2827) ||
558 (reg->EEPROMPhyType == RF_MAXIM_2828) ||
559 (reg->EEPROMPhyType == RF_MAXIM_2829) ||
560 (reg->EEPROMPhyType == RF_MAXIM_V1) ||
561 (reg->EEPROMPhyType == RF_AIROHA_2230) ||
Lars Lindleyfa448c12010-03-25 14:44:53 +0100562 (reg->EEPROMPhyType == RF_AIROHA_2230S) ||
Pekka Enberg65144de2008-10-22 11:02:37 +0300563 (reg->EEPROMPhyType == RF_AIROHA_7230) ||
Lars Lindleyfa448c12010-03-25 14:44:53 +0100564 (reg->EEPROMPhyType == RF_WB_242) ||
Pekka Enberg65144de2008-10-22 11:02:37 +0300565 (reg->EEPROMPhyType == RF_WB_242_1))
566 pHwData->phy_type = reg->EEPROMPhyType;
Pavel Machek66101de2008-10-01 14:36:56 +0200567 }
568
Lars Lindleyfa448c12010-03-25 14:44:53 +0100569 /* Power On procedure running. The relative parameter will be set according to phy_type */
570 Uxx_power_on_procedure(pHwData);
Pavel Machek66101de2008-10-01 14:36:56 +0200571
Lars Lindleyfa448c12010-03-25 14:44:53 +0100572 /* Reading MAC address */
573 Uxx_ReadEthernetAddress(pHwData);
Pavel Machek66101de2008-10-01 14:36:56 +0200574
Lars Lindleyfa448c12010-03-25 14:44:53 +0100575 /* Read VCO trim for RF parameter */
576 Wb35Reg_WriteSync(pHwData, 0x03b4, 0x08200000);
577 Wb35Reg_ReadSync(pHwData, 0x03b4, &VCO_trim);
Pavel Machek66101de2008-10-01 14:36:56 +0200578
Lars Lindleyfa448c12010-03-25 14:44:53 +0100579 /* Read Antenna On/Off of software flag */
580 Wb35Reg_WriteSync(pHwData, 0x03b4, 0x08210000);
581 Wb35Reg_ReadSync(pHwData, 0x03b4, &SoftwareSet);
Pavel Machek66101de2008-10-01 14:36:56 +0200582
Lars Lindleyfa448c12010-03-25 14:44:53 +0100583 /* Read TXVGA */
584 Wb35Reg_WriteSync(pHwData, 0x03b4, 0x08100000);
585 Wb35Reg_ReadSync(pHwData, 0x03b4, &TxVga);
Pavel Machek66101de2008-10-01 14:36:56 +0200586
Lars Lindleyfa448c12010-03-25 14:44:53 +0100587 /* Get Scan interval setting from EEPROM offset 0x1c */
588 Wb35Reg_WriteSync(pHwData, 0x03b4, 0x081d0000);
589 Wb35Reg_ReadSync(pHwData, 0x03b4, &Region_ScanInterval);
Pavel Machek66101de2008-10-01 14:36:56 +0200590
Lars Lindleyfa448c12010-03-25 14:44:53 +0100591 /* Update Ethernet address */
592 memcpy(pHwData->CurrentMacAddress, pHwData->PermanentMacAddress, ETH_ALEN);
Pavel Machek66101de2008-10-01 14:36:56 +0200593
Lars Lindleyfa448c12010-03-25 14:44:53 +0100594 /* Update software variable */
Pavel Machek66101de2008-10-01 14:36:56 +0200595 pHwData->SoftwareSet = (u16)(SoftwareSet & 0xffff);
596 TxVga &= 0x000000ff;
597 pHwData->PowerIndexFromEEPROM = (u8)TxVga;
598 pHwData->VCO_trim = (u8)VCO_trim & 0xff;
599 if (pHwData->VCO_trim == 0xff)
600 pHwData->VCO_trim = 0x28;
601
Lars Lindleyfa448c12010-03-25 14:44:53 +0100602 reg->EEPROMRegion = (u8)(Region_ScanInterval >> 8);
603 if (reg->EEPROMRegion < 1 || reg->EEPROMRegion > 6)
Pekka Enberg65144de2008-10-22 11:02:37 +0300604 reg->EEPROMRegion = REGION_AUTO;
Pavel Machek66101de2008-10-01 14:36:56 +0200605
Lars Lindleyfa448c12010-03-25 14:44:53 +0100606 /* For Get Tx VGA from EEPROM */
607 GetTxVgaFromEEPROM(pHwData);
Pavel Machek66101de2008-10-01 14:36:56 +0200608
Lars Lindleyfa448c12010-03-25 14:44:53 +0100609 /* Set Scan Interval */
Pavel Machek66101de2008-10-01 14:36:56 +0200610 pHwData->Scan_Interval = (u8)(Region_ScanInterval & 0xff) * 10;
Lars Lindleyfa448c12010-03-25 14:44:53 +0100611 if ((pHwData->Scan_Interval == 2550) || (pHwData->Scan_Interval < 10)) /* Is default setting 0xff * 10 */
Pavel Machek66101de2008-10-01 14:36:56 +0200612 pHwData->Scan_Interval = SCAN_MAX_CHNL_TIME;
613
Lars Lindleyfa448c12010-03-25 14:44:53 +0100614 /* Initial register */
Pavel Machek66101de2008-10-01 14:36:56 +0200615 RFSynthesizer_initial(pHwData);
616
Lars Lindleyfa448c12010-03-25 14:44:53 +0100617 BBProcessor_initial(pHwData); /* Async write, must wait until complete */
Pavel Machek66101de2008-10-01 14:36:56 +0200618
619 Wb35Reg_phy_calibration(pHwData);
620
621 Mxx_initial(pHwData);
622 Dxx_initial(pHwData);
623
624 if (pHwData->SurpriseRemove)
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200625 return false;
Pavel Machek66101de2008-10-01 14:36:56 +0200626 else
Lars Lindleyfa448c12010-03-25 14:44:53 +0100627 return true; /* Initial fail */
Pavel Machek66101de2008-10-01 14:36:56 +0200628}
629
Lars Lindleyfa448c12010-03-25 14:44:53 +0100630/*
631 * ================================================================
632 * CardComputeCrc --
633 *
634 * Description:
635 * Runs the AUTODIN II CRC algorithm on buffer Buffer of length, Length.
636 *
637 * Arguments:
638 * Buffer - the input buffer
639 * Length - the length of Buffer
640 *
641 * Return Value:
642 * The 32-bit CRC value.
643 * ===================================================================
644 */
645u32 CardComputeCrc(u8 *Buffer, u32 Length)
Pavel Machek66101de2008-10-01 14:36:56 +0200646{
Lars Lindleyfa448c12010-03-25 14:44:53 +0100647 u32 Crc, Carry;
648 u32 i, j;
649 u8 CurByte;
Pavel Machek66101de2008-10-01 14:36:56 +0200650
Lars Lindleyfa448c12010-03-25 14:44:53 +0100651 Crc = 0xffffffff;
Pavel Machek66101de2008-10-01 14:36:56 +0200652
Lars Lindleyfa448c12010-03-25 14:44:53 +0100653 for (i = 0; i < Length; i++) {
654 CurByte = Buffer[i];
655 for (j = 0; j < 8; j++) {
656 Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
657 Crc <<= 1;
658 CurByte >>= 1;
659 if (Carry)
660 Crc = (Crc ^ 0x04c11db6) | Carry;
661 }
662 }
663 return Crc;
Pavel Machek66101de2008-10-01 14:36:56 +0200664}
665
666
Lars Lindleyfa448c12010-03-25 14:44:53 +0100667/*
668 * ==================================================================
669 * BitReverse --
670 * Reverse the bits in the input argument, dwData, which is
671 * regarded as a string of bits with the length, DataLength.
672 *
673 * Arguments:
674 * dwData :
675 * DataLength :
676 *
677 * Return:
678 * The converted value.
679 * ==================================================================
680 */
681u32 BitReverse(u32 dwData, u32 DataLength)
Pavel Machek66101de2008-10-01 14:36:56 +0200682{
Lars Lindleyfa448c12010-03-25 14:44:53 +0100683 u32 HalfLength, i, j;
684 u32 BitA, BitB;
Pavel Machek66101de2008-10-01 14:36:56 +0200685
Lars Lindleyfa448c12010-03-25 14:44:53 +0100686 if (DataLength <= 0)
687 return 0; /* No conversion is done. */
Pavel Machek66101de2008-10-01 14:36:56 +0200688 dwData = dwData & (0xffffffff >> (32 - DataLength));
689
690 HalfLength = DataLength / 2;
Lars Lindleyfa448c12010-03-25 14:44:53 +0100691 for (i = 0, j = DataLength - 1; i < HalfLength; i++, j--) {
692 BitA = GetBit(dwData, i);
693 BitB = GetBit(dwData, j);
Pavel Machek66101de2008-10-01 14:36:56 +0200694 if (BitA && !BitB) {
Lars Lindleyfa448c12010-03-25 14:44:53 +0100695 dwData = ClearBit(dwData, i);
696 dwData = SetBit(dwData, j);
Pavel Machek66101de2008-10-01 14:36:56 +0200697 } else if (!BitA && BitB) {
Lars Lindleyfa448c12010-03-25 14:44:53 +0100698 dwData = SetBit(dwData, i);
699 dwData = ClearBit(dwData, j);
700 } else {
701 /* Do nothing since these two bits are of the save values. */
Pavel Machek66101de2008-10-01 14:36:56 +0200702 }
703 }
Pavel Machek66101de2008-10-01 14:36:56 +0200704 return dwData;
705}
706
Lars Lindleyfa448c12010-03-25 14:44:53 +0100707void Wb35Reg_phy_calibration(struct hw_data *pHwData)
Pavel Machek66101de2008-10-01 14:36:56 +0200708{
Lars Lindleyfa448c12010-03-25 14:44:53 +0100709 u32 BB3c, BB54;
Pavel Machek66101de2008-10-01 14:36:56 +0200710
711 if ((pHwData->phy_type == RF_WB_242) ||
712 (pHwData->phy_type == RF_WB_242_1)) {
Lars Lindleyfa448c12010-03-25 14:44:53 +0100713 phy_calibration_winbond(pHwData, 2412); /* Sync operation */
714 Wb35Reg_ReadSync(pHwData, 0x103c, &BB3c);
715 Wb35Reg_ReadSync(pHwData, 0x1054, &BB54);
Pavel Machek66101de2008-10-01 14:36:56 +0200716
717 pHwData->BB3c_cal = BB3c;
718 pHwData->BB54_cal = BB54;
719
720 RFSynthesizer_initial(pHwData);
Lars Lindleyfa448c12010-03-25 14:44:53 +0100721 BBProcessor_initial(pHwData); /* Async operation */
Pavel Machek66101de2008-10-01 14:36:56 +0200722
Lars Lindleyfa448c12010-03-25 14:44:53 +0100723 Wb35Reg_WriteSync(pHwData, 0x103c, BB3c);
724 Wb35Reg_WriteSync(pHwData, 0x1054, BB54);
Pavel Machek66101de2008-10-01 14:36:56 +0200725 }
726}
727
728