1 /* shared patches for k2 and magpie */
10 #include "usbfifo_api.h"
14 #define USB_EP4_MAX_PKT_SIZE bUSB_EP_MAX_PKT_SIZE_64
15 #define USB_EP3_MAX_PKT_SIZE bUSB_EP_MAX_PKT_SIZE_64
17 extern USB_FIFO_CONFIG usbFifoConf;
18 extern Action eUsbCxFinishAction;
19 extern void _fw_usb_suspend_reboot();
21 typedef void (* USBFIFO_recv_command)(VBUF *cmd);
22 USBFIFO_recv_command m_origUsbfifoRecvCmd = NULL;
24 void _fw_usbfifo_recv_command(VBUF *buf)
29 cmd_data = (uint8_t *)(buf->desc_list->buf_addr +
30 buf->desc_list->data_offset);
31 tmp = *((uint32_t *)cmd_data);
32 if (tmp == 0xFFFFFFFF)
33 _fw_usb_suspend_reboot();
35 m_origUsbfifoRecvCmd(buf);
38 void _fw_usbfifo_init(USB_FIFO_CONFIG *pConfig)
40 m_origUsbfifoRecvCmd = pConfig->recv_command;
42 usbFifoConf.get_command_buf = pConfig->get_command_buf;
43 usbFifoConf.recv_command = _fw_usbfifo_recv_command;
44 usbFifoConf.get_event_buf = pConfig->get_event_buf;
45 usbFifoConf.send_event_done = pConfig->send_event_done;
48 void cold_reboot(void)
50 A_PRINTF("Cold reboot initiated.");
51 #if defined(PROJECT_MAGPIE)
52 HAL_WORD_REG_WRITE(WATCH_DOG_MAGIC_PATTERN_ADDR, 0);
53 #elif defined(PROJECT_K2)
54 HAL_WORD_REG_WRITE(MAGPIE_REG_RST_STATUS_ADDR, 0);
55 #endif /* #if defined(PROJECT_MAGPIE) */
60 * support more than 64 bytes command on ep3
62 void usb_status_in_patch(void)
67 static uint16_t buf_len;
68 static VBUF *evntbuf = NULL;
69 static volatile uint32_t *regaddr;
70 static BOOLEAN cmd_is_new = TRUE;
71 BOOLEAN cmd_end = FALSE;
74 evntbuf = usbFifoConf.get_event_buf();
75 if (evntbuf != NULL) {
76 regaddr = (uint32_t *)VBUF_GET_DATA_ADDR(evntbuf);
77 buf_len = evntbuf->buf_length;
79 mUSB_STATUS_IN_INT_DISABLE();
86 if (buf_len > USB_EP3_MAX_PKT_SIZE) {
87 reg_buf_len = USB_EP3_MAX_PKT_SIZE;
88 buf_len -= USB_EP3_MAX_PKT_SIZE;
91 * controller supposed will take care of zero-length? */
93 reg_buf_len = buf_len;
98 for (count = 0; count < (reg_buf_len / 4); count++)
100 USB_WORD_REG_WRITE(ZM_EP3_DATA_OFFSET, *regaddr);
104 remainder = reg_buf_len % 4;
109 USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x7);
112 USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x3);
115 USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
119 USB_WORD_REG_WRITE(ZM_EP3_DATA_OFFSET, *regaddr);
121 /* Restore CBus FIFO size to word size */
122 USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
125 mUSB_EP3_XFER_DONE();
127 if (evntbuf != NULL && cmd_end) {
128 usbFifoConf.send_event_done(evntbuf);
134 * support more than 64 bytes command on ep4
136 void usb_reg_out_patch(void)
141 static volatile uint32_t *regaddr;
142 static uint16_t cmd_len;
144 BOOLEAN cmd_is_last = FALSE;
145 static BOOLEAN cmd_is_new = TRUE;
147 /* get the size of this transcation */
148 usbfifolen = USB_BYTE_REG_READ(ZM_EP4_BYTE_COUNT_LOW_OFFSET);
150 if (usbfifolen > USB_EP4_MAX_PKT_SIZE) {
151 A_PRINTF("EP4 FIFO Bug? Buffer is too big: %x\n", usbfifolen);
155 /* check is command is new */
158 buf = usbFifoConf.get_command_buf();
162 A_PRINTF("%s: Filed to get new buffer.\n", __func__);
166 /* copy free, assignment buffer of the address */
167 regaddr = (uint32_t *)buf->desc_list->buf_addr;
172 /* just in case, suppose should not happen */
176 /* if size is smaller, this is the last command!
177 * zero-length supposed should be set through 0x27/bit7->0x19/bit4, not here
179 if(usbfifolen < USB_EP4_MAX_PKT_SIZE)
182 /* accumulate the size */
183 cmd_len += usbfifolen;
185 if (cmd_len > buf->desc_list->buf_size) {
186 A_PRINTF("%s: Data length on EP4 FIFO is bigger as "
187 "allocated buffer data! Drop it!\n", __func__);
191 /* round it to alignment */
193 usbfifolen = (usbfifolen >> 2) + 1;
195 usbfifolen = usbfifolen >> 2;
197 /* retrieve the data from fifo */
198 for(ii = 0; ii < usbfifolen; ii++) {
199 /* read fifo data out */
200 ep4_data = USB_WORD_REG_READ(ZM_EP4_DATA_OFFSET);
205 /* if this is the last command, callback to HTC */
207 buf->desc_list->next_desc = NULL;
208 buf->desc_list->data_offset = 0;
209 buf->desc_list->data_size = cmd_len;
210 buf->desc_list->control = 0;
211 buf->next_buf = NULL;
212 buf->buf_length = cmd_len;
214 usbFifoConf.recv_command(buf);
221 /* we might get no command buffer here?
222 * but if we return here, the ep4 fifo will be lock out,
223 * so that we still read them out but just drop it? */
224 for(ii = 0; ii < usbfifolen; ii++)
225 ep4_data = USB_WORD_REG_READ(ZM_EP4_DATA_OFFSET);
228 /* mUSB_STATUS_IN_INT_ENABLE(); */
235 * - theoretically ep6 configured same way as ep1
236 * so, if there are some problems we should have it
238 * - do we really need support usb1.1?
240 extern uint16_t u8UsbConfigValue;
241 extern uint16_t u8UsbInterfaceValue;
242 extern uint16_t u8UsbInterfaceAlternateSetting;
243 extern SetupPacket ControlCmd;
244 extern void vUsbClrEPx(void);
246 #undef FS_C1_I0_A0_EP_NUMBER
247 #define FS_C1_I0_A0_EP_NUMBER 6
249 #define FS_C1_I0_A0_EP6_BLKSIZE BLK512BYTE
250 #define FS_C1_I0_A0_EP6_BLKNO DOUBLE_BLK
251 #define FS_C1_I0_A0_EP6_DIRECTION DIRECTION_OUT
252 #define FS_C1_I0_A0_EP6_TYPE TF_TYPE_BULK
253 #define FS_C1_I0_A0_EP6_MAX_PACKET 0x0040
254 #define FS_C1_I0_A0_EP6_bInterval 0
257 #define FS_C1_I0_A0_EP6_FIFO_START \
258 (FS_C1_I0_A0_EP5_FIFO_START + FS_C1_I0_A0_EP5_FIFO_NO)
259 #define FS_C1_I0_A0_EP6_FIFO_NO \
260 (FS_C1_I0_A0_EP6_BLKNO * FS_C1_I0_A0_EP6_BLKSIZE)
261 #define FS_C1_I0_A0_EP6_FIFO_CONFIG \
262 (0x80 | ((FS_C1_I0_A0_EP6_BLKSIZE - 1) << 4) | \
263 ((FS_C1_I0_A0_EP6_BLKNO - 1) << 2) | FS_C1_I0_A0_EP6_TYPE)
264 #define FS_C1_I0_A0_EP6_FIFO_MAP \
265 (((1 - FS_C1_I0_A0_EP6_DIRECTION) << 4) | EP6)
266 #define FS_C1_I0_A0_EP6_MAP \
267 (FS_C1_I0_A0_EP6_FIFO_START | (FS_C1_I0_A0_EP6_FIFO_START << 4) | \
268 (MASK_F0 >> (4*FS_C1_I0_A0_EP6_DIRECTION)))
270 void vUSBFIFO_EP6Cfg_FS_patch(void)
272 #if (FS_C1_I0_A0_EP_NUMBER >= 6)
276 mUsbEPMap(EP6, FS_C1_I0_A0_EP6_MAP);
277 mUsbFIFOMap(FS_C1_I0_A0_EP6_FIFO_START, FS_C1_I0_A0_EP6_FIFO_MAP);
278 mUsbFIFOConfig(FS_C1_I0_A0_EP6_FIFO_START, FS_C1_I0_A0_EP6_FIFO_CONFIG);
280 for(i = FS_C1_I0_A0_EP6_FIFO_START + 1 ;
281 i < FS_C1_I0_A0_EP6_FIFO_START + FS_C1_I0_A0_EP6_FIFO_NO ; i ++)
283 mUsbFIFOConfig(i, (FS_C1_I0_A0_EP6_FIFO_CONFIG & (~BIT7)) );
286 mUsbEPMxPtSzHigh(EP6, FS_C1_I0_A0_EP6_DIRECTION,
287 (FS_C1_I0_A0_EP6_MAX_PACKET & 0x7ff));
288 mUsbEPMxPtSzLow(EP6, FS_C1_I0_A0_EP6_DIRECTION,
289 (FS_C1_I0_A0_EP6_MAX_PACKET & 0x7ff));
290 mUsbEPinHighBandSet(EP6, FS_C1_I0_A0_EP6_DIRECTION,
291 FS_C1_I0_A0_EP6_MAX_PACKET);
295 void vUsbFIFO_EPxCfg_FS_patch(void)
297 switch (u8UsbConfigValue)
299 #if (FS_CONFIGURATION_NUMBER >= 1)
300 /* Configuration 0X01 */
302 switch (u8UsbInterfaceValue)
304 #if (FS_C1_INTERFACE_NUMBER >= 1)
307 switch (u8UsbInterfaceAlternateSetting)
310 #if (FS_C1_I0_ALT_NUMBER >= 1)
311 /* AlternateSetting 0 */
316 /* patch up this ep6_fs config */
317 vUSBFIFO_EP6Cfg_FS_patch();
335 /* mCHECK_STACK(); */
338 BOOLEAN bSet_configuration_patch(void)
340 /* do some defaul configuration */
341 bSet_configuration();
343 /* overwrite defaul FIFO configuration for FullSpeed USB */
344 if ((mLOW_BYTE(mDEV_REQ_VALUE()) != 0) && !mUsbHighSpeedST())
345 vUsbFIFO_EPxCfg_FS_patch();
347 eUsbCxFinishAction = ACT_DONE;
351 extern BOOLEAN bStandardCommand(void);
353 BOOLEAN bStandardCommand_patch(void)
355 if (mDEV_REQ_REQ() == USB_SET_CONFIGURATION) {
358 #if ENABLE_SWAP_DATA_MODE
359 /* SWAP FUNCTION should be enabled while DMA engine
360 * is not working, the best place to enable it
361 * is before we trigger the DMA */
362 MAGPIE_REG_USB_RX0_SWAP_DATA = 0x1;
363 MAGPIE_REG_USB_TX0_SWAP_DATA = 0x1;
365 #if SYSTEM_MODULE_HP_EP5
366 MAGPIE_REG_USB_RX1_SWAP_DATA = 0x1;
369 #if SYSTEM_MODULE_HP_EP6
370 MAGPIE_REG_USB_RX2_SWAP_DATA = 0x1;
373 #endif /* ENABLE_SWAP_DATA_MODE */
376 return bStandardCommand();
380 * usb descriptor patch
383 extern uint16_t *u8ConfigDescriptorEX;
384 extern uint16_t *pu8DescriptorEX;
385 extern uint16_t u16TxRxCounter;
386 extern SetupPacket ControlCmd;
387 extern uint16_t *u8UsbDeviceDescriptor;
388 extern BOOLEAN bGet_descriptor(void);
390 uint16_t ConfigDescriptorPatch[30];
391 uint16_t UsbDeviceDescriptorPatch[9];
393 #define BCD_DEVICE_OFFSET 6
394 #define BCD_DEVICE_FW_SIGNATURE 0xffff
395 #define VENDOR_ID_OFFSET 4
396 #define PRODUCT_ID_OFFSET 5
398 #define EP3_TRANSFER_TYPE_OFFSET 17
399 #define EP3_INT_INTERVAL 19
400 #define EP4_TRANSFER_TYPE_OFFSET 21
401 #define EP4_INT_INTERVAL 22
403 BOOLEAN bGet_descriptor_patch(void)
405 if (mDEV_REQ_VALUE_HIGH() == 1)
407 uint8_t *p = (uint8_t *)u8UsbDeviceDescriptor;
409 /* Copy Usb Device Descriptor */
410 ath_hal_memcpy(UsbDeviceDescriptorPatch, p,
411 sizeof(UsbDeviceDescriptorPatch));
413 /* Change bcdDevice. we need it to detect if FW
415 UsbDeviceDescriptorPatch[BCD_DEVICE_OFFSET] =
416 BCD_DEVICE_FW_SIGNATURE;
418 pu8DescriptorEX = UsbDeviceDescriptorPatch;
419 u16TxRxCounter = mTABLE_LEN(u8UsbDeviceDescriptor[0]);
421 if (u16TxRxCounter > mDEV_REQ_LENGTH())
422 u16TxRxCounter = mDEV_REQ_LENGTH();
427 } else if (mDEV_REQ_VALUE_HIGH() == 2) {
428 uint8_t *p = (uint8_t *)u8ConfigDescriptorEX;
430 /* Copy ConfigDescriptor */
431 ath_hal_memcpy(ConfigDescriptorPatch, p,
432 sizeof(ConfigDescriptorPatch));
434 /* place holder for EPx patches */
436 if (mDEV_REQ_VALUE_LOW() == 0) {
437 /* configuration no: 0 */
438 pu8DescriptorEX = ConfigDescriptorPatch;
439 u16TxRxCounter = ConfigDescriptorPatch[1];
443 if (u16TxRxCounter > mDEV_REQ_LENGTH())
444 u16TxRxCounter = mDEV_REQ_LENGTH();
449 return bGet_descriptor();