diff options
Diffstat (limited to 'carl9170fw/carlfw/usb')
-rw-r--r-- | carl9170fw/carlfw/usb/Kconfig | 37 | ||||
-rw-r--r-- | carl9170fw/carlfw/usb/fifo.c | 206 | ||||
-rw-r--r-- | carl9170fw/carlfw/usb/main.c | 432 | ||||
-rw-r--r-- | carl9170fw/carlfw/usb/usb.c | 758 |
4 files changed, 0 insertions, 1433 deletions
diff --git a/carl9170fw/carlfw/usb/Kconfig b/carl9170fw/carlfw/usb/Kconfig deleted file mode 100644 index dc70776..0000000 --- a/carl9170fw/carlfw/usb/Kconfig +++ /dev/null @@ -1,37 +0,0 @@ -menu "USB Firmware Configuration Settings" - -config CARL9170FW_USB_STANDARD_CMDS - def_bool y - prompt "Basic USB Interface" - ---help--- - Allows the device to be queried about Standard USB 2.0 Device - Description Descriptors. - - Say Y, unless you don't care if lsusb -v fails. - -config CARL9170FW_USB_UP_STREAM - def_bool y - prompt "USB Upload Stream" - ---help--- - This features allows the USB silicon to combine small, single - frames into bigger transfers. This can help to reduce - some per-transfer overhead in the application. - - Say Y, unless you have experienced strange rx corruptions. - -config CARL9170FW_USB_DN_STREAM - def_bool n - prompt "USB Download Stream" - -config CARL9170FW_DEBUG_USB - def_bool y - prompt "Pass debug messages through USB transport" - ---help--- - Report all firmware messages through the USB transport. - But there is a catch: In case of a BUG, the USB transport - needs to be functional, otherwise the application won't - receive anything. - - Say Y. - -endmenu diff --git a/carl9170fw/carlfw/usb/fifo.c b/carl9170fw/carlfw/usb/fifo.c deleted file mode 100644 index d5c2e12..0000000 --- a/carl9170fw/carlfw/usb/fifo.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * carl9170 firmware - used by the ar9170 wireless device - * - * Copyright (c) 2000-2005 ZyDAS Technology Corporation - * Copyright (c) 2007-2009 Atheros Communications, Inc. - * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> - * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "carl9170.h" -#include "printf.h" -#include "rom.h" -#include "usb_fifo.h" - -/* TODO / TOTEST */ -#ifdef CONFIG_CARL9170FW_USB_MODESWITCH -static inline void usb_ep_map(const uint8_t ep, const uint8_t map) -{ - setb(AR9170_USB_REG_EP_MAP + (ep - 1), map); -} - -static inline void usb_fifo_map(const uint8_t fifo, const uint8_t map) -{ - setb(AR9170_USB_REG_FIFO_MAP + (fifo - 1), map); -} - -static inline void usb_fifo_config(const uint8_t fifo, const uint8_t cfg) -{ - setb(AR9170_USB_REG_FIFO_CONFIG + (fifo - 1), cfg); -} - -static inline void usb_ep_packet_size_hi(const uint8_t ep, const uint8_t dir, - const uint16_t size) -{ - setb(AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH + (((dir * 0x20) + ep) << 1), - (size >> 8) & 0xf); -} - -static inline void usb_ep_packet_size_lo(const uint8_t ep, const uint8_t dir, - const uint16_t size) -{ - setb(AR9170_USB_REG_EP_IN_MAX_SIZE_LOW + (((dir * 0x20) + ep) << 1), - size & 0xff); -} - -static void usb_ep_in_highbandset(const uint8_t ep, const uint8_t dir, - const uint16_t size) -{ - andb(AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH + (ep << 1), ~(BIT(6) | BIT(5))); - - switch (dir) { - case DIRECTION_IN: - setb(AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH + (ep << 1), - ((size >> 11) + 1) << 5); - break; - case DIRECTION_OUT: - default: - break; - } -} - -/* - * vUsbFIFO_EPxCfg_HS(void) - * Description: - * 1. Configure the FIFO and EPx map - * input: none - * output: none - */ - -void usb_init_highspeed_fifo_cfg(void) -{ - int i; - - /* EP 1 */ - usb_ep_map(1, HS_C1_I0_A0_EP1_MAP); - usb_fifo_map(HS_C1_I0_A0_EP1_FIFO_START, HS_C1_I0_A0_EP1_FIFO_MAP); - usb_fifo_config(HS_C1_I0_A0_EP1_FIFO_START, HS_C1_I0_A0_EP1_FIFO_CONFIG); - - for (i = HS_C1_I0_A0_EP1_FIFO_START + 1; - i < HS_C1_I0_A0_EP1_FIFO_START + HS_C1_I0_A0_EP1_FIFO_NO; i++) { - usb_fifo_config(i, (HS_C1_I0_A0_EP1_FIFO_CONFIG & (~BIT(7)))); - } - - usb_ep_packet_size_hi(1, HS_C1_I0_A0_EP1_DIRECTION, (HS_C1_I0_A0_EP1_MAX_PACKET & 0x7ff)); - usb_ep_packet_size_lo(1, HS_C1_I0_A0_EP1_DIRECTION, (HS_C1_I0_A0_EP1_MAX_PACKET & 0x7ff)); - usb_ep_in_highbandset(1, HS_C1_I0_A0_EP1_DIRECTION, HS_C1_I0_A0_EP1_MAX_PACKET); - - /* EP 2 */ - usb_ep_map(2, HS_C1_I0_A0_EP2_MAP); - usb_fifo_map(HS_C1_I0_A0_EP2_FIFO_START, HS_C1_I0_A0_EP2_FIFO_MAP); - usb_fifo_config(HS_C1_I0_A0_EP2_FIFO_START, HS_C1_I0_A0_EP2_FIFO_CONFIG); - - for (i = HS_C1_I0_A0_EP2_FIFO_START + 1; - i < HS_C1_I0_A0_EP2_FIFO_START + HS_C1_I0_A0_EP2_FIFO_NO; i++) { - usb_fifo_config(i, (HS_C1_I0_A0_EP2_FIFO_CONFIG & (~BIT(7)))); - } - - usb_ep_packet_size_hi(2, HS_C1_I0_A0_EP2_DIRECTION, (HS_C1_I0_A0_EP2_MAX_PACKET & 0x7ff)); - usb_ep_packet_size_lo(2, HS_C1_I0_A0_EP2_DIRECTION, (HS_C1_I0_A0_EP2_MAX_PACKET & 0x7ff)); - usb_ep_in_highbandset(2, HS_C1_I0_A0_EP2_DIRECTION, HS_C1_I0_A0_EP2_MAX_PACKET); - - /* EP 3 */ - usb_ep_map(3, HS_C1_I0_A0_EP3_MAP); - usb_fifo_map(HS_C1_I0_A0_EP3_FIFO_START, HS_C1_I0_A0_EP3_FIFO_MAP); - usb_fifo_config(HS_C1_I0_A0_EP3_FIFO_START, HS_C1_I0_A0_EP3_FIFO_CONFIG); - - for (i = HS_C1_I0_A0_EP3_FIFO_START + 1; - i < HS_C1_I0_A0_EP3_FIFO_START + HS_C1_I0_A0_EP3_FIFO_NO; i++) { - usb_fifo_config(i, (HS_C1_I0_A0_EP3_FIFO_CONFIG & (~BIT(7)))); - } - - usb_ep_packet_size_hi(3, HS_C1_I0_A0_EP3_DIRECTION, (HS_C1_I0_A0_EP3_MAX_PACKET & 0x7ff)); - usb_ep_packet_size_lo(3, HS_C1_I0_A0_EP3_DIRECTION, (HS_C1_I0_A0_EP3_MAX_PACKET & 0x7ff)); - usb_ep_in_highbandset(3, HS_C1_I0_A0_EP3_DIRECTION, HS_C1_I0_A0_EP3_MAX_PACKET); - - /* EP 4 */ - usb_ep_map(4, HS_C1_I0_A0_EP4_MAP); - usb_fifo_map(HS_C1_I0_A0_EP4_FIFO_START, HS_C1_I0_A0_EP4_FIFO_MAP); - usb_fifo_config(HS_C1_I0_A0_EP4_FIFO_START, HS_C1_I0_A0_EP4_FIFO_CONFIG); - - for (i = HS_C1_I0_A0_EP4_FIFO_START + 1; - i < HS_C1_I0_A0_EP4_FIFO_START + HS_C1_I0_A0_EP4_FIFO_NO; i++) { - usb_fifo_config(i, (HS_C1_I0_A0_EP4_FIFO_CONFIG & (~BIT(7)))); - } - - usb_ep_packet_size_hi(4, HS_C1_I0_A0_EP4_DIRECTION, (HS_C1_I0_A0_EP4_MAX_PACKET & 0x7ff)); - usb_ep_packet_size_lo(4, HS_C1_I0_A0_EP4_DIRECTION, (HS_C1_I0_A0_EP4_MAX_PACKET & 0x7ff)); - usb_ep_in_highbandset(4, HS_C1_I0_A0_EP4_DIRECTION, HS_C1_I0_A0_EP4_MAX_PACKET); -} - -void usb_init_fullspeed_fifo_cfg(void) -{ - int i; - - /* EP 1 */ - usb_ep_map(1, FS_C1_I0_A0_EP1_MAP); - usb_fifo_map(FS_C1_I0_A0_EP1_FIFO_START, FS_C1_I0_A0_EP1_FIFO_MAP); - usb_fifo_config(FS_C1_I0_A0_EP1_FIFO_START, FS_C1_I0_A0_EP1_FIFO_CONFIG); - - for (i = FS_C1_I0_A0_EP1_FIFO_START + 1; - i < FS_C1_I0_A0_EP1_FIFO_START + FS_C1_I0_A0_EP1_FIFO_NO; i++) { - usb_fifo_config(i, (FS_C1_I0_A0_EP1_FIFO_CONFIG & (~BIT(7)))); - } - - usb_ep_packet_size_hi(1, FS_C1_I0_A0_EP1_DIRECTION, (FS_C1_I0_A0_EP1_MAX_PACKET & 0x7ff)); - usb_ep_packet_size_lo(1, FS_C1_I0_A0_EP1_DIRECTION, (FS_C1_I0_A0_EP1_MAX_PACKET & 0x7ff)); - /* ``.JWEI 2003/04/29 */ - usb_ep_in_highbandset(1, FS_C1_I0_A0_EP1_DIRECTION, FS_C1_I0_A0_EP1_MAX_PACKET); - - /* EP 2 */ - usb_ep_map(2, FS_C1_I0_A0_EP2_MAP); - usb_fifo_map(FS_C1_I0_A0_EP2_FIFO_START, FS_C1_I0_A0_EP2_FIFO_MAP); - usb_fifo_config(FS_C1_I0_A0_EP2_FIFO_START, FS_C1_I0_A0_EP2_FIFO_CONFIG); - - for (i = FS_C1_I0_A0_EP2_FIFO_START + 1; - i < FS_C1_I0_A0_EP2_FIFO_START + FS_C1_I0_A0_EP2_FIFO_NO; i++) { - usb_fifo_config(i, (FS_C1_I0_A0_EP2_FIFO_CONFIG & (~BIT(7)))); - } - - usb_ep_packet_size_hi(2, FS_C1_I0_A0_EP2_DIRECTION, (FS_C1_I0_A0_EP2_MAX_PACKET & 0x7ff)); - usb_ep_packet_size_lo(2, FS_C1_I0_A0_EP2_DIRECTION, (FS_C1_I0_A0_EP2_MAX_PACKET & 0x7ff)); - usb_ep_in_highbandset(2, FS_C1_I0_A0_EP2_DIRECTION, FS_C1_I0_A0_EP2_MAX_PACKET); - - /* EP 3 */ - usb_ep_map(3, FS_C1_I0_A0_EP3_MAP); - usb_fifo_map(FS_C1_I0_A0_EP3_FIFO_START, FS_C1_I0_A0_EP3_FIFO_MAP); - usb_fifo_config(FS_C1_I0_A0_EP3_FIFO_START, FS_C1_I0_A0_EP3_FIFO_CONFIG); - - for (i = FS_C1_I0_A0_EP3_FIFO_START + 1; - i < FS_C1_I0_A0_EP3_FIFO_START + FS_C1_I0_A0_EP3_FIFO_NO; i++) { - usb_fifo_config(i, (FS_C1_I0_A0_EP3_FIFO_CONFIG & (~BIT(7)))); - } - - usb_ep_packet_size_hi(3, FS_C1_I0_A0_EP3_DIRECTION, (FS_C1_I0_A0_EP3_MAX_PACKET & 0x7ff)); - usb_ep_packet_size_lo(3, FS_C1_I0_A0_EP3_DIRECTION, (FS_C1_I0_A0_EP3_MAX_PACKET & 0x7ff)); - usb_ep_in_highbandset(3, FS_C1_I0_A0_EP3_DIRECTION, FS_C1_I0_A0_EP3_MAX_PACKET); - - /* EP 4 */ - usb_ep_map(4, FS_C1_I0_A0_EP4_MAP); - usb_fifo_map(FS_C1_I0_A0_EP4_FIFO_START, FS_C1_I0_A0_EP4_FIFO_MAP); - usb_fifo_config(FS_C1_I0_A0_EP4_FIFO_START, FS_C1_I0_A0_EP4_FIFO_CONFIG); - - for (i = FS_C1_I0_A0_EP4_FIFO_START + 1; - i < FS_C1_I0_A0_EP4_FIFO_START + FS_C1_I0_A0_EP4_FIFO_NO; i++) { - usb_fifo_config(i, (FS_C1_I0_A0_EP4_FIFO_CONFIG & (~BIT(7)))); - } - - usb_ep_packet_size_hi(4, FS_C1_I0_A0_EP4_DIRECTION, (FS_C1_I0_A0_EP4_MAX_PACKET & 0x7ff)); - usb_ep_packet_size_lo(4, FS_C1_I0_A0_EP4_DIRECTION, (FS_C1_I0_A0_EP4_MAX_PACKET & 0x7ff)); - usb_ep_in_highbandset(4, FS_C1_I0_A0_EP4_DIRECTION, FS_C1_I0_A0_EP4_MAX_PACKET); -} -#endif /* CONFIG_CARL9170FW_USB_MODESWITCH */ diff --git a/carl9170fw/carlfw/usb/main.c b/carl9170fw/carlfw/usb/main.c deleted file mode 100644 index 890970c..0000000 --- a/carl9170fw/carlfw/usb/main.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * carl9170 firmware - used by the ar9170 wireless device - * - * Copyright (c) 2000-2005 ZyDAS Technology Corporation - * Copyright (c) 2007-2009 Atheros Communications, Inc. - * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> - * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "carl9170.h" - -#include "shared/phy.h" -#include "hostif.h" -#include "printf.h" -#include "timer.h" -#include "rom.h" -#include "wl.h" -#include "wol.h" - -#ifdef CONFIG_CARL9170FW_DEBUG_USB -void usb_putc(const char c) -{ - fw.usb.put_buffer[fw.usb.put_index++] = (uint8_t) c; - - if (fw.usb.put_index == CARL9170_MAX_CMD_PAYLOAD_LEN || c == '\0') { - fw.usb.put_buffer[fw.usb.put_index] = 0; - - send_cmd_to_host(__roundup(fw.usb.put_index, 4), - CARL9170_RSP_TEXT, fw.usb.put_index, - fw.usb.put_buffer); - fw.usb.put_index = 0; - } -} - -void usb_print_hex_dump(const void *buf, int len) -{ - unsigned int offset = 0, block = 0; - while (len > 0) { - block = min(__roundup(len, 4), CARL9170_MAX_CMD_PAYLOAD_LEN); - - send_cmd_to_host(block, CARL9170_RSP_HEXDUMP, len, - (const uint8_t *) buf + offset); - - offset += block; - len -= block; - } -} -#endif /* CONFIG_CARL9170FW_DEBUG_USB */ - -/* grab a buffer from the interrupt in queue ring-buffer */ -static struct carl9170_rsp *get_int_buf(void) -{ - struct carl9170_rsp *tmp; - - /* fetch the _oldest_ buffer from the ring */ - tmp = &fw.usb.int_buf[fw.usb.int_tail_index]; - - /* assign a unique sequence for every response/trap */ - tmp->hdr.seq = fw.usb.int_tail_index; - - fw.usb.int_tail_index++; - - fw.usb.int_tail_index %= CARL9170_INT_RQ_CACHES; - if (fw.usb.int_pending != CARL9170_INT_RQ_CACHES) - fw.usb.int_pending++; - - return tmp; -} - -/* Pop up data from Interrupt IN Queue to USB Response buffer */ -static struct carl9170_rsp *dequeue_int_buf(unsigned int space) -{ - struct carl9170_rsp *tmp = NULL; - - if (fw.usb.int_pending > 0) { - tmp = &fw.usb.int_buf[fw.usb.int_head_index]; - - if ((unsigned int)(tmp->hdr.len + 8) > space) - return NULL; - - fw.usb.int_head_index++; - fw.usb.int_head_index %= CARL9170_INT_RQ_CACHES; - fw.usb.int_pending--; - } - - return tmp; -} - -static void usb_data_in(void) -{ -} - -static void usb_reg_out(void) -{ - uint32_t *regaddr = (uint32_t *) &dma_mem.reserved.cmd; - uint16_t usbfifolen, i; - - usb_reset_out(); - - usbfifolen = getb(AR9170_USB_REG_EP4_BYTE_COUNT_LOW) | - getb(AR9170_USB_REG_EP4_BYTE_COUNT_HIGH) << 8; - - if (usbfifolen & 0x3) - usbfifolen = (usbfifolen >> 2) + 1; - else - usbfifolen = usbfifolen >> 2; - - for (i = 0; i < usbfifolen; i++) - *regaddr++ = get(AR9170_USB_REG_EP4_DATA); - - handle_cmd(get_int_buf()); - - usb_trigger_in(); -} - -static void usb_status_in(void) -{ - struct carl9170_rsp *rsp; - unsigned int rem, tlen, elen; - - if (!fw.usb.int_desc_available) - return ; - - fw.usb.int_desc_available = 0; - - rem = AR9170_BLOCK_SIZE - AR9170_INT_MAGIC_HEADER_SIZE; - tlen = AR9170_INT_MAGIC_HEADER_SIZE; - - usb_reset_in(); - - while (fw.usb.int_pending) { - rsp = dequeue_int_buf(rem); - if (!rsp) - break; - - elen = rsp->hdr.len + 4; - - memcpy(DESC_PAYLOAD_OFF(fw.usb.int_desc, tlen), rsp, elen); - - rem -= elen; - tlen += elen; - } - - if (tlen == AR9170_INT_MAGIC_HEADER_SIZE) { - DBG("attempted to send an empty int response!\n"); - goto reclaim; - } - - fw.usb.int_desc->ctrl = AR9170_CTRL_FS_BIT | AR9170_CTRL_LS_BIT; - fw.usb.int_desc->totalLen = tlen; - fw.usb.int_desc->dataSize = tlen; - - /* Put to UpQ */ - dma_put(&fw.pta.up_queue, fw.usb.int_desc); - - /* Trigger PTA UP DMA */ - set(AR9170_PTA_REG_UP_DMA_TRIGGER, 1); - usb_trigger_out(); - - return ; - -reclaim: - /* TODO: not sure what to do here */ - fw.usb.int_desc_available = 1; -} - -void send_cmd_to_host(const uint8_t len, const uint8_t type, - const uint8_t ext, const uint8_t *body) -{ - struct carl9170_cmd *resp; - -#ifdef CONFIG_CARL9170FW_DEBUG - if (unlikely(len > sizeof(resp->data))) { - DBG("CMD too long:%x %d\n", type, len); - return ; - } - - /* Element length must be a multiple of 4. */ - if (unlikely(len & 0x3)) { - DBG("CMD length not mult. of 4:%x %d\n", type, len); - return ; - } -#endif /* CONFIG_CARL9170FW_DEBUG */ - - resp = (struct carl9170_cmd *) get_int_buf(); - if (unlikely(resp == NULL)) { - /* not very helpful for NON UART users */ - DBG("out of msg buffers\n"); - return ; - } - - resp->hdr.len = len; - resp->hdr.cmd = type; - resp->hdr.ext = ext; - - memcpy(resp->data, body, len); - usb_trigger_in(); -} - -/* Turn off ADDA/RF power, PLL */ -static void turn_power_off(void) -{ - set(AR9170_PHY_REG_ACTIVE, AR9170_PHY_ACTIVE_DIS); - set(AR9170_PHY_REG_ADC_CTL, 0xa0000000 | - AR9170_PHY_ADC_CTL_OFF_PWDADC | AR9170_PHY_ADC_CTL_OFF_PWDDAC); - - /* This will also turn-off the LEDs */ - set(AR9170_GPIO_REG_PORT_DATA, 0); - set(AR9170_GPIO_REG_PORT_TYPE, 0xf); - - set(AR9170_PWR_REG_BASE, 0x40021); - - set(AR9170_MAC_REG_DMA_TRIGGER, 0); - - andl(AR9170_USB_REG_DMA_CTL, ~(AR9170_USB_DMA_CTL_ENABLE_TO_DEVICE | - AR9170_USB_DMA_CTL_ENABLE_FROM_DEVICE | - AR9170_USB_DMA_CTL_UP_PACKET_MODE | - AR9170_USB_DMA_CTL_DOWN_STREAM)); - - /* Do a software reset to PTA component */ - orl(AR9170_PTA_REG_DMA_MODE_CTRL, AR9170_PTA_DMA_MODE_CTRL_RESET); - andl(AR9170_PTA_REG_DMA_MODE_CTRL, ~AR9170_PTA_DMA_MODE_CTRL_RESET); - - orl(AR9170_PTA_REG_DMA_MODE_CTRL, AR9170_PTA_DMA_MODE_CTRL_DISABLE_USB); - - set(AR9170_MAC_REG_POWER_STATE_CTRL, - AR9170_MAC_POWER_STATE_CTRL_RESET); - - /* Reset USB FIFO */ - set(AR9170_PWR_REG_RESET, AR9170_PWR_RESET_COMMIT_RESET_MASK | - AR9170_PWR_RESET_DMA_MASK | - AR9170_PWR_RESET_WLAN_MASK); - set(AR9170_PWR_REG_RESET, 0x0); - - clock_set(AHB_20_22MHZ, false); - - set(AR9170_PWR_REG_PLL_ADDAC, 0x5163); /* 0x502b; */ - set(AR9170_PHY_REG_ADC_SERIAL_CTL, AR9170_PHY_ADC_SCTL_SEL_EXTERNAL_RADIO); - set(0x1c589c, 0); /* 7-0 */ - set(0x1c589c, 0); /* 15-8 */ - set(0x1c589c, 0); /* 23-16 */ - set(0x1c589c, 0); /* 31- */ - set(0x1c589c, 0); /* 39- */ - set(0x1c589c, 0); /* 47- */ - set(0x1c589c, 0); /* 55- */ - set(0x1c589c, 0xf8); /* 63- */ - set(0x1c589c, 0x27); /* 0x24; 71- modified */ - set(0x1c589c, 0xf9); /* 79- */ - set(0x1c589c, 0x90); /* 87- */ - set(0x1c589c, 0x04); /* 95- */ - set(0x1c589c, 0x48); /* 103- */ - set(0x1c589c, 0x19); /* 0; 111- modified */ - set(0x1c589c, 0); /* 119- */ - set(0x1c589c, 0); /* 127- */ - set(0x1c589c, 0); /* 135- */ - set(0x1c589c, 0); /* 143- */ - set(0x1c589c, 0); /* 151- */ - set(0x1c589c, 0x70); /* 159- */ - set(0x1c589c, 0x0c); /* 167- */ - set(0x1c589c, 0); /* 175- */ - set(0x1c589c, 0); /* 183-176 */ - set(0x1c589c, 0); /* 191-184 */ - set(0x1c589c, 0); /* 199- */ - set(0x1c589c, 0); /* 207- */ - set(0x1c589c, 0); /* 215- */ - set(0x1c589c, 0); /* 223- */ - set(0x1c589c, 0); /* 231- */ - set(0x1c58c4, 0); /* 233- 232 */ - set(AR9170_PHY_REG_ADC_SERIAL_CTL, AR9170_PHY_ADC_SCTL_SEL_INTERNAL_ADDAC); -} - -static void disable_watchdog(void) -{ - if (!fw.watchdog_enable) - return; - - /* write watchdog magic pattern for suspend */ - andl(AR9170_PWR_REG_WATCH_DOG_MAGIC, 0xffff); - orl(AR9170_PWR_REG_WATCH_DOG_MAGIC, 0x98760000); - - /* Disable watchdog */ - set(AR9170_TIMER_REG_WATCH_DOG, 0xffff); -} - -void __noreturn reboot(void) -{ - disable_watchdog(); - - /* Turn off power */ - turn_power_off(); - - /* clean bootloader workspace */ - memset(&dma_mem, 0, sizeof(dma_mem)); - - /* add by ygwei for work around USB PHY chirp sequence problem */ - set(0x10f100, 0x12345678); - - /* Jump to boot code */ - jump_to_bootcode(); -} - -/* service USB events and re-enable USB interrupt */ -static void usb_handler(uint8_t usb_interrupt_level1) -{ - uint8_t usb_interrupt_level2; - - if (usb_interrupt_level1 & BIT(5)) - usb_data_in(); - - if (usb_interrupt_level1 & BIT(4)) - usb_reg_out(); - - if (usb_interrupt_level1 & BIT(6)) - usb_status_in(); - - if (usb_interrupt_level1 & BIT(0)) { - usb_interrupt_level2 = getb(AR9170_USB_REG_INTR_SOURCE_0); - - if (usb_interrupt_level2 & AR9170_USB_INTR_SRC0_SETUP) - usb_ep0setup(); - - if (usb_interrupt_level2 & AR9170_USB_INTR_SRC0_IN) - usb_ep0tx(); - - if (usb_interrupt_level2 & AR9170_USB_INTR_SRC0_OUT) - usb_ep0rx(); - - if (usb_interrupt_level2 & AR9170_USB_INTR_SRC0_ABORT) { - /* Clear the command abort interrupt */ - andb(AR9170_USB_REG_INTR_SOURCE_0, (uint8_t) - ~AR9170_USB_INTR_SRC0_ABORT); - } - - if (usb_interrupt_level2 & AR9170_USB_INTR_SRC0_FAIL || - fw.usb.ep0_action & CARL9170_EP0_STALL) { - /* - * transmission failure. - * stall ep 0 - */ - setb(AR9170_USB_REG_CX_CONFIG_STATUS, BIT(2)); - fw.usb.ep0_action &= ~CARL9170_EP0_STALL; - } - - if (usb_interrupt_level2 & AR9170_USB_INTR_SRC0_END || - fw.usb.ep0_action & CARL9170_EP0_TRIGGER) { - /* - * transmission done. - * set DONE bit. - */ - setb(AR9170_USB_REG_CX_CONFIG_STATUS, BIT(0)); - fw.usb.ep0_action &= ~CARL9170_EP0_TRIGGER; - } - } - - if (usb_interrupt_level1 & BIT(7)) { - usb_interrupt_level2 = getb(AR9170_USB_REG_INTR_SOURCE_7); - - if (usb_interrupt_level2 & AR9170_USB_INTR_SRC7_RX0BYTE) - usb_data_out0Byte(); - - if (usb_interrupt_level2 & AR9170_USB_INTR_SRC7_TX0BYTE) - usb_data_in0Byte(); - - if (usb_interrupt_level2 & AR9170_USB_INTR_SRC7_USB_RESET) { - usb_reset_ack(); - reboot(); - } - - if (usb_interrupt_level2 & AR9170_USB_INTR_SRC7_USB_SUSPEND) { - usb_suspend_ack(); - - fw.suspend_mode = CARL9170_HOST_SUSPENDED; - -#ifdef CONFIG_CARL9170FW_WOL - if (!(fw.usb.device_feature & USB_DEVICE_REMOTE_WAKEUP) || - !fw.wol.cmd.flags) { - disable_watchdog(); - - /* GO_TO_SUSPEND stops the CPU clock too. */ - orb(AR9170_USB_REG_MAIN_CTRL, AR9170_USB_MAIN_CTRL_GO_TO_SUSPEND); - } else { - wol_prepare(); - } -#else /* CONFIG_CARL9170FW_WOL */ - disable_watchdog(); - - /* GO_TO_SUSPEND stops the CPU clock too. */ - orb(AR9170_USB_REG_MAIN_CTRL, AR9170_USB_MAIN_CTRL_GO_TO_SUSPEND); -#endif /* CONFIG_CARL9170FW_WOL */ - } - - if (usb_interrupt_level2 & AR9170_USB_INTR_SRC7_USB_RESUME) { - usb_resume_ack(); - - fw.suspend_mode = CARL9170_HOST_AWAKE; - set(AR9170_USB_REG_WAKE_UP, 0); - - reboot(); - } - } -} - -void handle_usb(void) -{ - uint8_t usb_interrupt_level1; - - usb_interrupt_level1 = getb(AR9170_USB_REG_INTR_GROUP); - - if (usb_interrupt_level1) - usb_handler(usb_interrupt_level1); - - if (fw.usb.int_pending > 0) - usb_trigger_in(); -} - -void usb_timer(void) -{ -} diff --git a/carl9170fw/carlfw/usb/usb.c b/carl9170fw/carlfw/usb/usb.c deleted file mode 100644 index 74b8f8c..0000000 --- a/carl9170fw/carlfw/usb/usb.c +++ /dev/null @@ -1,758 +0,0 @@ -/* - * carl9170 firmware - used by the ar9170 wireless device - * - * USB Controller - * - * Copyright (c) 2000-2005 ZyDAS Technology Corporation - * Copyright (c) 2007-2009 Atheros Communications, Inc. - * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> - * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#include "carl9170.h" -#include "usb.h" -#include "printf.h" -#include "rom.h" - -/* - * NB: The firmware has to write into these structures - * so don't try to make them "const". - */ - -static struct ar9170_usb_config usb_config_highspeed = { - .cfg = { - .bLength = USB_DT_CONFIG_SIZE, - .bDescriptorType = USB_DT_CONFIG, - .wTotalLength = cpu_to_le16(sizeof(usb_config_highspeed)), - .bNumInterfaces = 1, - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = USB_CONFIG_ATT_ONE | -#ifdef CONFIG_CARL9170FW_WOL - USB_CONFIG_ATT_WAKEUP | -#endif /* CONFIG_CARL9170FW_WOL */ - 0, - .bMaxPower = 0xfa, /* 500 mA */ - }, - - .intf = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = AR9170_USB_NUM_EXTRA_EP, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC, - .bInterfaceProtocol = 0, - .iInterface = 0, - }, - - .ep = { - { /* EP 1 */ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT | AR9170_USB_EP_TX, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), - .bInterval = 0, - }, - - { /* EP 2 */ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN | AR9170_USB_EP_RX, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), - .bInterval = 0, - }, - - { /* EP 3 */ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN | AR9170_USB_EP_IRQ, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(64), - .bInterval = 1, - }, - - { /* EP 4 */ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT | AR9170_USB_EP_CMD, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(64), - .bInterval = 1, - }, - }, -}; - -static struct ar9170_usb_config usb_config_fullspeed = { - .cfg = { - .bLength = USB_DT_CONFIG_SIZE, - .bDescriptorType = USB_DT_CONFIG, - .wTotalLength = cpu_to_le16(sizeof(usb_config_fullspeed)), - .bNumInterfaces = 1, - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = USB_CONFIG_ATT_ONE | -#ifdef CONFIG_CARL9170FW_WOL - USB_CONFIG_ATT_WAKEUP | -#endif /* CONFIG_CARL9170FW_WOL */ - 0, - .bMaxPower = 0xfa, /* 500 mA */ - }, - - .intf = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = AR9170_USB_NUM_EXTRA_EP, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC, - .bInterfaceProtocol = 0, - .iInterface = 0, - }, - - .ep = { - { /* EP 1 */ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT | AR9170_USB_EP_TX, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(64), - .bInterval = 0, - }, - - { /* EP 2 */ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN | AR9170_USB_EP_RX, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(64), - .bInterval = 0, - }, - - { /* EP 3 */ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN | AR9170_USB_EP_IRQ, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(64), - .bInterval = 1, - }, - - { /* EP 4 */ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT | AR9170_USB_EP_CMD, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(64), - .bInterval = 1, - }, - }, -}; - -#ifdef CONFIG_CARL9170FW_USB_MODESWITCH -static void usb_reset_eps(void) -{ - unsigned int i; - - /* clear all EPs' toggle bit */ - for (i = 1; i < __AR9170_USB_NUM_MAX_EP; i++) { - usb_set_input_ep_toggle(i); - usb_clear_input_ep_toggle(i); - } - - /* - * NB: I've no idea why this cannot be integrated into the - * previous loop? - */ - for (i = 1; i < __AR9170_USB_NUM_MAX_EP; i++) { - usb_set_output_ep_toggle(i); - usb_clear_output_ep_toggle(i); - } -} -#endif /* CONFIG_CARL9170FW_USB_MODESWITCH */ - - -static void usb_pta_init(void) -{ - unsigned int usb_dma_ctrl = 0; - /* Set PTA mode to USB */ - andl(AR9170_PTA_REG_DMA_MODE_CTRL, - ~AR9170_PTA_DMA_MODE_CTRL_DISABLE_USB); - - /* Do a software reset to PTA component */ - orl(AR9170_PTA_REG_DMA_MODE_CTRL, AR9170_PTA_DMA_MODE_CTRL_RESET); - andl(AR9170_PTA_REG_DMA_MODE_CTRL, ~AR9170_PTA_DMA_MODE_CTRL_RESET); - - if (usb_detect_highspeed()) { - fw.usb.os_cfg_desc = &usb_config_fullspeed; - fw.usb.cfg_desc = &usb_config_highspeed; - - /* 512 Byte DMA transfers */ - usb_dma_ctrl |= AR9170_USB_DMA_CTL_HIGH_SPEED; - } else { - fw.usb.cfg_desc = &usb_config_fullspeed; - fw.usb.os_cfg_desc = &usb_config_highspeed; - } - -#ifdef CONFIG_CARL9170FW_USB_UP_STREAM -# if (CONFIG_CARL9170FW_RX_FRAME_LEN == 4096) - usb_dma_ctrl |= AR9170_USB_DMA_CTL_UP_STREAM_4K; -# elif (CONFIG_CARL9170FW_RX_FRAME_LEN == 8192) - usb_dma_ctrl |= AR9170_USB_DMA_CTL_UP_STREAM_8K; -# elif (CONFIG_CARL9170FW_RX_FRAME_LEN == 16384) - usb_dma_ctrl |= AR9170_USB_DMA_CTL_UP_STREAM_16K; -# elif (CONFIG_CARL9170FW_RX_FRAME_LEN == 32768) - usb_dma_ctrl |= AR9170_USB_DMA_CTL_UP_STREAM_32K; -# else -# error "Invalid AR9170_RX_FRAME_LEN setting" -# endif - -#else /* CONFIG_CARL9170FW_USB_UP_STREAM */ - usb_dma_ctrl |= AR9170_USB_DMA_CTL_UP_PACKET_MODE; -#endif /* CONFIG_CARL9170FW_USB_UP_STREAM */ - -#ifdef CONFIG_CARL9170FW_USB_DOWN_STREAM - /* Enable down stream mode */ - usb_dma_ctrl |= AR9170_USB_DMA_CTL_DOWN_STREAM; -#endif /* CONFIG_CARL9170FW_USB_DOWN_STREAM */ - -#ifdef CONFIG_CARL9170FW_USB_UP_STREAM - /* Set the up stream mode maximum aggregate number */ - set(AR9170_USB_REG_MAX_AGG_UPLOAD, 4); - - /* - * Set the up stream mode timeout value. - * NB: The vendor driver (otus) set 0x80? - */ - set(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80); -#endif /* CONFIG_CARL9170FW_USB_UP_STREAM */ - - /* Enable up stream and down stream */ - usb_dma_ctrl |= AR9170_USB_DMA_CTL_ENABLE_TO_DEVICE | - AR9170_USB_DMA_CTL_ENABLE_FROM_DEVICE; - - set(AR9170_USB_REG_DMA_CTL, usb_dma_ctrl); -} - -void usb_init(void) -{ - usb_pta_init(); - - fw.usb.config = 1; - /* - * The fw structure is always initialized with "0" - * during boot(); No need to waste precious bytes here. - * - * fw.usb.interface_setting = 0; - * fw.usb.alternate_interface_setting = 0; - * fw.usb.device_feature = 0; - */ - -#ifdef CONFIG_CARL9170FW_WOL - fw.usb.device_feature |= USB_DEVICE_REMOTE_WAKEUP; - usb_enable_remote_wakeup(); -#endif /* CONFIG_CARL9170FW_WOL */ -} - -#define GET_ARRAY(a, o) ((uint32_t *) (((unsigned long) data) + offset)) - -static void usb_ep0rx_data(const void *data, const unsigned int len) -{ - unsigned int offset; - uint32_t value; - - BUG_ON(len > AR9170_USB_EP_CTRL_MAX); - BUILD_BUG_ON(len > AR9170_USB_EP_CTRL_MAX); - - for (offset = 0; offset < ((len + 3) & ~3); offset += 4) { - value = get(AR9170_USB_REG_EP0_DATA); - memcpy(GET_ARRAY(data, offset), &value, - min(len - offset, (unsigned int)4)); - } -} - -static int usb_ep0tx_data(const void *data, const unsigned int len) -{ - unsigned int offset = 0, block, last_block = 0; - uint32_t value; - - BUG_ON(len > AR9170_USB_EP_CTRL_MAX); - BUILD_BUG_ON(len > AR9170_USB_EP_CTRL_MAX); - - block = min(len, (unsigned int) 4); - offset = 0; - while (offset < len) { - - if (last_block != block || block < 4) - setb(AR9170_USB_REG_FIFO_SIZE, (1 << block) - 1); - - memcpy(&value, GET_ARRAY(data, offset), block); - - set(AR9170_USB_REG_EP0_DATA, value); - - offset += block; - last_block = block = min(len - offset, (unsigned int) 4); - } - - setb(AR9170_USB_REG_FIFO_SIZE, 0xf); - - /* this will push the data to the host */ - return 1; -} -#undef GET_ARRAY - -#ifdef CONFIG_CARL9170FW_USB_STANDARD_CMDS -static int usb_get_status(const struct usb_ctrlrequest *ctrl) -{ - __le16 status = cpu_to_le16(fw.usb.device_feature); - - if ((ctrl->bRequestType & USB_DIR_MASK) != USB_DIR_IN) - return -1; - - switch (ctrl->bRequestType & USB_RECIP_MASK) { - case USB_RECIP_DEVICE: - status &= cpu_to_le16(~USB_DEVICE_SELF_POWERED); - status &= cpu_to_le16(~USB_DEVICE_REMOTE_WAKEUP); - break; - - case USB_RECIP_INTERFACE: - /* USB spec: This is reserved for future use. */ - status = cpu_to_le16(0); - break; - - case USB_RECIP_ENDPOINT: - case USB_RECIP_OTHER: - default: - break; - } - - return usb_ep0tx_data((const void *) &status, sizeof(status)); -} - -static int usb_get_string_desc(const struct usb_ctrlrequest *ctrl) -{ - const struct usb_string_descriptor *string_desc = NULL; - - switch (le16_to_cpu(ctrl->wValue) & 0xff) { - case 0x00: - string_desc = (const struct usb_string_descriptor *) - rom.hw.usb.string0_desc; - break; - - case 0x10: - string_desc = (const struct usb_string_descriptor *) - rom.hw.usb.string1_desc; - break; - - case 0x20: - string_desc = (const struct usb_string_descriptor *) - rom.hw.usb.string2_desc; - break; - - case 0x30: - string_desc = (const struct usb_string_descriptor *) - rom.hw.usb.string3_desc; - break; - - default: - break; - } - - if (string_desc) - return usb_ep0tx_data(string_desc, string_desc->bLength); - - return -1; -} - -static int usb_get_device_desc(const struct usb_ctrlrequest *ctrl __unused) -{ - return usb_ep0tx_data(&rom.hw.usb.device_desc, - rom.hw.usb.device_desc.bLength); -} - -static int usb_get_config_desc(const struct usb_ctrlrequest *ctrl __unused) -{ - fw.usb.cfg_desc->cfg.bDescriptorType = USB_DT_CONFIG; - - return usb_ep0tx_data(fw.usb.cfg_desc, - le16_to_cpu(fw.usb.cfg_desc->cfg.wTotalLength)); -} - -#ifdef CONFIG_CARL9170FW_USB_MODESWITCH -static int usb_get_otherspeed_desc(const struct usb_ctrlrequest *ctrl __unused) -{ - - fw.usb.os_cfg_desc->cfg.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG; - - return usb_ep0tx_data(fw.usb.os_cfg_desc, - le16_to_cpu(fw.usb.os_cfg_desc->cfg.wTotalLength)); -} -#endif /* CONFIG_CARL9170FW_USB_MODESWITCH */ - -static int usb_get_qualifier_desc(const struct usb_ctrlrequest *ctrl __unused) -{ - struct usb_qualifier_descriptor qual; - - /* - * The qualifier descriptor shares some structural details - * with the main device descriptor. - */ - - memcpy(&qual, &rom.hw.usb.device_desc, sizeof(qual)); - - /* (Re)-Initialize fields */ - qual.bDescriptorType = USB_DT_DEVICE_QUALIFIER; - qual.bLength = sizeof(qual); - qual.bNumConfigurations = rom.hw.usb.device_desc.bNumConfigurations; - qual.bRESERVED = 0; - - return usb_ep0tx_data(&qual, qual.bLength); -} - -#define USB_CHECK_REQTYPE(ctrl, recip, dir) \ - (((ctrl->bRequestType & USB_RECIP_MASK) != recip) || \ - ((ctrl->bRequestType & USB_DIR_MASK) != dir)) - -static int usb_get_descriptor(const struct usb_ctrlrequest *ctrl) -{ - int status = -1; - - if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_DEVICE, USB_DIR_IN)) - return status; - - switch (le16_to_cpu(ctrl->wValue) >> 8) { - case USB_DT_DEVICE: - status = usb_get_device_desc(ctrl); - break; - - case USB_DT_CONFIG: - status = usb_get_config_desc(ctrl); - break; - - case USB_DT_STRING: - status = usb_get_string_desc(ctrl); - break; - - case USB_DT_INTERFACE: - break; - - case USB_DT_ENDPOINT: - break; - - case USB_DT_DEVICE_QUALIFIER: - status = usb_get_qualifier_desc(ctrl); - break; - -#ifdef CONFIG_CARL9170FW_USB_MODESWITCH - case USB_DT_OTHER_SPEED_CONFIG: - status = usb_get_otherspeed_desc(ctrl); - break; -#endif /* CONFIG_CARL9170FW_USB_MODESWITCH */ - default: - break; - - } - - return status; -} - -static int usb_get_configuration(const struct usb_ctrlrequest *ctrl) -{ - if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_DEVICE, USB_DIR_IN)) - return -1; - - return usb_ep0tx_data(&fw.usb.config, 1); -} - -static int usb_set_configuration(const struct usb_ctrlrequest *ctrl) -{ - unsigned int config; - - if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_DEVICE, USB_DIR_OUT)) - return -1; - - config = le16_to_cpu(ctrl->wValue); - switch (config) { - case 0: - /* Disable Device */ - andb(AR9170_USB_REG_DEVICE_ADDRESS, - (uint8_t) ~(AR9170_USB_DEVICE_ADDRESS_CONFIGURE)); -#ifdef CONFIG_CARL9170FW_USB_MODESWITCH - case 1: - fw.usb.config = config; - - if (usb_detect_highspeed()) { - /* High Speed Configuration */ - usb_init_highspeed_fifo_cfg(); - } else { - /* Full Speed Configuration */ - usb_init_fullspeed_fifo_cfg(); - } - break; - - default: - return -1; - } - /* usb_pta_init() ? */ - - usb_reset_eps(); - orb(AR9170_USB_REG_DEVICE_ADDRESS, - (AR9170_USB_DEVICE_ADDRESS_CONFIGURE)); - - usb_enable_global_int(); - usb_trigger_out(); - return 1; -#else - default: - return -1; - } -#endif /* CONFIG_CARL9170FW_USB_MODESWITCH */ -} - -static int usb_set_address(const struct usb_ctrlrequest *ctrl) -{ - unsigned int address; - - if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_DEVICE, USB_DIR_OUT)) - return -1; - - address = le16_to_cpu(ctrl->wValue); - - /* - * The original firmware used 0x100 (which is, of course, - * too big to fit into uint8_t). - * However based on the available information (hw.h), BIT(7) - * is used as some sort of flag and should not be - * part of the device address. - */ - if (address >= BIT(7)) - return -1; - - setb(AR9170_USB_REG_DEVICE_ADDRESS, (uint8_t) address); - return 1; -} - -static int usb_get_interface(const struct usb_ctrlrequest *ctrl) -{ - if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_INTERFACE, USB_DIR_IN)) - return -1; - - if (usb_configured() == false) - return -1; - - switch (fw.usb.config) { - case 1: - break; - - default: - return -1; - } - - return usb_ep0tx_data(&fw.usb.alternate_interface_setting, 1); -} - -static int usb_manipulate_feature(const struct usb_ctrlrequest *ctrl, bool __unused clear) -{ - unsigned int feature; - if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_DEVICE, USB_DIR_OUT)) - return -1; - - if (usb_configured() == false) - return -1; - - feature = le16_to_cpu(ctrl->wValue); - -#ifdef CONFIG_CARL9170FW_WOL - if (feature & USB_DEVICE_REMOTE_WAKEUP) { - if (clear) - usb_disable_remote_wakeup(); - else - usb_enable_remote_wakeup(); - } -#endif /* CONFIG_CARL9170FW_WOL */ - - if (clear) - fw.usb.device_feature &= ~feature; - else - fw.usb.device_feature |= feature; - - return 1; -} - -#ifdef CONFIG_CARL9170FW_USB_MODESWITCH -static int usb_set_interface(const struct usb_ctrlrequest *ctrl) -{ - unsigned int intf, alt_intf; - if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_INTERFACE, USB_DIR_OUT)) - return -1; - - if (usb_configured() == false) - return -1; - - intf = le16_to_cpu(ctrl->wIndex); - alt_intf = le16_to_cpu(ctrl->wValue); - - switch (intf) { - case 0: - if (alt_intf != fw.usb.cfg_desc->intf.bAlternateSetting) - return -1; - - fw.usb.interface_setting = (uint8_t) intf; - fw.usb.alternate_interface_setting = (uint8_t) alt_intf; - if (usb_detect_highspeed()) - usb_init_highspeed_fifo_cfg(); - else - usb_init_fullspeed_fifo_cfg(); - - usb_reset_eps(); - usb_enable_global_int(); - usb_trigger_out(); - return 1; - - default: - return -1; - } -} -#endif /* CONFIG_CARL9170FW_USB_MODESWITCH */ -#endif /* CONFIG_CARL9170FW_USB_STANDARD_CMDS */ - -static int usb_standard_command(const struct usb_ctrlrequest *ctrl __unused) -{ - int status = -1; - -#ifdef CONFIG_CARL9170FW_USB_STANDARD_CMDS - switch (ctrl->bRequest) { - case USB_REQ_GET_STATUS: - status = usb_get_status(ctrl); - break; - - case USB_REQ_CLEAR_FEATURE: - case USB_REQ_SET_FEATURE: - usb_manipulate_feature(ctrl, ctrl->bRequest == USB_REQ_CLEAR_FEATURE); - break; - - case USB_REQ_SET_ADDRESS: - status = usb_set_address(ctrl); - break; - - case USB_REQ_GET_DESCRIPTOR: - status = usb_get_descriptor(ctrl); - break; - - case USB_REQ_SET_DESCRIPTOR: - break; - - case USB_REQ_GET_CONFIGURATION: - status = usb_get_configuration(ctrl); - break; - - case USB_REQ_SET_CONFIGURATION: - status = usb_set_configuration(ctrl); - break; - - case USB_REQ_GET_INTERFACE: - status = usb_get_interface(ctrl); - break; - - case USB_REQ_SET_INTERFACE: -#ifdef CONFIG_CARL9170FW_USB_MODESWITCH - status = usb_set_interface(ctrl); -#endif /* CONFIG_CARL9170FW_USB_MODESWITCH */ - break; - - case USB_REQ_SYNCH_FRAME: - break; - - default: - break; - - } -#endif /* CONFIG_CARL9170FW_USB_STANDARD_CMDS */ - - return status; -} - -static int usb_class_command(const struct usb_ctrlrequest *ctrl __unused) -{ - return -1; -} - -static int usb_vendor_command(const struct usb_ctrlrequest *ctrl __unused) -{ - /* - * Note: Firmware upload/boot is not implemented. - * It's impossible to replace the current image - * in place. - */ - - return -1; -} - -#undef USB_CHECK_TYPE - -void usb_ep0setup(void) -{ - struct usb_ctrlrequest ctrl; - int status = -1; - usb_ep0rx_data(&ctrl, sizeof(ctrl)); - - switch (ctrl.bRequestType & USB_TYPE_MASK) { - case USB_TYPE_STANDARD: - status = usb_standard_command(&ctrl); - break; - - case USB_TYPE_CLASS: - status = usb_class_command(&ctrl); - break; - - case USB_TYPE_VENDOR: - status = usb_vendor_command(&ctrl); - break; - - default: - break; - - } - - if (status < 0) - fw.usb.ep0_action |= CARL9170_EP0_STALL; -#ifdef CONFIG_CARL9170FW_USB_STANDARD_CMDS - if (status > 0) - fw.usb.ep0_action |= CARL9170_EP0_TRIGGER; -#endif /* CONFIG_CARL9170FW_USB_STANDARD_CMDS */ -} - -void usb_ep0rx(void) -{ - if (BUG_ON(!fw.usb.ep0_txrx_buffer || !fw.usb.ep0_txrx_len)) - return ; - - usb_ep0rx_data(fw.usb.ep0_txrx_buffer, fw.usb.ep0_txrx_len); - fw.usb.ep0_txrx_pos = fw.usb.ep0_txrx_len; -} - -void usb_ep0tx(void) -{ - if (BUG_ON(!fw.usb.ep0_txrx_buffer || !fw.usb.ep0_txrx_len)) - return ; - - usb_ep0tx_data(fw.usb.ep0_txrx_buffer, fw.usb.ep0_txrx_len); - fw.usb.ep0_txrx_pos = fw.usb.ep0_txrx_len; -} |