diff options
author | RajithaY <rajithax.yerrumsetty@intel.com> | 2017-04-25 03:31:15 -0700 |
---|---|---|
committer | Rajitha Yerrumchetty <rajithax.yerrumsetty@intel.com> | 2017-05-22 06:48:08 +0000 |
commit | bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch) | |
tree | ca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/roms/u-boot/drivers/usb | |
parent | a14b48d18a9ed03ec191cf16b162206998a895ce (diff) |
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to
kvmfornfv repo and make use of the updated latest qemu for the
execution of all testcase
Change-Id: I1280af507a857675c7f81d30c95255635667bdd7
Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/drivers/usb')
121 files changed, 0 insertions, 64809 deletions
diff --git a/qemu/roms/u-boot/drivers/usb/eth/Makefile b/qemu/roms/u-boot/drivers/usb/eth/Makefile deleted file mode 100644 index 94551c4c0..000000000 --- a/qemu/roms/u-boot/drivers/usb/eth/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Copyright (c) 2011 The Chromium OS Authors. -# SPDX-License-Identifier: GPL-2.0+ -# - -# new USB host ethernet layer dependencies -obj-$(CONFIG_USB_HOST_ETHER) += usb_ether.o -ifdef CONFIG_USB_ETHER_ASIX -obj-y += asix.o -endif -obj-$(CONFIG_USB_ETHER_MCS7830) += mcs7830.o -obj-$(CONFIG_USB_ETHER_SMSC95XX) += smsc95xx.o diff --git a/qemu/roms/u-boot/drivers/usb/eth/asix.c b/qemu/roms/u-boot/drivers/usb/eth/asix.c deleted file mode 100644 index ce133f006..000000000 --- a/qemu/roms/u-boot/drivers/usb/eth/asix.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> -#include <linux/mii.h> -#include "usb_ether.h" -#include <malloc.h> - - -/* ASIX AX8817X based USB 2.0 Ethernet Devices */ - -#define AX_CMD_SET_SW_MII 0x06 -#define AX_CMD_READ_MII_REG 0x07 -#define AX_CMD_WRITE_MII_REG 0x08 -#define AX_CMD_SET_HW_MII 0x0a -#define AX_CMD_READ_EEPROM 0x0b -#define AX_CMD_READ_RX_CTL 0x0f -#define AX_CMD_WRITE_RX_CTL 0x10 -#define AX_CMD_WRITE_IPG0 0x12 -#define AX_CMD_READ_NODE_ID 0x13 -#define AX_CMD_WRITE_NODE_ID 0x14 -#define AX_CMD_READ_PHY_ID 0x19 -#define AX_CMD_WRITE_MEDIUM_MODE 0x1b -#define AX_CMD_WRITE_GPIOS 0x1f -#define AX_CMD_SW_RESET 0x20 -#define AX_CMD_SW_PHY_SELECT 0x22 - -#define AX_SWRESET_CLEAR 0x00 -#define AX_SWRESET_PRTE 0x04 -#define AX_SWRESET_PRL 0x08 -#define AX_SWRESET_IPRL 0x20 -#define AX_SWRESET_IPPD 0x40 - -#define AX88772_IPG0_DEFAULT 0x15 -#define AX88772_IPG1_DEFAULT 0x0c -#define AX88772_IPG2_DEFAULT 0x12 - -/* AX88772 & AX88178 Medium Mode Register */ -#define AX_MEDIUM_PF 0x0080 -#define AX_MEDIUM_JFE 0x0040 -#define AX_MEDIUM_TFC 0x0020 -#define AX_MEDIUM_RFC 0x0010 -#define AX_MEDIUM_ENCK 0x0008 -#define AX_MEDIUM_AC 0x0004 -#define AX_MEDIUM_FD 0x0002 -#define AX_MEDIUM_GM 0x0001 -#define AX_MEDIUM_SM 0x1000 -#define AX_MEDIUM_SBP 0x0800 -#define AX_MEDIUM_PS 0x0200 -#define AX_MEDIUM_RE 0x0100 - -#define AX88178_MEDIUM_DEFAULT \ - (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \ - AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \ - AX_MEDIUM_RE) - -#define AX88772_MEDIUM_DEFAULT \ - (AX_MEDIUM_FD | AX_MEDIUM_RFC | \ - AX_MEDIUM_TFC | AX_MEDIUM_PS | \ - AX_MEDIUM_AC | AX_MEDIUM_RE) - -/* AX88772 & AX88178 RX_CTL values */ -#define AX_RX_CTL_SO 0x0080 -#define AX_RX_CTL_AB 0x0008 - -#define AX_DEFAULT_RX_CTL \ - (AX_RX_CTL_SO | AX_RX_CTL_AB) - -/* GPIO 2 toggles */ -#define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */ -#define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */ -#define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */ - -/* local defines */ -#define ASIX_BASE_NAME "asx" -#define USB_CTRL_SET_TIMEOUT 5000 -#define USB_CTRL_GET_TIMEOUT 5000 -#define USB_BULK_SEND_TIMEOUT 5000 -#define USB_BULK_RECV_TIMEOUT 5000 - -#define AX_RX_URB_SIZE 2048 -#define PHY_CONNECT_TIMEOUT 5000 - -/* asix_flags defines */ -#define FLAG_NONE 0 -#define FLAG_TYPE_AX88172 (1U << 0) -#define FLAG_TYPE_AX88772 (1U << 1) -#define FLAG_TYPE_AX88772B (1U << 2) -#define FLAG_EEPROM_MAC (1U << 3) /* initial mac address in eeprom */ - -/* local vars */ -static int curr_eth_dev; /* index for name of next device detected */ - -/* driver private */ -struct asix_private { - int flags; -}; - -/* - * Asix infrastructure commands - */ -static int asix_write_cmd(struct ueth_data *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - int len; - - debug("asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x " - "size=%d\n", cmd, value, index, size); - - len = usb_control_msg( - dev->pusb_dev, - usb_sndctrlpipe(dev->pusb_dev, 0), - cmd, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - data, - size, - USB_CTRL_SET_TIMEOUT); - - return len == size ? 0 : -1; -} - -static int asix_read_cmd(struct ueth_data *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - int len; - - debug("asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", - cmd, value, index, size); - - len = usb_control_msg( - dev->pusb_dev, - usb_rcvctrlpipe(dev->pusb_dev, 0), - cmd, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - data, - size, - USB_CTRL_GET_TIMEOUT); - return len == size ? 0 : -1; -} - -static inline int asix_set_sw_mii(struct ueth_data *dev) -{ - int ret; - - ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); - if (ret < 0) - debug("Failed to enable software MII access\n"); - return ret; -} - -static inline int asix_set_hw_mii(struct ueth_data *dev) -{ - int ret; - - ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); - if (ret < 0) - debug("Failed to enable hardware MII access\n"); - return ret; -} - -static int asix_mdio_read(struct ueth_data *dev, int phy_id, int loc) -{ - ALLOC_CACHE_ALIGN_BUFFER(__le16, res, 1); - - asix_set_sw_mii(dev); - asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, res); - asix_set_hw_mii(dev); - - debug("asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", - phy_id, loc, le16_to_cpu(*res)); - - return le16_to_cpu(*res); -} - -static void -asix_mdio_write(struct ueth_data *dev, int phy_id, int loc, int val) -{ - ALLOC_CACHE_ALIGN_BUFFER(__le16, res, 1); - *res = cpu_to_le16(val); - - debug("asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", - phy_id, loc, val); - asix_set_sw_mii(dev); - asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, res); - asix_set_hw_mii(dev); -} - -/* - * Asix "high level" commands - */ -static int asix_sw_reset(struct ueth_data *dev, u8 flags) -{ - int ret; - - ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL); - if (ret < 0) - debug("Failed to send software reset: %02x\n", ret); - else - udelay(150 * 1000); - - return ret; -} - -static inline int asix_get_phy_addr(struct ueth_data *dev) -{ - ALLOC_CACHE_ALIGN_BUFFER(u8, buf, 2); - - int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf); - - debug("asix_get_phy_addr()\n"); - - if (ret < 0) { - debug("Error reading PHYID register: %02x\n", ret); - goto out; - } - debug("asix_get_phy_addr() returning 0x%02x%02x\n", buf[0], buf[1]); - ret = buf[1]; - -out: - return ret; -} - -static int asix_write_medium_mode(struct ueth_data *dev, u16 mode) -{ - int ret; - - debug("asix_write_medium_mode() - mode = 0x%04x\n", mode); - ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, - 0, 0, NULL); - if (ret < 0) { - debug("Failed to write Medium Mode mode to 0x%04x: %02x\n", - mode, ret); - } - return ret; -} - -static u16 asix_read_rx_ctl(struct ueth_data *dev) -{ - ALLOC_CACHE_ALIGN_BUFFER(__le16, v, 1); - - int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, v); - - if (ret < 0) - debug("Error reading RX_CTL register: %02x\n", ret); - else - ret = le16_to_cpu(*v); - return ret; -} - -static int asix_write_rx_ctl(struct ueth_data *dev, u16 mode) -{ - int ret; - - debug("asix_write_rx_ctl() - mode = 0x%04x\n", mode); - ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); - if (ret < 0) { - debug("Failed to write RX_CTL mode to 0x%04x: %02x\n", - mode, ret); - } - return ret; -} - -static int asix_write_gpio(struct ueth_data *dev, u16 value, int sleep) -{ - int ret; - - debug("asix_write_gpio() - value = 0x%04x\n", value); - ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL); - if (ret < 0) { - debug("Failed to write GPIO value 0x%04x: %02x\n", - value, ret); - } - if (sleep) - udelay(sleep * 1000); - - return ret; -} - -static int asix_write_hwaddr(struct eth_device *eth) -{ - struct ueth_data *dev = (struct ueth_data *)eth->priv; - int ret; - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN); - - memcpy(buf, eth->enetaddr, ETH_ALEN); - - ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, buf); - if (ret < 0) - debug("Failed to set MAC address: %02x\n", ret); - - return ret; -} - -/* - * mii commands - */ - -/* - * mii_nway_restart - restart NWay (autonegotiation) for this interface - * - * Returns 0 on success, negative on error. - */ -static int mii_nway_restart(struct ueth_data *dev) -{ - int bmcr; - int r = -1; - - /* if autoneg is off, it's an error */ - bmcr = asix_mdio_read(dev, dev->phy_id, MII_BMCR); - - if (bmcr & BMCR_ANENABLE) { - bmcr |= BMCR_ANRESTART; - asix_mdio_write(dev, dev->phy_id, MII_BMCR, bmcr); - r = 0; - } - - return r; -} - -static int asix_read_mac(struct eth_device *eth) -{ - struct ueth_data *dev = (struct ueth_data *)eth->priv; - struct asix_private *priv = (struct asix_private *)dev->dev_priv; - int i; - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN); - - if (priv->flags & FLAG_EEPROM_MAC) { - for (i = 0; i < (ETH_ALEN >> 1); i++) { - if (asix_read_cmd(dev, AX_CMD_READ_EEPROM, - 0x04 + i, 0, 2, buf) < 0) { - debug("Failed to read SROM address 04h.\n"); - return -1; - } - memcpy((eth->enetaddr + i * 2), buf, 2); - } - } else { - if (asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf) - < 0) { - debug("Failed to read MAC address.\n"); - return -1; - } - memcpy(eth->enetaddr, buf, ETH_ALEN); - } - - return 0; -} - -static int asix_basic_reset(struct ueth_data *dev) -{ - int embd_phy; - u16 rx_ctl; - - if (asix_write_gpio(dev, - AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5) < 0) - return -1; - - /* 0x10 is the phy id of the embedded 10/100 ethernet phy */ - embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0); - if (asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, - embd_phy, 0, 0, NULL) < 0) { - debug("Select PHY #1 failed\n"); - return -1; - } - - if (asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL) < 0) - return -1; - - if (asix_sw_reset(dev, AX_SWRESET_CLEAR) < 0) - return -1; - - if (embd_phy) { - if (asix_sw_reset(dev, AX_SWRESET_IPRL) < 0) - return -1; - } else { - if (asix_sw_reset(dev, AX_SWRESET_PRTE) < 0) - return -1; - } - - rx_ctl = asix_read_rx_ctl(dev); - debug("RX_CTL is 0x%04x after software reset\n", rx_ctl); - if (asix_write_rx_ctl(dev, 0x0000) < 0) - return -1; - - rx_ctl = asix_read_rx_ctl(dev); - debug("RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); - - dev->phy_id = asix_get_phy_addr(dev); - if (dev->phy_id < 0) - debug("Failed to read phy id\n"); - - asix_mdio_write(dev, dev->phy_id, MII_BMCR, BMCR_RESET); - asix_mdio_write(dev, dev->phy_id, MII_ADVERTISE, - ADVERTISE_ALL | ADVERTISE_CSMA); - mii_nway_restart(dev); - - if (asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT) < 0) - return -1; - - if (asix_write_cmd(dev, AX_CMD_WRITE_IPG0, - AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, - AX88772_IPG2_DEFAULT, 0, NULL) < 0) { - debug("Write IPG,IPG1,IPG2 failed\n"); - return -1; - } - - return 0; -} - -/* - * Asix callbacks - */ -static int asix_init(struct eth_device *eth, bd_t *bd) -{ - struct ueth_data *dev = (struct ueth_data *)eth->priv; - int timeout = 0; -#define TIMEOUT_RESOLUTION 50 /* ms */ - int link_detected; - - debug("** %s()\n", __func__); - - if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL) < 0) - goto out_err; - - do { - link_detected = asix_mdio_read(dev, dev->phy_id, MII_BMSR) & - BMSR_LSTATUS; - if (!link_detected) { - if (timeout == 0) - printf("Waiting for Ethernet connection... "); - udelay(TIMEOUT_RESOLUTION * 1000); - timeout += TIMEOUT_RESOLUTION; - } - } while (!link_detected && timeout < PHY_CONNECT_TIMEOUT); - if (link_detected) { - if (timeout != 0) - printf("done.\n"); - } else { - printf("unable to connect.\n"); - goto out_err; - } - - return 0; -out_err: - return -1; -} - -static int asix_send(struct eth_device *eth, void *packet, int length) -{ - struct ueth_data *dev = (struct ueth_data *)eth->priv; - int err; - u32 packet_len; - int actual_len; - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg, - PKTSIZE + sizeof(packet_len)); - - debug("** %s(), len %d\n", __func__, length); - - packet_len = (((length) ^ 0x0000ffff) << 16) + (length); - cpu_to_le32s(&packet_len); - - memcpy(msg, &packet_len, sizeof(packet_len)); - memcpy(msg + sizeof(packet_len), (void *)packet, length); - - err = usb_bulk_msg(dev->pusb_dev, - usb_sndbulkpipe(dev->pusb_dev, dev->ep_out), - (void *)msg, - length + sizeof(packet_len), - &actual_len, - USB_BULK_SEND_TIMEOUT); - debug("Tx: len = %u, actual = %u, err = %d\n", - length + sizeof(packet_len), actual_len, err); - - return err; -} - -static int asix_recv(struct eth_device *eth) -{ - struct ueth_data *dev = (struct ueth_data *)eth->priv; - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, AX_RX_URB_SIZE); - unsigned char *buf_ptr; - int err; - int actual_len; - u32 packet_len; - - debug("** %s()\n", __func__); - - err = usb_bulk_msg(dev->pusb_dev, - usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in), - (void *)recv_buf, - AX_RX_URB_SIZE, - &actual_len, - USB_BULK_RECV_TIMEOUT); - debug("Rx: len = %u, actual = %u, err = %d\n", AX_RX_URB_SIZE, - actual_len, err); - if (err != 0) { - debug("Rx: failed to receive\n"); - return -1; - } - if (actual_len > AX_RX_URB_SIZE) { - debug("Rx: received too many bytes %d\n", actual_len); - return -1; - } - - buf_ptr = recv_buf; - while (actual_len > 0) { - /* - * 1st 4 bytes contain the length of the actual data as two - * complementary 16-bit words. Extract the length of the data. - */ - if (actual_len < sizeof(packet_len)) { - debug("Rx: incomplete packet length\n"); - return -1; - } - memcpy(&packet_len, buf_ptr, sizeof(packet_len)); - le32_to_cpus(&packet_len); - if (((~packet_len >> 16) & 0x7ff) != (packet_len & 0x7ff)) { - debug("Rx: malformed packet length: %#x (%#x:%#x)\n", - packet_len, (~packet_len >> 16) & 0x7ff, - packet_len & 0x7ff); - return -1; - } - packet_len = packet_len & 0x7ff; - if (packet_len > actual_len - sizeof(packet_len)) { - debug("Rx: too large packet: %d\n", packet_len); - return -1; - } - - /* Notify net stack */ - NetReceive(buf_ptr + sizeof(packet_len), packet_len); - - /* Adjust for next iteration. Packets are padded to 16-bits */ - if (packet_len & 1) - packet_len++; - actual_len -= sizeof(packet_len) + packet_len; - buf_ptr += sizeof(packet_len) + packet_len; - } - - return err; -} - -static void asix_halt(struct eth_device *eth) -{ - debug("** %s()\n", __func__); -} - -/* - * Asix probing functions - */ -void asix_eth_before_probe(void) -{ - curr_eth_dev = 0; -} - -struct asix_dongle { - unsigned short vendor; - unsigned short product; - int flags; -}; - -static const struct asix_dongle const asix_dongles[] = { - { 0x05ac, 0x1402, FLAG_TYPE_AX88772 }, /* Apple USB Ethernet Adapter */ - { 0x07d1, 0x3c05, FLAG_TYPE_AX88772 }, /* D-Link DUB-E100 H/W Ver B1 */ - { 0x2001, 0x1a02, FLAG_TYPE_AX88772 }, /* D-Link DUB-E100 H/W Ver C1 */ - /* Cables-to-Go USB Ethernet Adapter */ - { 0x0b95, 0x772a, FLAG_TYPE_AX88772 }, - { 0x0b95, 0x7720, FLAG_TYPE_AX88772 }, /* Trendnet TU2-ET100 V3.0R */ - { 0x0b95, 0x1720, FLAG_TYPE_AX88172 }, /* SMC */ - { 0x0db0, 0xa877, FLAG_TYPE_AX88772 }, /* MSI - ASIX 88772a */ - { 0x13b1, 0x0018, FLAG_TYPE_AX88172 }, /* Linksys 200M v2.1 */ - { 0x1557, 0x7720, FLAG_TYPE_AX88772 }, /* 0Q0 cable ethernet */ - /* DLink DUB-E100 H/W Ver B1 Alternate */ - { 0x2001, 0x3c05, FLAG_TYPE_AX88772 }, - /* ASIX 88772B */ - { 0x0b95, 0x772b, FLAG_TYPE_AX88772B | FLAG_EEPROM_MAC }, - { 0x0000, 0x0000, FLAG_NONE } /* END - Do not remove */ -}; - -/* Probe to see if a new device is actually an asix device */ -int asix_eth_probe(struct usb_device *dev, unsigned int ifnum, - struct ueth_data *ss) -{ - struct usb_interface *iface; - struct usb_interface_descriptor *iface_desc; - int ep_in_found = 0, ep_out_found = 0; - int i; - - /* let's examine the device now */ - iface = &dev->config.if_desc[ifnum]; - iface_desc = &dev->config.if_desc[ifnum].desc; - - for (i = 0; asix_dongles[i].vendor != 0; i++) { - if (dev->descriptor.idVendor == asix_dongles[i].vendor && - dev->descriptor.idProduct == asix_dongles[i].product) - /* Found a supported dongle */ - break; - } - - if (asix_dongles[i].vendor == 0) - return 0; - - memset(ss, 0, sizeof(struct ueth_data)); - - /* At this point, we know we've got a live one */ - debug("\n\nUSB Ethernet device detected: %#04x:%#04x\n", - dev->descriptor.idVendor, dev->descriptor.idProduct); - - /* Initialize the ueth_data structure with some useful info */ - ss->ifnum = ifnum; - ss->pusb_dev = dev; - ss->subclass = iface_desc->bInterfaceSubClass; - ss->protocol = iface_desc->bInterfaceProtocol; - - /* alloc driver private */ - ss->dev_priv = calloc(1, sizeof(struct asix_private)); - if (!ss->dev_priv) - return 0; - - ((struct asix_private *)ss->dev_priv)->flags = asix_dongles[i].flags; - - /* - * We are expecting a minimum of 3 endpoints - in, out (bulk), and - * int. We will ignore any others. - */ - for (i = 0; i < iface_desc->bNumEndpoints; i++) { - /* is it an BULK endpoint? */ - if ((iface->ep_desc[i].bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { - u8 ep_addr = iface->ep_desc[i].bEndpointAddress; - if (ep_addr & USB_DIR_IN) { - if (!ep_in_found) { - ss->ep_in = ep_addr & - USB_ENDPOINT_NUMBER_MASK; - ep_in_found = 1; - } - } else { - if (!ep_out_found) { - ss->ep_out = ep_addr & - USB_ENDPOINT_NUMBER_MASK; - ep_out_found = 1; - } - } - } - - /* is it an interrupt endpoint? */ - if ((iface->ep_desc[i].bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { - ss->ep_int = iface->ep_desc[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - ss->irqinterval = iface->ep_desc[i].bInterval; - } - } - debug("Endpoints In %d Out %d Int %d\n", - ss->ep_in, ss->ep_out, ss->ep_int); - - /* Do some basic sanity checks, and bail if we find a problem */ - if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) || - !ss->ep_in || !ss->ep_out || !ss->ep_int) { - debug("Problems with device\n"); - return 0; - } - dev->privptr = (void *)ss; - return 1; -} - -int asix_eth_get_info(struct usb_device *dev, struct ueth_data *ss, - struct eth_device *eth) -{ - struct asix_private *priv = (struct asix_private *)ss->dev_priv; - - if (!eth) { - debug("%s: missing parameter.\n", __func__); - return 0; - } - sprintf(eth->name, "%s%d", ASIX_BASE_NAME, curr_eth_dev++); - eth->init = asix_init; - eth->send = asix_send; - eth->recv = asix_recv; - eth->halt = asix_halt; - if (!(priv->flags & FLAG_TYPE_AX88172)) - eth->write_hwaddr = asix_write_hwaddr; - eth->priv = ss; - - if (asix_basic_reset(ss)) - return 0; - - /* Get the MAC address */ - if (asix_read_mac(eth)) - return 0; - debug("MAC %pM\n", eth->enetaddr); - - return 1; -} diff --git a/qemu/roms/u-boot/drivers/usb/eth/mcs7830.c b/qemu/roms/u-boot/drivers/usb/eth/mcs7830.c deleted file mode 100644 index c353286b6..000000000 --- a/qemu/roms/u-boot/drivers/usb/eth/mcs7830.c +++ /dev/null @@ -1,812 +0,0 @@ -/* - * Copyright (c) 2013 Gerhard Sittig <gsi@denx.de> - * based on the U-Boot Asix driver as well as information - * from the Linux Moschip driver - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * MOSCHIP MCS7830 based (7730/7830/7832) USB 2.0 Ethernet Devices - */ - -#include <common.h> -#include <errno.h> -#include <linux/mii.h> -#include <malloc.h> -#include <usb.h> - -#include "usb_ether.h" - -#define MCS7830_BASE_NAME "mcs" - -#define USBCALL_TIMEOUT 1000 -#define LINKSTATUS_TIMEOUT 5000 /* link status, connect timeout */ -#define LINKSTATUS_TIMEOUT_RES 50 /* link status, resolution in msec */ - -#define MCS7830_RX_URB_SIZE 2048 - -/* command opcodes */ -#define MCS7830_WR_BREQ 0x0d -#define MCS7830_RD_BREQ 0x0e - -/* register layout, numerical offset specs for USB API calls */ -struct mcs7830_regs { - uint8_t multicast_hashes[8]; - uint8_t packet_gap[2]; - uint8_t phy_data[2]; - uint8_t phy_command[2]; - uint8_t configuration; - uint8_t ether_address[6]; - uint8_t frame_drop_count; - uint8_t pause_threshold; -}; -#define REG_MULTICAST_HASH offsetof(struct mcs7830_regs, multicast_hashes) -#define REG_PHY_DATA offsetof(struct mcs7830_regs, phy_data) -#define REG_PHY_CMD offsetof(struct mcs7830_regs, phy_command) -#define REG_CONFIG offsetof(struct mcs7830_regs, configuration) -#define REG_ETHER_ADDR offsetof(struct mcs7830_regs, ether_address) -#define REG_FRAME_DROP_COUNTER offsetof(struct mcs7830_regs, frame_drop_count) -#define REG_PAUSE_THRESHOLD offsetof(struct mcs7830_regs, pause_threshold) - -/* bit masks and default values for the above registers */ -#define PHY_CMD1_READ 0x40 -#define PHY_CMD1_WRITE 0x20 -#define PHY_CMD1_PHYADDR 0x01 - -#define PHY_CMD2_PEND 0x80 -#define PHY_CMD2_READY 0x40 - -#define CONF_CFG 0x80 -#define CONF_SPEED100 0x40 -#define CONF_FDX_ENABLE 0x20 -#define CONF_RXENABLE 0x10 -#define CONF_TXENABLE 0x08 -#define CONF_SLEEPMODE 0x04 -#define CONF_ALLMULTICAST 0x02 -#define CONF_PROMISCUOUS 0x01 - -#define PAUSE_THRESHOLD_DEFAULT 0 - -/* bit masks for the status byte which follows received ethernet frames */ -#define STAT_RX_FRAME_CORRECT 0x20 -#define STAT_RX_LARGE_FRAME 0x10 -#define STAT_RX_CRC_ERROR 0x08 -#define STAT_RX_ALIGNMENT_ERROR 0x04 -#define STAT_RX_LENGTH_ERROR 0x02 -#define STAT_RX_SHORT_FRAME 0x01 - -/* - * struct mcs7830_private - private driver data for an individual adapter - * @config: shadow for the network adapter's configuration register - * @mchash: shadow for the network adapter's multicast hash registers - */ -struct mcs7830_private { - uint8_t config; - uint8_t mchash[8]; -}; - -/* - * mcs7830_read_reg() - read a register of the network adapter - * @dev: network device to read from - * @idx: index of the register to start reading from - * @size: number of bytes to read - * @data: buffer to read into - * Return: zero upon success, negative upon error - */ -static int mcs7830_read_reg(struct ueth_data *dev, uint8_t idx, - uint16_t size, void *data) -{ - int len; - ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, size); - - debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size); - - len = usb_control_msg(dev->pusb_dev, - usb_rcvctrlpipe(dev->pusb_dev, 0), - MCS7830_RD_BREQ, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, idx, buf, size, - USBCALL_TIMEOUT); - if (len != size) { - debug("%s() len=%d != sz=%d\n", __func__, len, size); - return -EIO; - } - memcpy(data, buf, size); - return 0; -} - -/* - * mcs7830_write_reg() - write a register of the network adapter - * @dev: network device to write to - * @idx: index of the register to start writing to - * @size: number of bytes to write - * @data: buffer holding the data to write - * Return: zero upon success, negative upon error - */ -static int mcs7830_write_reg(struct ueth_data *dev, uint8_t idx, - uint16_t size, void *data) -{ - int len; - ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, size); - - debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size); - - memcpy(buf, data, size); - len = usb_control_msg(dev->pusb_dev, - usb_sndctrlpipe(dev->pusb_dev, 0), - MCS7830_WR_BREQ, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, idx, buf, size, - USBCALL_TIMEOUT); - if (len != size) { - debug("%s() len=%d != sz=%d\n", __func__, len, size); - return -EIO; - } - return 0; -} - -/* - * mcs7830_phy_emit_wait() - emit PHY read/write access, wait for its execution - * @dev: network device to talk to - * @rwflag: PHY_CMD1_READ or PHY_CMD1_WRITE opcode - * @index: number of the PHY register to read or write - * Return: zero upon success, negative upon error - */ -static int mcs7830_phy_emit_wait(struct ueth_data *dev, - uint8_t rwflag, uint8_t index) -{ - int rc; - int retry; - uint8_t cmd[2]; - - /* send the PHY read/write request */ - cmd[0] = rwflag | PHY_CMD1_PHYADDR; - cmd[1] = PHY_CMD2_PEND | (index & 0x1f); - rc = mcs7830_write_reg(dev, REG_PHY_CMD, sizeof(cmd), cmd); - if (rc < 0) - return rc; - - /* wait for the response to become available (usually < 1ms) */ - retry = 10; - do { - rc = mcs7830_read_reg(dev, REG_PHY_CMD, sizeof(cmd), cmd); - if (rc < 0) - return rc; - if (cmd[1] & PHY_CMD2_READY) - return 0; - if (!retry--) - return -ETIMEDOUT; - mdelay(1); - } while (1); - /* UNREACH */ -} - -/* - * mcs7830_read_phy() - read a PHY register of the network adapter - * @dev: network device to read from - * @index: index of the PHY register to read from - * Return: non-negative 16bit register content, negative upon error - */ -static int mcs7830_read_phy(struct ueth_data *dev, uint8_t index) -{ - int rc; - uint16_t val; - - /* issue the PHY read request and wait for its execution */ - rc = mcs7830_phy_emit_wait(dev, PHY_CMD1_READ, index); - if (rc < 0) - return rc; - - /* fetch the PHY data which was read */ - rc = mcs7830_read_reg(dev, REG_PHY_DATA, sizeof(val), &val); - if (rc < 0) - return rc; - rc = le16_to_cpu(val); - debug("%s(%s, %d) => 0x%04X\n", __func__, dev->eth_dev.name, index, rc); - return rc; -} - -/* - * mcs7830_write_phy() - write a PHY register of the network adapter - * @dev: network device to write to - * @index: index of the PHY register to write to - * @val: value to write to the PHY register - * Return: zero upon success, negative upon error - */ -static int mcs7830_write_phy(struct ueth_data *dev, uint8_t index, uint16_t val) -{ - int rc; - - debug("%s(%s, %d, 0x%04X)\n", __func__, dev->eth_dev.name, index, val); - - /* setup the PHY data which is to get written */ - val = cpu_to_le16(val); - rc = mcs7830_write_reg(dev, REG_PHY_DATA, sizeof(val), &val); - if (rc < 0) - return rc; - - /* issue the PHY write request and wait for its execution */ - rc = mcs7830_phy_emit_wait(dev, PHY_CMD1_WRITE, index); - if (rc < 0) - return rc; - - return 0; -} - -/* - * mcs7830_write_config() - write to the network adapter's config register - * @eth: network device to write to - * Return: zero upon success, negative upon error - * - * the data which gets written is taken from the shadow config register - * within the device driver's private data - */ -static int mcs7830_write_config(struct ueth_data *dev) -{ - struct mcs7830_private *priv; - int rc; - - debug("%s()\n", __func__); - priv = dev->dev_priv; - - rc = mcs7830_write_reg(dev, REG_CONFIG, - sizeof(priv->config), &priv->config); - if (rc < 0) { - debug("writing config to adapter failed\n"); - return rc; - } - - return 0; -} - -/* - * mcs7830_write_mchash() - write the network adapter's multicast filter - * @eth: network device to write to - * Return: zero upon success, negative upon error - * - * the data which gets written is taken from the shadow multicast hashes - * within the device driver's private data - */ -static int mcs7830_write_mchash(struct ueth_data *dev) -{ - struct mcs7830_private *priv; - int rc; - - debug("%s()\n", __func__); - priv = dev->dev_priv; - - rc = mcs7830_write_reg(dev, REG_MULTICAST_HASH, - sizeof(priv->mchash), &priv->mchash); - if (rc < 0) { - debug("writing multicast hash to adapter failed\n"); - return rc; - } - - return 0; -} - -/* - * mcs7830_set_autoneg() - setup and trigger ethernet link autonegotiation - * @eth: network device to run link negotiation on - * Return: zero upon success, negative upon error - * - * the routine advertises available media and starts autonegotiation - */ -static int mcs7830_set_autoneg(struct ueth_data *dev) -{ - int adv, flg; - int rc; - - debug("%s()\n", __func__); - - /* - * algorithm taken from the Linux driver, which took it from - * "the original mcs7830 version 1.4 driver": - * - * enable all media, reset BMCR, enable auto neg, restart - * auto neg while keeping the enable auto neg flag set - */ - - adv = ADVERTISE_PAUSE_CAP | ADVERTISE_ALL | ADVERTISE_CSMA; - rc = mcs7830_write_phy(dev, MII_ADVERTISE, adv); - - flg = 0; - if (!rc) - rc = mcs7830_write_phy(dev, MII_BMCR, flg); - - flg |= BMCR_ANENABLE; - if (!rc) - rc = mcs7830_write_phy(dev, MII_BMCR, flg); - - flg |= BMCR_ANRESTART; - if (!rc) - rc = mcs7830_write_phy(dev, MII_BMCR, flg); - - return rc; -} - -/* - * mcs7830_get_rev() - identify a network adapter's chip revision - * @eth: network device to identify - * Return: non-negative number, reflecting the revision number - * - * currently, only "rev C and higher" and "below rev C" are needed, so - * the return value is #1 for "below rev C", and #2 for "rev C and above" - */ -static int mcs7830_get_rev(struct ueth_data *dev) -{ - uint8_t buf[2]; - int rc; - int rev; - - /* register 22 is readable in rev C and higher */ - rc = mcs7830_read_reg(dev, REG_FRAME_DROP_COUNTER, sizeof(buf), buf); - if (rc < 0) - rev = 1; - else - rev = 2; - debug("%s() rc=%d, rev=%d\n", __func__, rc, rev); - return rev; -} - -/* - * mcs7830_apply_fixup() - identify an adapter and potentially apply fixups - * @eth: network device to identify and apply fixups to - * Return: zero upon success (no errors emitted from here) - * - * this routine identifies the network adapter's chip revision, and applies - * fixups for known issues - */ -static int mcs7830_apply_fixup(struct ueth_data *dev) -{ - int rev; - int i; - uint8_t thr; - - rev = mcs7830_get_rev(dev); - debug("%s() rev=%d\n", __func__, rev); - - /* - * rev C requires setting the pause threshold (the Linux driver - * is inconsistent, the implementation does it for "rev C - * exactly", the introductory comment says "rev C and above") - */ - if (rev == 2) { - debug("%s: applying rev C fixup\n", dev->eth_dev.name); - thr = PAUSE_THRESHOLD_DEFAULT; - for (i = 0; i < 2; i++) { - (void)mcs7830_write_reg(dev, REG_PAUSE_THRESHOLD, - sizeof(thr), &thr); - mdelay(1); - } - } - - return 0; -} - -/* - * mcs7830_basic_reset() - bring the network adapter into a known first state - * @eth: network device to act upon - * Return: zero upon success, negative upon error - * - * this routine initializes the network adapter such that subsequent invocations - * of the interface callbacks can exchange ethernet frames; link negotiation is - * triggered from here already and continues in background - */ -static int mcs7830_basic_reset(struct ueth_data *dev) -{ - struct mcs7830_private *priv; - int rc; - - debug("%s()\n", __func__); - priv = dev->dev_priv; - - /* - * comment from the respective Linux driver, which - * unconditionally sets the ALLMULTICAST flag as well: - * should not be needed, but does not work otherwise - */ - priv->config = CONF_TXENABLE; - priv->config |= CONF_ALLMULTICAST; - - rc = mcs7830_set_autoneg(dev); - if (rc < 0) { - error("setting autoneg failed\n"); - return rc; - } - - rc = mcs7830_write_mchash(dev); - if (rc < 0) { - error("failed to set multicast hash\n"); - return rc; - } - - rc = mcs7830_write_config(dev); - if (rc < 0) { - error("failed to set configuration\n"); - return rc; - } - - rc = mcs7830_apply_fixup(dev); - if (rc < 0) { - error("fixup application failed\n"); - return rc; - } - - return 0; -} - -/* - * mcs7830_read_mac() - read an ethernet adapter's MAC address - * @eth: network device to read from - * Return: zero upon success, negative upon error - * - * this routine fetches the MAC address stored within the ethernet adapter, - * and stores it in the ethernet interface's data structure - */ -static int mcs7830_read_mac(struct eth_device *eth) -{ - struct ueth_data *dev; - int rc; - uint8_t buf[ETH_ALEN]; - - debug("%s()\n", __func__); - dev = eth->priv; - - rc = mcs7830_read_reg(dev, REG_ETHER_ADDR, ETH_ALEN, buf); - if (rc < 0) { - debug("reading MAC from adapter failed\n"); - return rc; - } - - memcpy(ð->enetaddr[0], buf, ETH_ALEN); - return 0; -} - -/* - * mcs7830_write_mac() - write an ethernet adapter's MAC address - * @eth: network device to write to - * Return: zero upon success, negative upon error - * - * this routine takes the MAC address from the ethernet interface's data - * structure, and writes it into the ethernet adapter such that subsequent - * exchange of ethernet frames uses this address - */ -static int mcs7830_write_mac(struct eth_device *eth) -{ - struct ueth_data *dev; - int rc; - - debug("%s()\n", __func__); - dev = eth->priv; - - if (sizeof(eth->enetaddr) != ETH_ALEN) - return -EINVAL; - rc = mcs7830_write_reg(dev, REG_ETHER_ADDR, ETH_ALEN, eth->enetaddr); - if (rc < 0) { - debug("writing MAC to adapter failed\n"); - return rc; - } - return 0; -} - -/* - * mcs7830_init() - network interface's init callback - * @eth: network device to initialize - * @bd: board information - * Return: zero upon success, negative upon error - * - * after initial setup during probe() and get_info(), this init() callback - * ensures that the link is up and subsequent send() and recv() calls can - * exchange ethernet frames - */ -static int mcs7830_init(struct eth_device *eth, bd_t *bd) -{ - struct ueth_data *dev; - int timeout; - int have_link; - - debug("%s()\n", __func__); - dev = eth->priv; - - timeout = 0; - do { - have_link = mcs7830_read_phy(dev, MII_BMSR) & BMSR_LSTATUS; - if (have_link) - break; - udelay(LINKSTATUS_TIMEOUT_RES * 1000); - timeout += LINKSTATUS_TIMEOUT_RES; - } while (timeout < LINKSTATUS_TIMEOUT); - if (!have_link) { - debug("ethernet link is down\n"); - return -ETIMEDOUT; - } - return 0; -} - -/* - * mcs7830_send() - network interface's send callback - * @eth: network device to send the frame from - * @packet: ethernet frame content - * @length: ethernet frame length - * Return: zero upon success, negative upon error - * - * this routine send an ethernet frame out of the network interface - */ -static int mcs7830_send(struct eth_device *eth, void *packet, int length) -{ - struct ueth_data *dev; - int rc; - int gotlen; - /* there is a status byte after the ethernet frame */ - ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, PKTSIZE + sizeof(uint8_t)); - - dev = eth->priv; - - memcpy(buf, packet, length); - rc = usb_bulk_msg(dev->pusb_dev, - usb_sndbulkpipe(dev->pusb_dev, dev->ep_out), - &buf[0], length, &gotlen, - USBCALL_TIMEOUT); - debug("%s() TX want len %d, got len %d, rc %d\n", - __func__, length, gotlen, rc); - return rc; -} - -/* - * mcs7830_recv() - network interface's recv callback - * @eth: network device to receive frames from - * Return: zero upon success, negative upon error - * - * this routine checks for available ethernet frames that the network - * interface might have received, and notifies the network stack - */ -static int mcs7830_recv(struct eth_device *eth) -{ - struct ueth_data *dev; - ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, MCS7830_RX_URB_SIZE); - int rc, wantlen, gotlen; - uint8_t sts; - - debug("%s()\n", __func__); - dev = eth->priv; - - /* fetch input data from the adapter */ - wantlen = MCS7830_RX_URB_SIZE; - rc = usb_bulk_msg(dev->pusb_dev, - usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in), - &buf[0], wantlen, &gotlen, - USBCALL_TIMEOUT); - debug("%s() RX want len %d, got len %d, rc %d\n", - __func__, wantlen, gotlen, rc); - if (rc != 0) { - error("RX: failed to receive\n"); - return rc; - } - if (gotlen > wantlen) { - error("RX: got too many bytes (%d)\n", gotlen); - return -EIO; - } - - /* - * the bulk message that we received from USB contains exactly - * one ethernet frame and a trailing status byte - */ - if (gotlen < sizeof(sts)) - return -EIO; - gotlen -= sizeof(sts); - sts = buf[gotlen]; - - if (sts == STAT_RX_FRAME_CORRECT) { - debug("%s() got a frame, len=%d\n", __func__, gotlen); - NetReceive(buf, gotlen); - return 0; - } - - debug("RX: frame error (sts 0x%02X, %s %s %s %s %s)\n", - sts, - (sts & STAT_RX_LARGE_FRAME) ? "large" : "-", - (sts & STAT_RX_LENGTH_ERROR) ? "length" : "-", - (sts & STAT_RX_SHORT_FRAME) ? "short" : "-", - (sts & STAT_RX_CRC_ERROR) ? "crc" : "-", - (sts & STAT_RX_ALIGNMENT_ERROR) ? "align" : "-"); - return -EIO; -} - -/* - * mcs7830_halt() - network interface's halt callback - * @eth: network device to cease operation of - * Return: none - * - * this routine is supposed to undo the effect of previous initialization and - * ethernet frames exchange; in this implementation it's a NOP - */ -static void mcs7830_halt(struct eth_device *eth) -{ - debug("%s()\n", __func__); -} - -/* - * mcs7830_iface_idx - index of detected network interfaces - * - * this counter keeps track of identified supported interfaces, - * to assign unique names as more interfaces are found - */ -static int mcs7830_iface_idx; - -/* - * mcs7830_eth_before_probe() - network driver's before_probe callback - * Return: none - * - * this routine initializes driver's internal data in preparation of - * subsequent probe callbacks - */ -void mcs7830_eth_before_probe(void) -{ - mcs7830_iface_idx = 0; -} - -/* - * struct mcs7830_dongle - description of a supported Moschip ethernet dongle - * @vendor: 16bit USB vendor identification - * @product: 16bit USB product identification - * - * this structure describes a supported USB ethernet dongle by means of the - * vendor and product codes found during USB enumeration; no flags are held - * here since all supported dongles have identical behaviour, and required - * fixups get determined at runtime, such that no manual configuration is - * needed - */ -struct mcs7830_dongle { - uint16_t vendor; - uint16_t product; -}; - -/* - * mcs7830_dongles - the list of supported Moschip based USB ethernet dongles - */ -static const struct mcs7830_dongle const mcs7830_dongles[] = { - { 0x9710, 0x7832, }, /* Moschip 7832 */ - { 0x9710, 0x7830, }, /* Moschip 7830 */ - { 0x9710, 0x7730, }, /* Moschip 7730 */ - { 0x0df6, 0x0021, }, /* Sitecom LN 30 */ -}; - -/* - * mcs7830_eth_probe() - network driver's probe callback - * @dev: detected USB device to check - * @ifnum: detected USB interface to check - * @ss: USB ethernet data structure to fill in upon match - * Return: #1 upon match, #0 upon mismatch or error - * - * this routine checks whether the found USB device is supported by - * this ethernet driver, and upon match fills in the USB ethernet - * data structure which later is passed to the get_info callback - */ -int mcs7830_eth_probe(struct usb_device *dev, unsigned int ifnum, - struct ueth_data *ss) -{ - struct usb_interface *iface; - struct usb_interface_descriptor *iface_desc; - int i; - struct mcs7830_private *priv; - int ep_in_found, ep_out_found, ep_intr_found; - - debug("%s()\n", __func__); - - /* iterate the list of supported dongles */ - iface = &dev->config.if_desc[ifnum]; - iface_desc = &iface->desc; - for (i = 0; i < ARRAY_SIZE(mcs7830_dongles); i++) { - if (dev->descriptor.idVendor == mcs7830_dongles[i].vendor && - dev->descriptor.idProduct == mcs7830_dongles[i].product) - break; - } - if (i == ARRAY_SIZE(mcs7830_dongles)) - return 0; - debug("detected USB ethernet device: %04X:%04X\n", - dev->descriptor.idVendor, dev->descriptor.idProduct); - - /* fill in driver private data */ - priv = calloc(1, sizeof(*priv)); - if (!priv) - return 0; - - /* fill in the ueth_data structure, attach private data */ - memset(ss, 0, sizeof(*ss)); - ss->ifnum = ifnum; - ss->pusb_dev = dev; - ss->subclass = iface_desc->bInterfaceSubClass; - ss->protocol = iface_desc->bInterfaceProtocol; - ss->dev_priv = priv; - - /* - * a minimum of three endpoints is expected: in (bulk), - * out (bulk), and interrupt; ignore all others - */ - ep_in_found = ep_out_found = ep_intr_found = 0; - for (i = 0; i < iface_desc->bNumEndpoints; i++) { - uint8_t eptype, epaddr; - bool is_input; - - eptype = iface->ep_desc[i].bmAttributes; - eptype &= USB_ENDPOINT_XFERTYPE_MASK; - - epaddr = iface->ep_desc[i].bEndpointAddress; - is_input = epaddr & USB_DIR_IN; - epaddr &= USB_ENDPOINT_NUMBER_MASK; - - if (eptype == USB_ENDPOINT_XFER_BULK) { - if (is_input && !ep_in_found) { - ss->ep_in = epaddr; - ep_in_found++; - } - if (!is_input && !ep_out_found) { - ss->ep_out = epaddr; - ep_out_found++; - } - } - - if (eptype == USB_ENDPOINT_XFER_INT) { - if (is_input && !ep_intr_found) { - ss->ep_int = epaddr; - ss->irqinterval = iface->ep_desc[i].bInterval; - ep_intr_found++; - } - } - } - debug("endpoints: in %d, out %d, intr %d\n", - ss->ep_in, ss->ep_out, ss->ep_int); - - /* apply basic sanity checks */ - if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) || - !ss->ep_in || !ss->ep_out || !ss->ep_int) { - debug("device probe incomplete\n"); - return 0; - } - - dev->privptr = ss; - return 1; -} - -/* - * mcs7830_eth_get_info() - network driver's get_info callback - * @dev: detected USB device - * @ss: USB ethernet data structure filled in at probe() - * @eth: ethernet interface data structure to fill in - * Return: #1 upon success, #0 upon error - * - * this routine registers the mandatory init(), send(), recv(), and - * halt() callbacks with the ethernet interface, can register the - * optional write_hwaddr() callback with the ethernet interface, - * and initiates configuration of the interface such that subsequent - * calls to those callbacks results in network communication - */ -int mcs7830_eth_get_info(struct usb_device *dev, struct ueth_data *ss, - struct eth_device *eth) -{ - debug("%s()\n", __func__); - if (!eth) { - debug("%s: missing parameter.\n", __func__); - return 0; - } - - snprintf(eth->name, sizeof(eth->name), "%s%d", - MCS7830_BASE_NAME, mcs7830_iface_idx++); - eth->init = mcs7830_init; - eth->send = mcs7830_send; - eth->recv = mcs7830_recv; - eth->halt = mcs7830_halt; - eth->write_hwaddr = mcs7830_write_mac; - eth->priv = ss; - - if (mcs7830_basic_reset(ss)) - return 0; - - if (mcs7830_read_mac(eth)) - return 0; - debug("MAC %pM\n", eth->enetaddr); - - return 1; -} diff --git a/qemu/roms/u-boot/drivers/usb/eth/smsc95xx.c b/qemu/roms/u-boot/drivers/usb/eth/smsc95xx.c deleted file mode 100644 index 7bf0a3407..000000000 --- a/qemu/roms/u-boot/drivers/usb/eth/smsc95xx.c +++ /dev/null @@ -1,897 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * Copyright (C) 2009 NVIDIA, Corporation - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <asm/unaligned.h> -#include <common.h> -#include <usb.h> -#include <linux/mii.h> -#include "usb_ether.h" -#include <malloc.h> - -/* SMSC LAN95xx based USB 2.0 Ethernet Devices */ - -/* LED defines */ -#define LED_GPIO_CFG (0x24) -#define LED_GPIO_CFG_SPD_LED (0x01000000) -#define LED_GPIO_CFG_LNK_LED (0x00100000) -#define LED_GPIO_CFG_FDX_LED (0x00010000) - -/* Tx command words */ -#define TX_CMD_A_FIRST_SEG_ 0x00002000 -#define TX_CMD_A_LAST_SEG_ 0x00001000 - -/* Rx status word */ -#define RX_STS_FL_ 0x3FFF0000 /* Frame Length */ -#define RX_STS_ES_ 0x00008000 /* Error Summary */ - -/* SCSRs */ -#define ID_REV 0x00 - -#define INT_STS 0x08 - -#define TX_CFG 0x10 -#define TX_CFG_ON_ 0x00000004 - -#define HW_CFG 0x14 -#define HW_CFG_BIR_ 0x00001000 -#define HW_CFG_RXDOFF_ 0x00000600 -#define HW_CFG_MEF_ 0x00000020 -#define HW_CFG_BCE_ 0x00000002 -#define HW_CFG_LRST_ 0x00000008 - -#define PM_CTRL 0x20 -#define PM_CTL_PHY_RST_ 0x00000010 - -#define AFC_CFG 0x2C - -/* - * Hi watermark = 15.5Kb (~10 mtu pkts) - * low watermark = 3k (~2 mtu pkts) - * backpressure duration = ~ 350us - * Apply FC on any frame. - */ -#define AFC_CFG_DEFAULT 0x00F830A1 - -#define E2P_CMD 0x30 -#define E2P_CMD_BUSY_ 0x80000000 -#define E2P_CMD_READ_ 0x00000000 -#define E2P_CMD_TIMEOUT_ 0x00000400 -#define E2P_CMD_LOADED_ 0x00000200 -#define E2P_CMD_ADDR_ 0x000001FF - -#define E2P_DATA 0x34 - -#define BURST_CAP 0x38 - -#define INT_EP_CTL 0x68 -#define INT_EP_CTL_PHY_INT_ 0x00008000 - -#define BULK_IN_DLY 0x6C - -/* MAC CSRs */ -#define MAC_CR 0x100 -#define MAC_CR_MCPAS_ 0x00080000 -#define MAC_CR_PRMS_ 0x00040000 -#define MAC_CR_HPFILT_ 0x00002000 -#define MAC_CR_TXEN_ 0x00000008 -#define MAC_CR_RXEN_ 0x00000004 - -#define ADDRH 0x104 - -#define ADDRL 0x108 - -#define MII_ADDR 0x114 -#define MII_WRITE_ 0x02 -#define MII_BUSY_ 0x01 -#define MII_READ_ 0x00 /* ~of MII Write bit */ - -#define MII_DATA 0x118 - -#define FLOW 0x11C - -#define VLAN1 0x120 - -#define COE_CR 0x130 -#define Tx_COE_EN_ 0x00010000 -#define Rx_COE_EN_ 0x00000001 - -/* Vendor-specific PHY Definitions */ -#define PHY_INT_SRC 29 - -#define PHY_INT_MASK 30 -#define PHY_INT_MASK_ANEG_COMP_ ((u16)0x0040) -#define PHY_INT_MASK_LINK_DOWN_ ((u16)0x0010) -#define PHY_INT_MASK_DEFAULT_ (PHY_INT_MASK_ANEG_COMP_ | \ - PHY_INT_MASK_LINK_DOWN_) - -/* USB Vendor Requests */ -#define USB_VENDOR_REQUEST_WRITE_REGISTER 0xA0 -#define USB_VENDOR_REQUEST_READ_REGISTER 0xA1 - -/* Some extra defines */ -#define HS_USB_PKT_SIZE 512 -#define FS_USB_PKT_SIZE 64 -#define DEFAULT_HS_BURST_CAP_SIZE (16 * 1024 + 5 * HS_USB_PKT_SIZE) -#define DEFAULT_FS_BURST_CAP_SIZE (6 * 1024 + 33 * FS_USB_PKT_SIZE) -#define DEFAULT_BULK_IN_DELAY 0x00002000 -#define MAX_SINGLE_PACKET_SIZE 2048 -#define EEPROM_MAC_OFFSET 0x01 -#define SMSC95XX_INTERNAL_PHY_ID 1 -#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ - -/* local defines */ -#define SMSC95XX_BASE_NAME "sms" -#define USB_CTRL_SET_TIMEOUT 5000 -#define USB_CTRL_GET_TIMEOUT 5000 -#define USB_BULK_SEND_TIMEOUT 5000 -#define USB_BULK_RECV_TIMEOUT 5000 - -#define AX_RX_URB_SIZE 2048 -#define PHY_CONNECT_TIMEOUT 5000 - -#define TURBO_MODE - -/* local vars */ -static int curr_eth_dev; /* index for name of next device detected */ - -/* driver private */ -struct smsc95xx_private { - size_t rx_urb_size; /* maximum USB URB size */ - u32 mac_cr; /* MAC control register value */ - int have_hwaddr; /* 1 if we have a hardware MAC address */ -}; - -/* - * Smsc95xx infrastructure commands - */ -static int smsc95xx_write_reg(struct ueth_data *dev, u32 index, u32 data) -{ - int len; - ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1); - - cpu_to_le32s(&data); - tmpbuf[0] = data; - - len = usb_control_msg(dev->pusb_dev, usb_sndctrlpipe(dev->pusb_dev, 0), - USB_VENDOR_REQUEST_WRITE_REGISTER, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 00, index, tmpbuf, sizeof(data), USB_CTRL_SET_TIMEOUT); - if (len != sizeof(data)) { - debug("smsc95xx_write_reg failed: index=%d, data=%d, len=%d", - index, data, len); - return -1; - } - return 0; -} - -static int smsc95xx_read_reg(struct ueth_data *dev, u32 index, u32 *data) -{ - int len; - ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1); - - len = usb_control_msg(dev->pusb_dev, usb_rcvctrlpipe(dev->pusb_dev, 0), - USB_VENDOR_REQUEST_READ_REGISTER, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 00, index, tmpbuf, sizeof(data), USB_CTRL_GET_TIMEOUT); - *data = tmpbuf[0]; - if (len != sizeof(data)) { - debug("smsc95xx_read_reg failed: index=%d, len=%d", - index, len); - return -1; - } - - le32_to_cpus(data); - return 0; -} - -/* Loop until the read is completed with timeout */ -static int smsc95xx_phy_wait_not_busy(struct ueth_data *dev) -{ - unsigned long start_time = get_timer(0); - u32 val; - - do { - smsc95xx_read_reg(dev, MII_ADDR, &val); - if (!(val & MII_BUSY_)) - return 0; - } while (get_timer(start_time) < 1 * 1000 * 1000); - - return -1; -} - -static int smsc95xx_mdio_read(struct ueth_data *dev, int phy_id, int idx) -{ - u32 val, addr; - - /* confirm MII not busy */ - if (smsc95xx_phy_wait_not_busy(dev)) { - debug("MII is busy in smsc95xx_mdio_read\n"); - return -1; - } - - /* set the address, index & direction (read from PHY) */ - addr = (phy_id << 11) | (idx << 6) | MII_READ_; - smsc95xx_write_reg(dev, MII_ADDR, addr); - - if (smsc95xx_phy_wait_not_busy(dev)) { - debug("Timed out reading MII reg %02X\n", idx); - return -1; - } - - smsc95xx_read_reg(dev, MII_DATA, &val); - - return (u16)(val & 0xFFFF); -} - -static void smsc95xx_mdio_write(struct ueth_data *dev, int phy_id, int idx, - int regval) -{ - u32 val, addr; - - /* confirm MII not busy */ - if (smsc95xx_phy_wait_not_busy(dev)) { - debug("MII is busy in smsc95xx_mdio_write\n"); - return; - } - - val = regval; - smsc95xx_write_reg(dev, MII_DATA, val); - - /* set the address, index & direction (write to PHY) */ - addr = (phy_id << 11) | (idx << 6) | MII_WRITE_; - smsc95xx_write_reg(dev, MII_ADDR, addr); - - if (smsc95xx_phy_wait_not_busy(dev)) - debug("Timed out writing MII reg %02X\n", idx); -} - -static int smsc95xx_eeprom_confirm_not_busy(struct ueth_data *dev) -{ - unsigned long start_time = get_timer(0); - u32 val; - - do { - smsc95xx_read_reg(dev, E2P_CMD, &val); - if (!(val & E2P_CMD_BUSY_)) - return 0; - udelay(40); - } while (get_timer(start_time) < 1 * 1000 * 1000); - - debug("EEPROM is busy\n"); - return -1; -} - -static int smsc95xx_wait_eeprom(struct ueth_data *dev) -{ - unsigned long start_time = get_timer(0); - u32 val; - - do { - smsc95xx_read_reg(dev, E2P_CMD, &val); - if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_)) - break; - udelay(40); - } while (get_timer(start_time) < 1 * 1000 * 1000); - - if (val & (E2P_CMD_TIMEOUT_ | E2P_CMD_BUSY_)) { - debug("EEPROM read operation timeout\n"); - return -1; - } - return 0; -} - -static int smsc95xx_read_eeprom(struct ueth_data *dev, u32 offset, u32 length, - u8 *data) -{ - u32 val; - int i, ret; - - ret = smsc95xx_eeprom_confirm_not_busy(dev); - if (ret) - return ret; - - for (i = 0; i < length; i++) { - val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_); - smsc95xx_write_reg(dev, E2P_CMD, val); - - ret = smsc95xx_wait_eeprom(dev); - if (ret < 0) - return ret; - - smsc95xx_read_reg(dev, E2P_DATA, &val); - data[i] = val & 0xFF; - offset++; - } - return 0; -} - -/* - * mii_nway_restart - restart NWay (autonegotiation) for this interface - * - * Returns 0 on success, negative on error. - */ -static int mii_nway_restart(struct ueth_data *dev) -{ - int bmcr; - int r = -1; - - /* if autoneg is off, it's an error */ - bmcr = smsc95xx_mdio_read(dev, dev->phy_id, MII_BMCR); - - if (bmcr & BMCR_ANENABLE) { - bmcr |= BMCR_ANRESTART; - smsc95xx_mdio_write(dev, dev->phy_id, MII_BMCR, bmcr); - r = 0; - } - return r; -} - -static int smsc95xx_phy_initialize(struct ueth_data *dev) -{ - smsc95xx_mdio_write(dev, dev->phy_id, MII_BMCR, BMCR_RESET); - smsc95xx_mdio_write(dev, dev->phy_id, MII_ADVERTISE, - ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | - ADVERTISE_PAUSE_ASYM); - - /* read to clear */ - smsc95xx_mdio_read(dev, dev->phy_id, PHY_INT_SRC); - - smsc95xx_mdio_write(dev, dev->phy_id, PHY_INT_MASK, - PHY_INT_MASK_DEFAULT_); - mii_nway_restart(dev); - - debug("phy initialised succesfully\n"); - return 0; -} - -static int smsc95xx_init_mac_address(struct eth_device *eth, - struct ueth_data *dev) -{ - /* try reading mac address from EEPROM */ - if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, - eth->enetaddr) == 0) { - if (is_valid_ether_addr(eth->enetaddr)) { - /* eeprom values are valid so use them */ - debug("MAC address read from EEPROM\n"); - return 0; - } - } - - /* - * No eeprom, or eeprom values are invalid. Generating a random MAC - * address is not safe. Just return an error. - */ - return -1; -} - -static int smsc95xx_write_hwaddr(struct eth_device *eth) -{ - struct ueth_data *dev = (struct ueth_data *)eth->priv; - struct smsc95xx_private *priv = dev->dev_priv; - u32 addr_lo = __get_unaligned_le32(ð->enetaddr[0]); - u32 addr_hi = __get_unaligned_le16(ð->enetaddr[4]); - int ret; - - /* set hardware address */ - debug("** %s()\n", __func__); - ret = smsc95xx_write_reg(dev, ADDRL, addr_lo); - if (ret < 0) - return ret; - - ret = smsc95xx_write_reg(dev, ADDRH, addr_hi); - if (ret < 0) - return ret; - - debug("MAC %pM\n", eth->enetaddr); - priv->have_hwaddr = 1; - return 0; -} - -/* Enable or disable Tx & Rx checksum offload engines */ -static int smsc95xx_set_csums(struct ueth_data *dev, - int use_tx_csum, int use_rx_csum) -{ - u32 read_buf; - int ret = smsc95xx_read_reg(dev, COE_CR, &read_buf); - if (ret < 0) - return ret; - - if (use_tx_csum) - read_buf |= Tx_COE_EN_; - else - read_buf &= ~Tx_COE_EN_; - - if (use_rx_csum) - read_buf |= Rx_COE_EN_; - else - read_buf &= ~Rx_COE_EN_; - - ret = smsc95xx_write_reg(dev, COE_CR, read_buf); - if (ret < 0) - return ret; - - debug("COE_CR = 0x%08x\n", read_buf); - return 0; -} - -static void smsc95xx_set_multicast(struct ueth_data *dev) -{ - struct smsc95xx_private *priv = dev->dev_priv; - - /* No multicast in u-boot */ - priv->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_); -} - -/* starts the TX path */ -static void smsc95xx_start_tx_path(struct ueth_data *dev) -{ - struct smsc95xx_private *priv = dev->dev_priv; - u32 reg_val; - - /* Enable Tx at MAC */ - priv->mac_cr |= MAC_CR_TXEN_; - - smsc95xx_write_reg(dev, MAC_CR, priv->mac_cr); - - /* Enable Tx at SCSRs */ - reg_val = TX_CFG_ON_; - smsc95xx_write_reg(dev, TX_CFG, reg_val); -} - -/* Starts the Receive path */ -static void smsc95xx_start_rx_path(struct ueth_data *dev) -{ - struct smsc95xx_private *priv = dev->dev_priv; - - priv->mac_cr |= MAC_CR_RXEN_; - smsc95xx_write_reg(dev, MAC_CR, priv->mac_cr); -} - -/* - * Smsc95xx callbacks - */ -static int smsc95xx_init(struct eth_device *eth, bd_t *bd) -{ - int ret; - u32 write_buf; - u32 read_buf; - u32 burst_cap; - int timeout; - struct ueth_data *dev = (struct ueth_data *)eth->priv; - struct smsc95xx_private *priv = - (struct smsc95xx_private *)dev->dev_priv; -#define TIMEOUT_RESOLUTION 50 /* ms */ - int link_detected; - - debug("** %s()\n", __func__); - dev->phy_id = SMSC95XX_INTERNAL_PHY_ID; /* fixed phy id */ - - write_buf = HW_CFG_LRST_; - ret = smsc95xx_write_reg(dev, HW_CFG, write_buf); - if (ret < 0) - return ret; - - timeout = 0; - do { - ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); - if (ret < 0) - return ret; - udelay(10 * 1000); - timeout++; - } while ((read_buf & HW_CFG_LRST_) && (timeout < 100)); - - if (timeout >= 100) { - debug("timeout waiting for completion of Lite Reset\n"); - return -1; - } - - write_buf = PM_CTL_PHY_RST_; - ret = smsc95xx_write_reg(dev, PM_CTRL, write_buf); - if (ret < 0) - return ret; - - timeout = 0; - do { - ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf); - if (ret < 0) - return ret; - udelay(10 * 1000); - timeout++; - } while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100)); - if (timeout >= 100) { - debug("timeout waiting for PHY Reset\n"); - return -1; - } - if (!priv->have_hwaddr && smsc95xx_init_mac_address(eth, dev) == 0) - priv->have_hwaddr = 1; - if (!priv->have_hwaddr) { - puts("Error: SMSC95xx: No MAC address set - set usbethaddr\n"); - return -1; - } - if (smsc95xx_write_hwaddr(eth) < 0) - return -1; - - ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); - if (ret < 0) - return ret; - debug("Read Value from HW_CFG : 0x%08x\n", read_buf); - - read_buf |= HW_CFG_BIR_; - ret = smsc95xx_write_reg(dev, HW_CFG, read_buf); - if (ret < 0) - return ret; - - ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); - if (ret < 0) - return ret; - debug("Read Value from HW_CFG after writing " - "HW_CFG_BIR_: 0x%08x\n", read_buf); - -#ifdef TURBO_MODE - if (dev->pusb_dev->speed == USB_SPEED_HIGH) { - burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE; - priv->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE; - } else { - burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE; - priv->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE; - } -#else - burst_cap = 0; - priv->rx_urb_size = MAX_SINGLE_PACKET_SIZE; -#endif - debug("rx_urb_size=%ld\n", (ulong)priv->rx_urb_size); - - ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap); - if (ret < 0) - return ret; - - ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf); - if (ret < 0) - return ret; - debug("Read Value from BURST_CAP after writing: 0x%08x\n", read_buf); - - read_buf = DEFAULT_BULK_IN_DELAY; - ret = smsc95xx_write_reg(dev, BULK_IN_DLY, read_buf); - if (ret < 0) - return ret; - - ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf); - if (ret < 0) - return ret; - debug("Read Value from BULK_IN_DLY after writing: " - "0x%08x\n", read_buf); - - ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); - if (ret < 0) - return ret; - debug("Read Value from HW_CFG: 0x%08x\n", read_buf); - -#ifdef TURBO_MODE - read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_); -#endif - read_buf &= ~HW_CFG_RXDOFF_; - -#define NET_IP_ALIGN 0 - read_buf |= NET_IP_ALIGN << 9; - - ret = smsc95xx_write_reg(dev, HW_CFG, read_buf); - if (ret < 0) - return ret; - - ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); - if (ret < 0) - return ret; - debug("Read Value from HW_CFG after writing: 0x%08x\n", read_buf); - - write_buf = 0xFFFFFFFF; - ret = smsc95xx_write_reg(dev, INT_STS, write_buf); - if (ret < 0) - return ret; - - ret = smsc95xx_read_reg(dev, ID_REV, &read_buf); - if (ret < 0) - return ret; - debug("ID_REV = 0x%08x\n", read_buf); - - /* Configure GPIO pins as LED outputs */ - write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED | - LED_GPIO_CFG_FDX_LED; - ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf); - if (ret < 0) - return ret; - debug("LED_GPIO_CFG set\n"); - - /* Init Tx */ - write_buf = 0; - ret = smsc95xx_write_reg(dev, FLOW, write_buf); - if (ret < 0) - return ret; - - read_buf = AFC_CFG_DEFAULT; - ret = smsc95xx_write_reg(dev, AFC_CFG, read_buf); - if (ret < 0) - return ret; - - ret = smsc95xx_read_reg(dev, MAC_CR, &priv->mac_cr); - if (ret < 0) - return ret; - - /* Init Rx. Set Vlan */ - write_buf = (u32)ETH_P_8021Q; - ret = smsc95xx_write_reg(dev, VLAN1, write_buf); - if (ret < 0) - return ret; - - /* Disable checksum offload engines */ - ret = smsc95xx_set_csums(dev, 0, 0); - if (ret < 0) { - debug("Failed to set csum offload: %d\n", ret); - return ret; - } - smsc95xx_set_multicast(dev); - - if (smsc95xx_phy_initialize(dev) < 0) - return -1; - ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf); - if (ret < 0) - return ret; - - /* enable PHY interrupts */ - read_buf |= INT_EP_CTL_PHY_INT_; - - ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf); - if (ret < 0) - return ret; - - smsc95xx_start_tx_path(dev); - smsc95xx_start_rx_path(dev); - - timeout = 0; - do { - link_detected = smsc95xx_mdio_read(dev, dev->phy_id, MII_BMSR) - & BMSR_LSTATUS; - if (!link_detected) { - if (timeout == 0) - printf("Waiting for Ethernet connection... "); - udelay(TIMEOUT_RESOLUTION * 1000); - timeout += TIMEOUT_RESOLUTION; - } - } while (!link_detected && timeout < PHY_CONNECT_TIMEOUT); - if (link_detected) { - if (timeout != 0) - printf("done.\n"); - } else { - printf("unable to connect.\n"); - return -1; - } - return 0; -} - -static int smsc95xx_send(struct eth_device *eth, void* packet, int length) -{ - struct ueth_data *dev = (struct ueth_data *)eth->priv; - int err; - int actual_len; - u32 tx_cmd_a; - u32 tx_cmd_b; - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg, - PKTSIZE + sizeof(tx_cmd_a) + sizeof(tx_cmd_b)); - - debug("** %s(), len %d, buf %#x\n", __func__, length, (int)msg); - if (length > PKTSIZE) - return -1; - - tx_cmd_a = (u32)length | TX_CMD_A_FIRST_SEG_ | TX_CMD_A_LAST_SEG_; - tx_cmd_b = (u32)length; - cpu_to_le32s(&tx_cmd_a); - cpu_to_le32s(&tx_cmd_b); - - /* prepend cmd_a and cmd_b */ - memcpy(msg, &tx_cmd_a, sizeof(tx_cmd_a)); - memcpy(msg + sizeof(tx_cmd_a), &tx_cmd_b, sizeof(tx_cmd_b)); - memcpy(msg + sizeof(tx_cmd_a) + sizeof(tx_cmd_b), (void *)packet, - length); - err = usb_bulk_msg(dev->pusb_dev, - usb_sndbulkpipe(dev->pusb_dev, dev->ep_out), - (void *)msg, - length + sizeof(tx_cmd_a) + sizeof(tx_cmd_b), - &actual_len, - USB_BULK_SEND_TIMEOUT); - debug("Tx: len = %u, actual = %u, err = %d\n", - length + sizeof(tx_cmd_a) + sizeof(tx_cmd_b), - actual_len, err); - return err; -} - -static int smsc95xx_recv(struct eth_device *eth) -{ - struct ueth_data *dev = (struct ueth_data *)eth->priv; - DEFINE_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, AX_RX_URB_SIZE); - unsigned char *buf_ptr; - int err; - int actual_len; - u32 packet_len; - int cur_buf_align; - - debug("** %s()\n", __func__); - err = usb_bulk_msg(dev->pusb_dev, - usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in), - (void *)recv_buf, - AX_RX_URB_SIZE, - &actual_len, - USB_BULK_RECV_TIMEOUT); - debug("Rx: len = %u, actual = %u, err = %d\n", AX_RX_URB_SIZE, - actual_len, err); - if (err != 0) { - debug("Rx: failed to receive\n"); - return -1; - } - if (actual_len > AX_RX_URB_SIZE) { - debug("Rx: received too many bytes %d\n", actual_len); - return -1; - } - - buf_ptr = recv_buf; - while (actual_len > 0) { - /* - * 1st 4 bytes contain the length of the actual data plus error - * info. Extract data length. - */ - if (actual_len < sizeof(packet_len)) { - debug("Rx: incomplete packet length\n"); - return -1; - } - memcpy(&packet_len, buf_ptr, sizeof(packet_len)); - le32_to_cpus(&packet_len); - if (packet_len & RX_STS_ES_) { - debug("Rx: Error header=%#x", packet_len); - return -1; - } - packet_len = ((packet_len & RX_STS_FL_) >> 16); - - if (packet_len > actual_len - sizeof(packet_len)) { - debug("Rx: too large packet: %d\n", packet_len); - return -1; - } - - /* Notify net stack */ - NetReceive(buf_ptr + sizeof(packet_len), packet_len - 4); - - /* Adjust for next iteration */ - actual_len -= sizeof(packet_len) + packet_len; - buf_ptr += sizeof(packet_len) + packet_len; - cur_buf_align = (int)buf_ptr - (int)recv_buf; - - if (cur_buf_align & 0x03) { - int align = 4 - (cur_buf_align & 0x03); - - actual_len -= align; - buf_ptr += align; - } - } - return err; -} - -static void smsc95xx_halt(struct eth_device *eth) -{ - debug("** %s()\n", __func__); -} - -/* - * SMSC probing functions - */ -void smsc95xx_eth_before_probe(void) -{ - curr_eth_dev = 0; -} - -struct smsc95xx_dongle { - unsigned short vendor; - unsigned short product; -}; - -static const struct smsc95xx_dongle smsc95xx_dongles[] = { - { 0x0424, 0xec00 }, /* LAN9512/LAN9514 Ethernet */ - { 0x0424, 0x9500 }, /* LAN9500 Ethernet */ - { 0x0424, 0x9730 }, /* LAN9730 Ethernet (HSIC) */ - { 0x0424, 0x9900 }, /* SMSC9500 USB Ethernet Device (SAL10) */ - { 0x0000, 0x0000 } /* END - Do not remove */ -}; - -/* Probe to see if a new device is actually an SMSC device */ -int smsc95xx_eth_probe(struct usb_device *dev, unsigned int ifnum, - struct ueth_data *ss) -{ - struct usb_interface *iface; - struct usb_interface_descriptor *iface_desc; - int i; - - /* let's examine the device now */ - iface = &dev->config.if_desc[ifnum]; - iface_desc = &dev->config.if_desc[ifnum].desc; - - for (i = 0; smsc95xx_dongles[i].vendor != 0; i++) { - if (dev->descriptor.idVendor == smsc95xx_dongles[i].vendor && - dev->descriptor.idProduct == smsc95xx_dongles[i].product) - /* Found a supported dongle */ - break; - } - if (smsc95xx_dongles[i].vendor == 0) - return 0; - - /* At this point, we know we've got a live one */ - debug("\n\nUSB Ethernet device detected\n"); - memset(ss, '\0', sizeof(struct ueth_data)); - - /* Initialize the ueth_data structure with some useful info */ - ss->ifnum = ifnum; - ss->pusb_dev = dev; - ss->subclass = iface_desc->bInterfaceSubClass; - ss->protocol = iface_desc->bInterfaceProtocol; - - /* - * We are expecting a minimum of 3 endpoints - in, out (bulk), and int. - * We will ignore any others. - */ - for (i = 0; i < iface_desc->bNumEndpoints; i++) { - /* is it an BULK endpoint? */ - if ((iface->ep_desc[i].bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { - if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN) - ss->ep_in = - iface->ep_desc[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - else - ss->ep_out = - iface->ep_desc[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - } - - /* is it an interrupt endpoint? */ - if ((iface->ep_desc[i].bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { - ss->ep_int = iface->ep_desc[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - ss->irqinterval = iface->ep_desc[i].bInterval; - } - } - debug("Endpoints In %d Out %d Int %d\n", - ss->ep_in, ss->ep_out, ss->ep_int); - - /* Do some basic sanity checks, and bail if we find a problem */ - if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) || - !ss->ep_in || !ss->ep_out || !ss->ep_int) { - debug("Problems with device\n"); - return 0; - } - dev->privptr = (void *)ss; - - /* alloc driver private */ - ss->dev_priv = calloc(1, sizeof(struct smsc95xx_private)); - if (!ss->dev_priv) - return 0; - - return 1; -} - -int smsc95xx_eth_get_info(struct usb_device *dev, struct ueth_data *ss, - struct eth_device *eth) -{ - debug("** %s()\n", __func__); - if (!eth) { - debug("%s: missing parameter.\n", __func__); - return 0; - } - sprintf(eth->name, "%s%d", SMSC95XX_BASE_NAME, curr_eth_dev++); - eth->init = smsc95xx_init; - eth->send = smsc95xx_send; - eth->recv = smsc95xx_recv; - eth->halt = smsc95xx_halt; - eth->write_hwaddr = smsc95xx_write_hwaddr; - eth->priv = ss; - return 1; -} diff --git a/qemu/roms/u-boot/drivers/usb/eth/usb_ether.c b/qemu/roms/u-boot/drivers/usb/eth/usb_ether.c deleted file mode 100644 index 1dda54c2f..000000000 --- a/qemu/roms/u-boot/drivers/usb/eth/usb_ether.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> - -#include "usb_ether.h" - -typedef void (*usb_eth_before_probe)(void); -typedef int (*usb_eth_probe)(struct usb_device *dev, unsigned int ifnum, - struct ueth_data *ss); -typedef int (*usb_eth_get_info)(struct usb_device *dev, struct ueth_data *ss, - struct eth_device *dev_desc); - -struct usb_eth_prob_dev { - usb_eth_before_probe before_probe; /* optional */ - usb_eth_probe probe; - usb_eth_get_info get_info; -}; - -/* driver functions go here, each bracketed by #ifdef CONFIG_USB_ETHER_xxx */ -static const struct usb_eth_prob_dev prob_dev[] = { -#ifdef CONFIG_USB_ETHER_ASIX - { - .before_probe = asix_eth_before_probe, - .probe = asix_eth_probe, - .get_info = asix_eth_get_info, - }, -#endif -#ifdef CONFIG_USB_ETHER_MCS7830 - { - .before_probe = mcs7830_eth_before_probe, - .probe = mcs7830_eth_probe, - .get_info = mcs7830_eth_get_info, - }, -#endif -#ifdef CONFIG_USB_ETHER_SMSC95XX - { - .before_probe = smsc95xx_eth_before_probe, - .probe = smsc95xx_eth_probe, - .get_info = smsc95xx_eth_get_info, - }, -#endif - { }, /* END */ -}; - -static int usb_max_eth_dev; /* number of highest available usb eth device */ -static struct ueth_data usb_eth[USB_MAX_ETH_DEV]; - -/******************************************************************************* - * tell if current ethernet device is a usb dongle - */ -int is_eth_dev_on_usb_host(void) -{ - int i; - struct eth_device *dev = eth_get_dev(); - - if (dev) { - for (i = 0; i < usb_max_eth_dev; i++) - if (&usb_eth[i].eth_dev == dev) - return 1; - } - return 0; -} - -/* - * Given a USB device, ask each driver if it can support it, and attach it - * to the first driver that says 'yes' - */ -static void probe_valid_drivers(struct usb_device *dev) -{ - struct eth_device *eth; - int j; - - for (j = 0; prob_dev[j].probe && prob_dev[j].get_info; j++) { - if (!prob_dev[j].probe(dev, 0, &usb_eth[usb_max_eth_dev])) - continue; - /* - * ok, it is a supported eth device. Get info and fill it in - */ - eth = &usb_eth[usb_max_eth_dev].eth_dev; - if (prob_dev[j].get_info(dev, - &usb_eth[usb_max_eth_dev], - eth)) { - /* found proper driver */ - /* register with networking stack */ - usb_max_eth_dev++; - - /* - * usb_max_eth_dev must be incremented prior to this - * call since eth_current_changed (internally called) - * relies on it - */ - eth_register(eth); - if (eth_write_hwaddr(eth, "usbeth", - usb_max_eth_dev - 1)) - puts("Warning: failed to set MAC address\n"); - break; - } - } - } - -/******************************************************************************* - * scan the usb and reports device info - * to the user if mode = 1 - * returns current device or -1 if no - */ -int usb_host_eth_scan(int mode) -{ - int i, old_async; - struct usb_device *dev; - - - if (mode == 1) - printf(" scanning usb for ethernet devices... "); - - old_async = usb_disable_asynch(1); /* asynch transfer not allowed */ - - /* unregister a previously detected device */ - for (i = 0; i < usb_max_eth_dev; i++) - eth_unregister(&usb_eth[i].eth_dev); - - memset(usb_eth, 0, sizeof(usb_eth)); - - for (i = 0; prob_dev[i].probe; i++) { - if (prob_dev[i].before_probe) - prob_dev[i].before_probe(); - } - - usb_max_eth_dev = 0; - for (i = 0; i < USB_MAX_DEVICE; i++) { - dev = usb_get_dev_index(i); /* get device */ - debug("i=%d\n", i); - if (dev == NULL) - break; /* no more devices available */ - - /* find valid usb_ether driver for this device, if any */ - probe_valid_drivers(dev); - - /* check limit */ - if (usb_max_eth_dev == USB_MAX_ETH_DEV) { - printf("max USB Ethernet Device reached: %d stopping\n", - usb_max_eth_dev); - break; - } - } /* for */ - - usb_disable_asynch(old_async); /* restore asynch value */ - printf("%d Ethernet Device(s) found\n", usb_max_eth_dev); - if (usb_max_eth_dev > 0) - return 0; - return -1; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/Makefile b/qemu/roms/u-boot/drivers/usb/gadget/Makefile deleted file mode 100644 index 896c8d407..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -# -# (C) Copyright 2000-2007 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -obj-$(CONFIG_USB_GADGET) += epautoconf.o config.o usbstring.o -obj-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o - -# new USB gadget layer dependencies -ifdef CONFIG_USB_GADGET -obj-$(CONFIG_USB_GADGET_ATMEL_USBA) += atmel_usba_udc.o -obj-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o -obj-$(CONFIG_USB_GADGET_FOTG210) += fotg210.o -obj-$(CONFIG_CI_UDC) += ci_udc.o -obj-$(CONFIG_THOR_FUNCTION) += f_thor.o -obj-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o -obj-$(CONFIG_DFU_FUNCTION) += f_dfu.o -obj-$(CONFIG_USB_GADGET_MASS_STORAGE) += f_mass_storage.o -endif -ifdef CONFIG_USB_ETHER -obj-y += ether.o -obj-$(CONFIG_USB_ETH_RNDIS) += rndis.o -obj-$(CONFIG_CI_UDC) += ci_udc.o -obj-$(CONFIG_CPU_PXA25X) += pxa25x_udc.o -else -# Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE -ifdef CONFIG_USB_DEVICE -obj-y += core.o -obj-y += ep0.o -obj-$(CONFIG_DW_UDC) += designware_udc.o -obj-$(CONFIG_OMAP1510) += omap1510_udc.o -obj-$(CONFIG_OMAP1610) += omap1510_udc.o -obj-$(CONFIG_MPC885_FAMILY) += mpc8xx_udc.o -obj-$(CONFIG_CPU_PXA27X) += pxa27x_udc.o -endif -endif diff --git a/qemu/roms/u-boot/drivers/usb/gadget/atmel_usba_udc.c b/qemu/roms/u-boot/drivers/usb/gadget/atmel_usba_udc.c deleted file mode 100644 index c99208d10..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/atmel_usba_udc.c +++ /dev/null @@ -1,1306 +0,0 @@ -/* - * Driver for the Atmel USBA high speed USB device controller - * [Original from Linux kernel: drivers/usb/gadget/atmel_usba_udc.c] - * - * Copyright (C) 2005-2013 Atmel Corporation - * Bo Shen <voice.shen@atmel.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/errno.h> -#include <asm/gpio.h> -#include <asm/hardware.h> -#include <linux/list.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <linux/usb/atmel_usba_udc.h> -#include <malloc.h> -#include <usb/lin_gadget_compat.h> - -#include "atmel_usba_udc.h" - -static int vbus_is_present(struct usba_udc *udc) -{ - /* No Vbus detection: Assume always present */ - return 1; -} - -static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req) -{ - unsigned int transaction_len; - - transaction_len = req->req.length - req->req.actual; - req->last_transaction = 1; - if (transaction_len > ep->ep.maxpacket) { - transaction_len = ep->ep.maxpacket; - req->last_transaction = 0; - } else if (transaction_len == ep->ep.maxpacket && req->req.zero) { - req->last_transaction = 0; - } - - DBG(DBG_QUEUE, "%s: submit_transaction, req %p (length %d)%s\n", - ep->ep.name, req, transaction_len, - req->last_transaction ? ", done" : ""); - - memcpy(ep->fifo, req->req.buf + req->req.actual, transaction_len); - usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY); - req->req.actual += transaction_len; -} - -static void submit_request(struct usba_ep *ep, struct usba_request *req) -{ - DBG(DBG_QUEUE, "%s: submit_request: req %p (length %d), dma: %d\n", - ep->ep.name, req, req->req.length, req->using_dma); - - req->req.actual = 0; - req->submitted = 1; - - next_fifo_transaction(ep, req); - if (req->last_transaction) { - usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY); - usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE); - } else { - usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); - usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY); - } -} - -static void submit_next_request(struct usba_ep *ep) -{ - struct usba_request *req; - - if (list_empty(&ep->queue)) { - usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY | USBA_RX_BK_RDY); - return; - } - - req = list_entry(ep->queue.next, struct usba_request, queue); - if (!req->submitted) - submit_request(ep, req); -} - -static void send_status(struct usba_udc *udc, struct usba_ep *ep) -{ - ep->state = STATUS_STAGE_IN; - usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY); - usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE); -} - -static void receive_data(struct usba_ep *ep) -{ - struct usba_udc *udc = ep->udc; - struct usba_request *req; - unsigned long status; - unsigned int bytecount, nr_busy; - int is_complete = 0; - - status = usba_ep_readl(ep, STA); - nr_busy = USBA_BFEXT(BUSY_BANKS, status); - - DBG(DBG_QUEUE, "receive data: nr_busy=%u\n", nr_busy); - - while (nr_busy > 0) { - if (list_empty(&ep->queue)) { - usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY); - break; - } - req = list_entry(ep->queue.next, - struct usba_request, queue); - - bytecount = USBA_BFEXT(BYTE_COUNT, status); - - if (status & USBA_SHORT_PACKET) - is_complete = 1; - if (req->req.actual + bytecount >= req->req.length) { - is_complete = 1; - bytecount = req->req.length - req->req.actual; - } - - memcpy(req->req.buf + req->req.actual, ep->fifo, bytecount); - req->req.actual += bytecount; - - usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY); - - if (is_complete) { - DBG(DBG_QUEUE, "%s: request done\n", ep->ep.name); - req->req.status = 0; - list_del_init(&req->queue); - usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY); - spin_lock(&udc->lock); - req->req.complete(&ep->ep, &req->req); - spin_unlock(&udc->lock); - } - - status = usba_ep_readl(ep, STA); - nr_busy = USBA_BFEXT(BUSY_BANKS, status); - - if (is_complete && ep_is_control(ep)) { - send_status(udc, ep); - break; - } - } -} - -static void -request_complete(struct usba_ep *ep, struct usba_request *req, int status) -{ - if (req->req.status == -EINPROGRESS) - req->req.status = status; - - DBG(DBG_GADGET | DBG_REQ, "%s: req %p complete: status %d, actual %u\n", - ep->ep.name, req, req->req.status, req->req.actual); - - req->req.complete(&ep->ep, &req->req); -} - -static void -request_complete_list(struct usba_ep *ep, struct list_head *list, int status) -{ - struct usba_request *req, *tmp_req; - - list_for_each_entry_safe(req, tmp_req, list, queue) { - list_del_init(&req->queue); - request_complete(ep, req, status); - } -} - -static int -usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) -{ - struct usba_ep *ep = to_usba_ep(_ep); - struct usba_udc *udc = ep->udc; - unsigned long flags, ept_cfg, maxpacket; - unsigned int nr_trans; - - DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc); - - maxpacket = usb_endpoint_maxp(desc) & 0x7ff; - - if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) - != ep->index) || - ep->index == 0 || - desc->bDescriptorType != USB_DT_ENDPOINT || - maxpacket == 0 || - maxpacket > ep->fifo_size) { - DBG(DBG_ERR, "ep_enable: Invalid argument"); - return -EINVAL; - } - - ep->is_isoc = 0; - ep->is_in = 0; - - if (maxpacket <= 8) - ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8); - else - /* LSB is bit 1, not 0 */ - ept_cfg = USBA_BF(EPT_SIZE, fls(maxpacket - 1) - 3); - - DBG(DBG_HW, "%s: EPT_SIZE = %lu (maxpacket = %lu)\n", - ep->ep.name, ept_cfg, maxpacket); - - if (usb_endpoint_dir_in(desc)) { - ep->is_in = 1; - ept_cfg |= USBA_EPT_DIR_IN; - } - - switch (usb_endpoint_type(desc)) { - case USB_ENDPOINT_XFER_CONTROL: - ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL); - ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE); - break; - case USB_ENDPOINT_XFER_ISOC: - if (!ep->can_isoc) { - DBG(DBG_ERR, "ep_enable: %s is not isoc capable\n", - ep->ep.name); - return -EINVAL; - } - - /* - * Bits 11:12 specify number of _additional_ - * transactions per microframe. - */ - nr_trans = ((usb_endpoint_maxp(desc) >> 11) & 3) + 1; - if (nr_trans > 3) - return -EINVAL; - - ep->is_isoc = 1; - ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO); - - /* - * Do triple-buffering on high-bandwidth iso endpoints. - */ - if (nr_trans > 1 && ep->nr_banks == 3) - ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_TRIPLE); - else - ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE); - ept_cfg |= USBA_BF(NB_TRANS, nr_trans); - break; - case USB_ENDPOINT_XFER_BULK: - ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK); - ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE); - break; - case USB_ENDPOINT_XFER_INT: - ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT); - ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE); - break; - } - - spin_lock_irqsave(&ep->udc->lock, flags); - - ep->desc = desc; - ep->ep.maxpacket = maxpacket; - - usba_ep_writel(ep, CFG, ept_cfg); - usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE); - - usba_writel(udc, INT_ENB, - (usba_readl(udc, INT_ENB) - | USBA_BF(EPT_INT, 1 << ep->index))); - - spin_unlock_irqrestore(&udc->lock, flags); - - DBG(DBG_HW, "EPT_CFG%d after init: %#08lx\n", ep->index, - (unsigned long)usba_ep_readl(ep, CFG)); - DBG(DBG_HW, "INT_ENB after init: %#08lx\n", - (unsigned long)usba_readl(udc, INT_ENB)); - - return 0; -} - -static int usba_ep_disable(struct usb_ep *_ep) -{ - struct usba_ep *ep = to_usba_ep(_ep); - struct usba_udc *udc = ep->udc; - LIST_HEAD(req_list); - unsigned long flags; - - DBG(DBG_GADGET, "ep_disable: %s\n", ep->ep.name); - - spin_lock_irqsave(&udc->lock, flags); - - if (!ep->desc) { - spin_unlock_irqrestore(&udc->lock, flags); - /* REVISIT because this driver disables endpoints in - * reset_all_endpoints() before calling disconnect(), - * most gadget drivers would trigger this non-error ... - */ - if (udc->gadget.speed != USB_SPEED_UNKNOWN) - DBG(DBG_ERR, "ep_disable: %s not enabled\n", - ep->ep.name); - return -EINVAL; - } - ep->desc = NULL; - - list_splice_init(&ep->queue, &req_list); - usba_ep_writel(ep, CFG, 0); - usba_ep_writel(ep, CTL_DIS, USBA_EPT_ENABLE); - usba_writel(udc, INT_ENB, - usba_readl(udc, INT_ENB) & - ~USBA_BF(EPT_INT, 1 << ep->index)); - - request_complete_list(ep, &req_list, -ESHUTDOWN); - - spin_unlock_irqrestore(&udc->lock, flags); - - return 0; -} - -static struct usb_request * -usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) -{ - struct usba_request *req; - - DBG(DBG_GADGET, "ep_alloc_request: %p, 0x%x\n", _ep, gfp_flags); - - req = malloc(sizeof(struct usba_request)); - if (!req) - return NULL; - - INIT_LIST_HEAD(&req->queue); - - return &req->req; -} - -static void -usba_ep_free_request(struct usb_ep *_ep, struct usb_request *_req) -{ - struct usba_request *req = to_usba_req(_req); - - DBG(DBG_GADGET, "ep_free_request: %p, %p\n", _ep, _req); - - free(req); -} - -static int -usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) -{ - struct usba_request *req = to_usba_req(_req); - struct usba_ep *ep = to_usba_ep(_ep); - struct usba_udc *udc = ep->udc; - unsigned long flags; - int ret; - - DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, "%s: queue req %p, len %u\n", - ep->ep.name, req, _req->length); - - if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN || - !ep->desc) - return -ESHUTDOWN; - - req->submitted = 0; - req->using_dma = 0; - req->last_transaction = 0; - - _req->status = -EINPROGRESS; - _req->actual = 0; - - /* May have received a reset since last time we checked */ - ret = -ESHUTDOWN; - spin_lock_irqsave(&udc->lock, flags); - if (ep->desc) { - list_add_tail(&req->queue, &ep->queue); - - if ((!ep_is_control(ep) && ep->is_in) || - (ep_is_control(ep) && (ep->state == DATA_STAGE_IN || - ep->state == STATUS_STAGE_IN))) - usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY); - else - usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY); - - ret = 0; - } - spin_unlock_irqrestore(&udc->lock, flags); - - return ret; -} - -static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) -{ - struct usba_ep *ep = to_usba_ep(_ep); - struct usba_request *req = to_usba_req(_req); - - DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n", - ep->ep.name, req); - - /* - * Errors should stop the queue from advancing until the - * completion function returns. - */ - list_del_init(&req->queue); - - request_complete(ep, req, -ECONNRESET); - - /* Process the next request if any */ - submit_next_request(ep); - - return 0; -} - -static int usba_ep_set_halt(struct usb_ep *_ep, int value) -{ - struct usba_ep *ep = to_usba_ep(_ep); - unsigned long flags; - int ret = 0; - - DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep->ep.name, - value ? "set" : "clear"); - - if (!ep->desc) { - DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n", - ep->ep.name); - return -ENODEV; - } - - if (ep->is_isoc) { - DBG(DBG_ERR, "Attempted to halt isochronous ep %s\n", - ep->ep.name); - return -ENOTTY; - } - - spin_lock_irqsave(&udc->lock, flags); - - /* - * We can't halt IN endpoints while there are still data to be - * transferred - */ - if (!list_empty(&ep->queue) || - ((value && ep->is_in && (usba_ep_readl(ep, STA) & - USBA_BF(BUSY_BANKS, -1L))))) { - ret = -EAGAIN; - } else { - if (value) - usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL); - else - usba_ep_writel(ep, CLR_STA, - USBA_FORCE_STALL | USBA_TOGGLE_CLR); - usba_ep_readl(ep, STA); - } - - spin_unlock_irqrestore(&udc->lock, flags); - - return ret; -} - -static int usba_ep_fifo_status(struct usb_ep *_ep) -{ - struct usba_ep *ep = to_usba_ep(_ep); - - return USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA)); -} - -static void usba_ep_fifo_flush(struct usb_ep *_ep) -{ - struct usba_ep *ep = to_usba_ep(_ep); - struct usba_udc *udc = ep->udc; - - usba_writel(udc, EPT_RST, 1 << ep->index); -} - -static const struct usb_ep_ops usba_ep_ops = { - .enable = usba_ep_enable, - .disable = usba_ep_disable, - .alloc_request = usba_ep_alloc_request, - .free_request = usba_ep_free_request, - .queue = usba_ep_queue, - .dequeue = usba_ep_dequeue, - .set_halt = usba_ep_set_halt, - .fifo_status = usba_ep_fifo_status, - .fifo_flush = usba_ep_fifo_flush, -}; - -static int usba_udc_get_frame(struct usb_gadget *gadget) -{ - struct usba_udc *udc = to_usba_udc(gadget); - - return USBA_BFEXT(FRAME_NUMBER, usba_readl(udc, FNUM)); -} - -static int usba_udc_wakeup(struct usb_gadget *gadget) -{ - struct usba_udc *udc = to_usba_udc(gadget); - unsigned long flags; - u32 ctrl; - int ret = -EINVAL; - - spin_lock_irqsave(&udc->lock, flags); - if (udc->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { - ctrl = usba_readl(udc, CTRL); - usba_writel(udc, CTRL, ctrl | USBA_REMOTE_WAKE_UP); - ret = 0; - } - spin_unlock_irqrestore(&udc->lock, flags); - - return ret; -} - -static int -usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered) -{ - struct usba_udc *udc = to_usba_udc(gadget); - unsigned long flags; - - spin_lock_irqsave(&udc->lock, flags); - if (is_selfpowered) - udc->devstatus |= 1 << USB_DEVICE_SELF_POWERED; - else - udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED); - spin_unlock_irqrestore(&udc->lock, flags); - - return 0; -} - -static const struct usb_gadget_ops usba_udc_ops = { - .get_frame = usba_udc_get_frame, - .wakeup = usba_udc_wakeup, - .set_selfpowered = usba_udc_set_selfpowered, -}; - -static struct usb_endpoint_descriptor usba_ep0_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0, - .bmAttributes = USB_ENDPOINT_XFER_CONTROL, - .wMaxPacketSize = cpu_to_le16(64), - /* FIXME: I have no idea what to put here */ - .bInterval = 1, -}; - -/* - * Called with interrupts disabled and udc->lock held. - */ -static void reset_all_endpoints(struct usba_udc *udc) -{ - struct usba_ep *ep; - struct usba_request *req, *tmp_req; - - usba_writel(udc, EPT_RST, ~0UL); - - ep = to_usba_ep(udc->gadget.ep0); - list_for_each_entry_safe(req, tmp_req, &ep->queue, queue) { - list_del_init(&req->queue); - request_complete(ep, req, -ECONNRESET); - } - - /* NOTE: normally, the next call to the gadget driver is in - * charge of disabling endpoints... usually disconnect(). - * The exception would be entering a high speed test mode. - * - * FIXME remove this code ... and retest thoroughly. - */ - list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { - if (ep->desc) { - spin_unlock(&udc->lock); - usba_ep_disable(&ep->ep); - spin_lock(&udc->lock); - } - } -} - -static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex) -{ - struct usba_ep *ep; - - if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0) - return to_usba_ep(udc->gadget.ep0); - - list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { - u8 bEndpointAddress; - - if (!ep->desc) - continue; - bEndpointAddress = ep->desc->bEndpointAddress; - if ((wIndex ^ bEndpointAddress) & USB_DIR_IN) - continue; - if ((bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) - == (wIndex & USB_ENDPOINT_NUMBER_MASK)) - return ep; - } - - return NULL; -} - -/* Called with interrupts disabled and udc->lock held */ -static inline void set_protocol_stall(struct usba_udc *udc, struct usba_ep *ep) -{ - usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL); - ep->state = WAIT_FOR_SETUP; -} - -static inline int is_stalled(struct usba_udc *udc, struct usba_ep *ep) -{ - if (usba_ep_readl(ep, STA) & USBA_FORCE_STALL) - return 1; - return 0; -} - -static inline void set_address(struct usba_udc *udc, unsigned int addr) -{ - u32 regval; - - DBG(DBG_BUS, "setting address %u...\n", addr); - regval = usba_readl(udc, CTRL); - regval = USBA_BFINS(DEV_ADDR, addr, regval); - usba_writel(udc, CTRL, regval); -} - -static int do_test_mode(struct usba_udc *udc) -{ - static const char test_packet_buffer[] = { - /* JKJKJKJK * 9 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* JJKKJJKK * 8 */ - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, - /* JJKKJJKK * 8 */ - 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, - /* JJJJJJJKKKKKKK * 8 */ - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /* JJJJJJJK * 8 */ - 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, - /* {JKKKKKKK * 10}, JK */ - 0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E - }; - struct usba_ep *ep; - int test_mode; - - test_mode = udc->test_mode; - - /* Start from a clean slate */ - reset_all_endpoints(udc); - - switch (test_mode) { - case 0x0100: - /* Test_J */ - usba_writel(udc, TST, USBA_TST_J_MODE); - DBG(DBG_ALL, "Entering Test_J mode...\n"); - break; - case 0x0200: - /* Test_K */ - usba_writel(udc, TST, USBA_TST_K_MODE); - DBG(DBG_ALL, "Entering Test_K mode...\n"); - break; - case 0x0300: - /* - * Test_SE0_NAK: Force high-speed mode and set up ep0 - * for Bulk IN transfers - */ - ep = &udc->usba_ep[0]; - usba_writel(udc, TST, - USBA_BF(SPEED_CFG, USBA_SPEED_CFG_FORCE_HIGH)); - usba_ep_writel(ep, CFG, - USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64) - | USBA_EPT_DIR_IN - | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK) - | USBA_BF(BK_NUMBER, 1)); - if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) { - set_protocol_stall(udc, ep); - DBG(DBG_ALL, "Test_SE0_NAK: ep0 not mapped\n"); - } else { - usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE); - DBG(DBG_ALL, "Entering Test_SE0_NAK mode...\n"); - } - break; - case 0x0400: - /* Test_Packet */ - ep = &udc->usba_ep[0]; - usba_ep_writel(ep, CFG, - USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64) - | USBA_EPT_DIR_IN - | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK) - | USBA_BF(BK_NUMBER, 1)); - if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) { - set_protocol_stall(udc, ep); - DBG(DBG_ALL, "Test_Packet: ep0 not mapped\n"); - } else { - usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE); - usba_writel(udc, TST, USBA_TST_PKT_MODE); - memcpy(ep->fifo, test_packet_buffer, - sizeof(test_packet_buffer)); - usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY); - DBG(DBG_ALL, "Entering Test_Packet mode...\n"); - } - break; - default: - DBG(DBG_ERR, "Invalid test mode: 0x%04x\n", test_mode); - return -EINVAL; - } - - return 0; -} - -/* Avoid overly long expressions */ -static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq) -{ - if (crq->wValue == cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP)) - return true; - return false; -} - -static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq) -{ - if (crq->wValue == cpu_to_le16(USB_DEVICE_TEST_MODE)) - return true; - return false; -} - -static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq) -{ - if (crq->wValue == cpu_to_le16(USB_ENDPOINT_HALT)) - return true; - return false; -} - -static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, - struct usb_ctrlrequest *crq) -{ - int retval = 0; - - switch (crq->bRequest) { - case USB_REQ_GET_STATUS: { - u16 status; - - if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_DEVICE)) { - status = cpu_to_le16(udc->devstatus); - } else if (crq->bRequestType - == (USB_DIR_IN | USB_RECIP_INTERFACE)) { - status = cpu_to_le16(0); - } else if (crq->bRequestType - == (USB_DIR_IN | USB_RECIP_ENDPOINT)) { - struct usba_ep *target; - - target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); - if (!target) - goto stall; - - status = 0; - if (is_stalled(udc, target)) - status |= cpu_to_le16(1); - } else { - goto delegate; - } - - /* Write directly to the FIFO. No queueing is done. */ - if (crq->wLength != cpu_to_le16(sizeof(status))) - goto stall; - ep->state = DATA_STAGE_IN; - __raw_writew(status, ep->fifo); - usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY); - break; - } - - case USB_REQ_CLEAR_FEATURE: { - if (crq->bRequestType == USB_RECIP_DEVICE) { - if (feature_is_dev_remote_wakeup(crq)) - udc->devstatus - &= ~(1 << USB_DEVICE_REMOTE_WAKEUP); - else - /* Can't CLEAR_FEATURE TEST_MODE */ - goto stall; - } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { - struct usba_ep *target; - - if (crq->wLength != cpu_to_le16(0) || - !feature_is_ep_halt(crq)) - goto stall; - target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); - if (!target) - goto stall; - - usba_ep_writel(target, CLR_STA, USBA_FORCE_STALL); - if (target->index != 0) - usba_ep_writel(target, CLR_STA, - USBA_TOGGLE_CLR); - } else { - goto delegate; - } - - send_status(udc, ep); - break; - } - - case USB_REQ_SET_FEATURE: { - if (crq->bRequestType == USB_RECIP_DEVICE) { - if (feature_is_dev_test_mode(crq)) { - send_status(udc, ep); - ep->state = STATUS_STAGE_TEST; - udc->test_mode = le16_to_cpu(crq->wIndex); - return 0; - } else if (feature_is_dev_remote_wakeup(crq)) { - udc->devstatus |= 1 << USB_DEVICE_REMOTE_WAKEUP; - } else { - goto stall; - } - } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { - struct usba_ep *target; - - if (crq->wLength != cpu_to_le16(0) || - !feature_is_ep_halt(crq)) - goto stall; - - target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); - if (!target) - goto stall; - - usba_ep_writel(target, SET_STA, USBA_FORCE_STALL); - } else { - goto delegate; - } - - send_status(udc, ep); - break; - } - - case USB_REQ_SET_ADDRESS: - if (crq->bRequestType != (USB_DIR_OUT | USB_RECIP_DEVICE)) - goto delegate; - - set_address(udc, le16_to_cpu(crq->wValue)); - send_status(udc, ep); - ep->state = STATUS_STAGE_ADDR; - break; - - default: -delegate: - spin_unlock(&udc->lock); - retval = udc->driver->setup(&udc->gadget, crq); - spin_lock(&udc->lock); - } - - return retval; - -stall: - DBG(DBG_ALL, "%s: Invalid setup request: %02x.%02x v%04x i%04x l%d\n", - ep->ep.name, crq->bRequestType, crq->bRequest, - le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex), - le16_to_cpu(crq->wLength)); - set_protocol_stall(udc, ep); - - return -1; -} - -static void usba_control_irq(struct usba_udc *udc, struct usba_ep *ep) -{ - struct usba_request *req; - u32 epstatus; - u32 epctrl; - -restart: - epstatus = usba_ep_readl(ep, STA); - epctrl = usba_ep_readl(ep, CTL); - - DBG(DBG_INT, "%s [%d]: s/%08x c/%08x\n", - ep->ep.name, ep->state, epstatus, epctrl); - - req = NULL; - if (!list_empty(&ep->queue)) - req = list_entry(ep->queue.next, - struct usba_request, queue); - - if ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) { - if (req->submitted) - next_fifo_transaction(ep, req); - else - submit_request(ep, req); - - if (req->last_transaction) { - usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY); - usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE); - } - goto restart; - } - if ((epstatus & epctrl) & USBA_TX_COMPLETE) { - usba_ep_writel(ep, CLR_STA, USBA_TX_COMPLETE); - - switch (ep->state) { - case DATA_STAGE_IN: - usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY); - usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); - ep->state = STATUS_STAGE_OUT; - break; - case STATUS_STAGE_ADDR: - /* Activate our new address */ - usba_writel(udc, CTRL, (usba_readl(udc, CTRL) - | USBA_FADDR_EN)); - usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); - ep->state = WAIT_FOR_SETUP; - break; - case STATUS_STAGE_IN: - if (req) { - list_del_init(&req->queue); - request_complete(ep, req, 0); - submit_next_request(ep); - } - usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); - ep->state = WAIT_FOR_SETUP; - break; - case STATUS_STAGE_TEST: - usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); - ep->state = WAIT_FOR_SETUP; - if (do_test_mode(udc)) - set_protocol_stall(udc, ep); - break; - default: - DBG(DBG_ALL, "%s: TXCOMP: Invalid endpoint state %d\n", - ep->ep.name, ep->state); - set_protocol_stall(udc, ep); - break; - } - - goto restart; - } - if ((epstatus & epctrl) & USBA_RX_BK_RDY) { - switch (ep->state) { - case STATUS_STAGE_OUT: - usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY); - usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY); - - if (req) { - list_del_init(&req->queue); - request_complete(ep, req, 0); - } - ep->state = WAIT_FOR_SETUP; - break; - - case DATA_STAGE_OUT: - receive_data(ep); - break; - - default: - usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY); - usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY); - DBG(DBG_ALL, "%s: RXRDY: Invalid endpoint state %d\n", - ep->ep.name, ep->state); - set_protocol_stall(udc, ep); - break; - } - - goto restart; - } - if (epstatus & USBA_RX_SETUP) { - union { - struct usb_ctrlrequest crq; - unsigned long data[2]; - } crq; - unsigned int pkt_len; - int ret; - - if (ep->state != WAIT_FOR_SETUP) { - /* - * Didn't expect a SETUP packet at this - * point. Clean up any pending requests (which - * may be successful). - */ - int status = -EPROTO; - - /* - * RXRDY and TXCOMP are dropped when SETUP - * packets arrive. Just pretend we received - * the status packet. - */ - if (ep->state == STATUS_STAGE_OUT || - ep->state == STATUS_STAGE_IN) { - usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY); - status = 0; - } - - if (req) { - list_del_init(&req->queue); - request_complete(ep, req, status); - } - } - - pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA)); - DBG(DBG_HW, "Packet length: %u\n", pkt_len); - if (pkt_len != sizeof(crq)) { - DBG(DBG_ALL, "udc: Invalid length %u (expected %zu)\n", - pkt_len, sizeof(crq)); - set_protocol_stall(udc, ep); - return; - } - - DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo); - memcpy(crq.data, ep->fifo, sizeof(crq)); - - /* Free up one bank in the FIFO so that we can - * generate or receive a reply right away. */ - usba_ep_writel(ep, CLR_STA, USBA_RX_SETUP); - - if (crq.crq.bRequestType & USB_DIR_IN) { - /* - * The USB 2.0 spec states that "if wLength is - * zero, there is no data transfer phase." - * However, testusb #14 seems to actually - * expect a data phase even if wLength = 0... - */ - ep->state = DATA_STAGE_IN; - } else { - if (crq.crq.wLength != cpu_to_le16(0)) - ep->state = DATA_STAGE_OUT; - else - ep->state = STATUS_STAGE_IN; - } - - ret = -1; - if (ep->index == 0) { - ret = handle_ep0_setup(udc, ep, &crq.crq); - } else { - spin_unlock(&udc->lock); - ret = udc->driver->setup(&udc->gadget, &crq.crq); - spin_lock(&udc->lock); - } - - DBG(DBG_BUS, "req %02x.%02x, length %d, state %d, ret %d\n", - crq.crq.bRequestType, crq.crq.bRequest, - le16_to_cpu(crq.crq.wLength), ep->state, ret); - - if (ret < 0) { - /* Let the host know that we failed */ - set_protocol_stall(udc, ep); - } - } -} - -static void usba_ep_irq(struct usba_udc *udc, struct usba_ep *ep) -{ - struct usba_request *req; - u32 epstatus; - u32 epctrl; - - epstatus = usba_ep_readl(ep, STA); - epctrl = usba_ep_readl(ep, CTL); - - DBG(DBG_INT, "%s: interrupt, status: 0x%08x\n", ep->ep.name, epstatus); - - while ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) { - DBG(DBG_BUS, "%s: TX PK ready\n", ep->ep.name); - - if (list_empty(&ep->queue)) { - DBG(DBG_INT, "ep_irq: queue empty\n"); - usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY); - return; - } - - req = list_entry(ep->queue.next, struct usba_request, queue); - - if (req->submitted) - next_fifo_transaction(ep, req); - else - submit_request(ep, req); - - if (req->last_transaction) { - list_del_init(&req->queue); - submit_next_request(ep); - request_complete(ep, req, 0); - } - - epstatus = usba_ep_readl(ep, STA); - epctrl = usba_ep_readl(ep, CTL); - } - - if ((epstatus & epctrl) & USBA_RX_BK_RDY) { - DBG(DBG_BUS, "%s: RX data ready\n", ep->ep.name); - receive_data(ep); - usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY); - } -} - -static int usba_udc_irq(struct usba_udc *udc) -{ - u32 status, ep_status; - - spin_lock(&udc->lock); - - status = usba_readl(udc, INT_STA); - DBG(DBG_INT, "irq, status=%#08x\n", status); - - if (status & USBA_DET_SUSPEND) { - usba_writel(udc, INT_CLR, USBA_DET_SUSPEND); - DBG(DBG_BUS, "Suspend detected\n"); - if (udc->gadget.speed != USB_SPEED_UNKNOWN && - udc->driver && udc->driver->suspend) { - spin_unlock(&udc->lock); - udc->driver->suspend(&udc->gadget); - spin_lock(&udc->lock); - } - } - - if (status & USBA_WAKE_UP) { - usba_writel(udc, INT_CLR, USBA_WAKE_UP); - DBG(DBG_BUS, "Wake Up CPU detected\n"); - } - - if (status & USBA_END_OF_RESUME) { - usba_writel(udc, INT_CLR, USBA_END_OF_RESUME); - DBG(DBG_BUS, "Resume detected\n"); - if (udc->gadget.speed != USB_SPEED_UNKNOWN && - udc->driver && udc->driver->resume) { - spin_unlock(&udc->lock); - udc->driver->resume(&udc->gadget); - spin_lock(&udc->lock); - } - } - - ep_status = USBA_BFEXT(EPT_INT, status); - if (ep_status) { - int i; - - for (i = 0; i < USBA_NR_ENDPOINTS; i++) - if (ep_status & (1 << i)) { - if (ep_is_control(&udc->usba_ep[i])) - usba_control_irq(udc, &udc->usba_ep[i]); - else - usba_ep_irq(udc, &udc->usba_ep[i]); - } - } - - if (status & USBA_END_OF_RESET) { - struct usba_ep *ep0; - - usba_writel(udc, INT_CLR, USBA_END_OF_RESET); - reset_all_endpoints(udc); - - if (udc->gadget.speed != USB_SPEED_UNKNOWN && - udc->driver->disconnect) { - udc->gadget.speed = USB_SPEED_UNKNOWN; - spin_unlock(&udc->lock); - udc->driver->disconnect(&udc->gadget); - spin_lock(&udc->lock); - } - - if (status & USBA_HIGH_SPEED) - udc->gadget.speed = USB_SPEED_HIGH; - else - udc->gadget.speed = USB_SPEED_FULL; - - ep0 = &udc->usba_ep[0]; - ep0->desc = &usba_ep0_desc; - ep0->state = WAIT_FOR_SETUP; - usba_ep_writel(ep0, CFG, - (USBA_BF(EPT_SIZE, EP0_EPT_SIZE) - | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL) - | USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE))); - usba_ep_writel(ep0, CTL_ENB, - USBA_EPT_ENABLE | USBA_RX_SETUP); - usba_writel(udc, INT_ENB, - (usba_readl(udc, INT_ENB) - | USBA_BF(EPT_INT, 1) - | USBA_DET_SUSPEND - | USBA_END_OF_RESUME)); - - /* - * Unclear why we hit this irregularly, e.g. in usbtest, - * but it's clearly harmless... - */ - if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED)) - DBG(DBG_ALL, "ODD: EP0 configuration is invalid!\n"); - } - - spin_unlock(&udc->lock); - - return 0; -} - -static int atmel_usba_start(struct usba_udc *udc) -{ - udc->devstatus = 1 << USB_DEVICE_SELF_POWERED; - - udc->vbus_prev = 0; - - /* If Vbus is present, enable the controller and wait for reset */ - if (vbus_is_present(udc) && udc->vbus_prev == 0) { - usba_writel(udc, CTRL, USBA_ENABLE_MASK); - usba_writel(udc, INT_ENB, USBA_END_OF_RESET); - } - - return 0; -} - -static int atmel_usba_stop(struct usba_udc *udc) -{ - udc->gadget.speed = USB_SPEED_UNKNOWN; - reset_all_endpoints(udc); - - /* This will also disable the DP pullup */ - usba_writel(udc, CTRL, USBA_DISABLE_MASK); - - return 0; -} - -static struct usba_udc controller = { - .regs = (unsigned *)ATMEL_BASE_UDPHS, - .fifo = (unsigned *)ATMEL_BASE_UDPHS_FIFO, - .gadget = { - .ops = &usba_udc_ops, - .ep_list = LIST_HEAD_INIT(controller.gadget.ep_list), - .speed = USB_SPEED_HIGH, - .is_dualspeed = 1, - .name = "atmel_usba_udc", - }, -}; - -int usb_gadget_handle_interrupts(void) -{ - struct usba_udc *udc = &controller; - - return usba_udc_irq(udc); -} - - -int usb_gadget_register_driver(struct usb_gadget_driver *driver) -{ - struct usba_udc *udc = &controller; - int ret; - - if (!driver || !driver->bind || !driver->setup) { - printf("bad paramter\n"); - return -EINVAL; - } - - if (udc->driver) { - printf("UDC already has a gadget driver\n"); - return -EBUSY; - } - - atmel_usba_start(udc); - - udc->driver = driver; - - ret = driver->bind(&udc->gadget); - if (ret) { - error("driver->bind() returned %d\n", ret); - udc->driver = NULL; - } - - return ret; -} - -int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -{ - struct usba_udc *udc = &controller; - - if (!driver || !driver->unbind || !driver->disconnect) { - error("bad paramter\n"); - return -EINVAL; - } - - driver->disconnect(&udc->gadget); - driver->unbind(&udc->gadget); - udc->driver = NULL; - - atmel_usba_stop(udc); - - return 0; -} - -static struct usba_ep *usba_udc_pdata(struct usba_platform_data *pdata, - struct usba_udc *udc) -{ - struct usba_ep *eps; - int i; - - eps = malloc(sizeof(struct usba_ep) * pdata->num_ep); - if (!eps) { - error("failed to alloc eps\n"); - return NULL; - } - - udc->gadget.ep0 = &eps[0].ep; - - INIT_LIST_HEAD(&udc->gadget.ep_list); - INIT_LIST_HEAD(&eps[0].ep.ep_list); - - for (i = 0; i < pdata->num_ep; i++) { - struct usba_ep *ep = &eps[i]; - - ep->ep_regs = udc->regs + USBA_EPT_BASE(i); - ep->dma_regs = udc->regs + USBA_DMA_BASE(i); - ep->fifo = udc->fifo + USBA_FIFO_BASE(i); - ep->ep.ops = &usba_ep_ops; - ep->ep.name = pdata->ep[i].name; - ep->ep.maxpacket = pdata->ep[i].fifo_size; - ep->fifo_size = ep->ep.maxpacket; - ep->udc = udc; - INIT_LIST_HEAD(&ep->queue); - ep->nr_banks = pdata->ep[i].nr_banks; - ep->index = pdata->ep[i].index; - ep->can_dma = pdata->ep[i].can_dma; - ep->can_isoc = pdata->ep[i].can_isoc; - if (i) - list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); - }; - - return eps; -} - -int usba_udc_probe(struct usba_platform_data *pdata) -{ - struct usba_udc *udc; - - udc = &controller; - - udc->usba_ep = usba_udc_pdata(pdata, udc); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/atmel_usba_udc.h b/qemu/roms/u-boot/drivers/usb/gadget/atmel_usba_udc.h deleted file mode 100644 index 92e462db6..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/atmel_usba_udc.h +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Register definition for Atmel USBA high speed USB device controller - * [Original from Linux kernel: drivers/usb/gadget/atmel_usba_udc.h] - * - * Copyright (C) 2005-2013 Atmel Corporation - * Bo Shen <voice.shen@atmel.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __LINUX_USB_GADGET_USBA_UDC_H__ -#define __LINUX_USB_GADGET_USBA_UDC_H__ - -/* USB register offsets */ -#define USBA_CTRL 0x0000 -#define USBA_FNUM 0x0004 -#define USBA_INT_ENB 0x0010 -#define USBA_INT_STA 0x0014 -#define USBA_INT_CLR 0x0018 -#define USBA_EPT_RST 0x001c -#define USBA_TST 0x00e0 - -/* USB endpoint register offsets */ -#define USBA_EPT_CFG 0x0000 -#define USBA_EPT_CTL_ENB 0x0004 -#define USBA_EPT_CTL_DIS 0x0008 -#define USBA_EPT_CTL 0x000c -#define USBA_EPT_SET_STA 0x0014 -#define USBA_EPT_CLR_STA 0x0018 -#define USBA_EPT_STA 0x001c - -/* USB DMA register offsets */ -#define USBA_DMA_NXT_DSC 0x0000 -#define USBA_DMA_ADDRESS 0x0004 -#define USBA_DMA_CONTROL 0x0008 -#define USBA_DMA_STATUS 0x000c - -/* Bitfields in CTRL */ -#define USBA_DEV_ADDR_OFFSET 0 -#define USBA_DEV_ADDR_SIZE 7 -#define USBA_FADDR_EN (1 << 7) -#define USBA_EN_USBA (1 << 8) -#define USBA_DETACH (1 << 9) -#define USBA_REMOTE_WAKE_UP (1 << 10) -#define USBA_PULLD_DIS (1 << 11) - -#if defined(CONFIG_AVR32) -#define USBA_ENABLE_MASK USBA_EN_USBA -#define USBA_DISABLE_MASK 0 -#elif defined(CONFIG_AT91FAMILY) -#define USBA_ENABLE_MASK (USBA_EN_USBA | USBA_PULLD_DIS) -#define USBA_DISABLE_MASK USBA_DETACH -#endif /* CONFIG_ARCH_AT91 */ - -/* Bitfields in FNUM */ -#define USBA_MICRO_FRAME_NUM_OFFSET 0 -#define USBA_MICRO_FRAME_NUM_SIZE 3 -#define USBA_FRAME_NUMBER_OFFSET 3 -#define USBA_FRAME_NUMBER_SIZE 11 -#define USBA_FRAME_NUM_ERROR (1 << 31) - -/* Bitfields in INT_ENB/INT_STA/INT_CLR */ -#define USBA_HIGH_SPEED (1 << 0) -#define USBA_DET_SUSPEND (1 << 1) -#define USBA_MICRO_SOF (1 << 2) -#define USBA_SOF (1 << 3) -#define USBA_END_OF_RESET (1 << 4) -#define USBA_WAKE_UP (1 << 5) -#define USBA_END_OF_RESUME (1 << 6) -#define USBA_UPSTREAM_RESUME (1 << 7) -#define USBA_EPT_INT_OFFSET 8 -#define USBA_EPT_INT_SIZE 16 -#define USBA_DMA_INT_OFFSET 24 -#define USBA_DMA_INT_SIZE 8 - -/* Bitfields in EPT_RST */ -#define USBA_RST_OFFSET 0 -#define USBA_RST_SIZE 16 - -/* Bitfields in USBA_TST */ -#define USBA_SPEED_CFG_OFFSET 0 -#define USBA_SPEED_CFG_SIZE 2 -#define USBA_TST_J_MODE (1 << 2) -#define USBA_TST_K_MODE (1 << 3) -#define USBA_TST_PKT_MODE (1 << 4) -#define USBA_OPMODE2 (1 << 5) - -/* Bitfields in EPT_CFG */ -#define USBA_EPT_SIZE_OFFSET 0 -#define USBA_EPT_SIZE_SIZE 3 -#define USBA_EPT_DIR_IN (1 << 3) -#define USBA_EPT_TYPE_OFFSET 4 -#define USBA_EPT_TYPE_SIZE 2 -#define USBA_BK_NUMBER_OFFSET 6 -#define USBA_BK_NUMBER_SIZE 2 -#define USBA_NB_TRANS_OFFSET 8 -#define USBA_NB_TRANS_SIZE 2 -#define USBA_EPT_MAPPED (1 << 31) - -/* Bitfields in EPT_CTL/EPT_CTL_ENB/EPT_CTL_DIS */ -#define USBA_EPT_ENABLE (1 << 0) -#define USBA_AUTO_VALID (1 << 1) -#define USBA_INTDIS_DMA (1 << 3) -#define USBA_NYET_DIS (1 << 4) -#define USBA_DATAX_RX (1 << 6) -#define USBA_MDATA_RX (1 << 7) -/* Bits 8-15 and 31 enable interrupts for respective bits in EPT_STA */ -#define USBA_BUSY_BANK_IE (1 << 18) - -/* Bitfields in EPT_SET_STA/EPT_CLR_STA/EPT_STA */ -#define USBA_FORCE_STALL (1 << 5) -#define USBA_TOGGLE_CLR (1 << 6) -#define USBA_TOGGLE_SEQ_OFFSET 6 -#define USBA_TOGGLE_SEQ_SIZE 2 -#define USBA_ERR_OVFLW (1 << 8) -#define USBA_RX_BK_RDY (1 << 9) -#define USBA_KILL_BANK (1 << 9) -#define USBA_TX_COMPLETE (1 << 10) -#define USBA_TX_PK_RDY (1 << 11) -#define USBA_ISO_ERR_TRANS (1 << 11) -#define USBA_RX_SETUP (1 << 12) -#define USBA_ISO_ERR_FLOW (1 << 12) -#define USBA_STALL_SENT (1 << 13) -#define USBA_ISO_ERR_CRC (1 << 13) -#define USBA_ISO_ERR_NBTRANS (1 << 13) -#define USBA_NAK_IN (1 << 14) -#define USBA_ISO_ERR_FLUSH (1 << 14) -#define USBA_NAK_OUT (1 << 15) -#define USBA_CURRENT_BANK_OFFSET 16 -#define USBA_CURRENT_BANK_SIZE 2 -#define USBA_BUSY_BANKS_OFFSET 18 -#define USBA_BUSY_BANKS_SIZE 2 -#define USBA_BYTE_COUNT_OFFSET 20 -#define USBA_BYTE_COUNT_SIZE 11 -#define USBA_SHORT_PACKET (1 << 31) - -/* Bitfields in DMA_CONTROL */ -#define USBA_DMA_CH_EN (1 << 0) -#define USBA_DMA_LINK (1 << 1) -#define USBA_DMA_END_TR_EN (1 << 2) -#define USBA_DMA_END_BUF_EN (1 << 3) -#define USBA_DMA_END_TR_IE (1 << 4) -#define USBA_DMA_END_BUF_IE (1 << 5) -#define USBA_DMA_DESC_LOAD_IE (1 << 6) -#define USBA_DMA_BURST_LOCK (1 << 7) -#define USBA_DMA_BUF_LEN_OFFSET 16 -#define USBA_DMA_BUF_LEN_SIZE 16 - -/* Bitfields in DMA_STATUS */ -#define USBA_DMA_CH_ACTIVE (1 << 1) -#define USBA_DMA_END_TR_ST (1 << 4) -#define USBA_DMA_END_BUF_ST (1 << 5) -#define USBA_DMA_DESC_LOAD_ST (1 << 6) - -/* Constants for SPEED_CFG */ -#define USBA_SPEED_CFG_NORMAL 0 -#define USBA_SPEED_CFG_FORCE_HIGH 2 -#define USBA_SPEED_CFG_FORCE_FULL 3 - -/* Constants for EPT_SIZE */ -#define USBA_EPT_SIZE_8 0 -#define USBA_EPT_SIZE_16 1 -#define USBA_EPT_SIZE_32 2 -#define USBA_EPT_SIZE_64 3 -#define USBA_EPT_SIZE_128 4 -#define USBA_EPT_SIZE_256 5 -#define USBA_EPT_SIZE_512 6 -#define USBA_EPT_SIZE_1024 7 - -/* Constants for EPT_TYPE */ -#define USBA_EPT_TYPE_CONTROL 0 -#define USBA_EPT_TYPE_ISO 1 -#define USBA_EPT_TYPE_BULK 2 -#define USBA_EPT_TYPE_INT 3 - -/* Constants for BK_NUMBER */ -#define USBA_BK_NUMBER_ZERO 0 -#define USBA_BK_NUMBER_ONE 1 -#define USBA_BK_NUMBER_DOUBLE 2 -#define USBA_BK_NUMBER_TRIPLE 3 - -/* Bit manipulation macros */ -#define USBA_BF(name, value) \ - (((value) & ((1 << USBA_##name##_SIZE) - 1)) \ - << USBA_##name##_OFFSET) -#define USBA_BFEXT(name, value) \ - (((value) >> USBA_##name##_OFFSET) \ - & ((1 << USBA_##name##_SIZE) - 1)) -#define USBA_BFINS(name, value, old) \ - (((old) & ~(((1 << USBA_##name##_SIZE) - 1) \ - << USBA_##name##_OFFSET)) \ - | USBA_BF(name, value)) - -/* Register access macros */ -#define usba_readl(udc, reg) \ - __raw_readl((udc)->regs + USBA_##reg) -#define usba_writel(udc, reg, value) \ - __raw_writel((value), (udc)->regs + USBA_##reg) -#define usba_ep_readl(ep, reg) \ - __raw_readl((ep)->ep_regs + USBA_EPT_##reg) -#define usba_ep_writel(ep, reg, value) \ - __raw_writel((value), (ep)->ep_regs + USBA_EPT_##reg) -#define usba_dma_readl(ep, reg) \ - __raw_readl((ep)->dma_regs + USBA_DMA_##reg) -#define usba_dma_writel(ep, reg, value) \ - __raw_writel((value), (ep)->dma_regs + USBA_DMA_##reg) - -/* Calculate base address for a given endpoint or DMA controller */ -#define USBA_EPT_BASE(x) (0x100 + (x) * 0x20) -#define USBA_DMA_BASE(x) (0x300 + (x) * 0x10) -#define USBA_FIFO_BASE(x) ((x) << 16) - -/* Synth parameters */ -#define USBA_NR_ENDPOINTS 7 - -#define EP0_FIFO_SIZE 64 -#define EP0_EPT_SIZE USBA_EPT_SIZE_64 -#define EP0_NR_BANKS 1 - -#define DBG_ERR 0x0001 /* report all error returns */ -#define DBG_HW 0x0002 /* debug hardware initialization */ -#define DBG_GADGET 0x0004 /* calls to/from gadget driver */ -#define DBG_INT 0x0008 /* interrupts */ -#define DBG_BUS 0x0010 /* report changes in bus state */ -#define DBG_QUEUE 0x0020 /* debug request queue processing */ -#define DBG_FIFO 0x0040 /* debug FIFO contents */ -#define DBG_DMA 0x0080 /* debug DMA handling */ -#define DBG_REQ 0x0100 /* print out queued request length */ -#define DBG_ALL 0xffff -#define DBG_NONE 0x0000 - -#define DEBUG_LEVEL (DBG_ERR) - -#define DBG(level, fmt, ...) \ - do { \ - if ((level) & DEBUG_LEVEL) \ - debug("udc: " fmt, ## __VA_ARGS__); \ - } while (0) - -enum usba_ctrl_state { - WAIT_FOR_SETUP, - DATA_STAGE_IN, - DATA_STAGE_OUT, - STATUS_STAGE_IN, - STATUS_STAGE_OUT, - STATUS_STAGE_ADDR, - STATUS_STAGE_TEST, -}; - -struct usba_dma_desc { - dma_addr_t next; - dma_addr_t addr; - u32 ctrl; -}; - -struct usba_ep { - int state; - void *ep_regs; - void *dma_regs; - void *fifo; - struct usb_ep ep; - struct usba_udc *udc; - - struct list_head queue; - - u16 fifo_size; - u8 nr_banks; - u8 index; - unsigned int can_dma:1; - unsigned int can_isoc:1; - unsigned int is_isoc:1; - unsigned int is_in:1; - - const struct usb_endpoint_descriptor *desc; -}; - -struct usba_request { - struct usb_request req; - struct list_head queue; - - u32 ctrl; - - unsigned int submitted:1; - unsigned int last_transaction:1; - unsigned int using_dma:1; - unsigned int mapped:1; -}; - -struct usba_udc { - void *regs; - void *fifo; - - struct usb_gadget gadget; - struct usb_gadget_driver *driver; - struct platform_device *pdev; - int irq; - int vbus_pin; - int vbus_pin_inverted; - int num_ep; - struct usba_ep *usba_ep; - - u16 devstatus; - - u16 test_mode; - int vbus_prev; -}; - -static inline struct usba_ep *to_usba_ep(struct usb_ep *ep) -{ - return container_of(ep, struct usba_ep, ep); -} - -static inline struct usba_request *to_usba_req(struct usb_request *req) -{ - return container_of(req, struct usba_request, req); -} - -static inline struct usba_udc *to_usba_udc(struct usb_gadget *gadget) -{ - return container_of(gadget, struct usba_udc, gadget); -} - -#define ep_is_control(ep) ((ep)->index == 0) -#define ep_is_idle(ep) ((ep)->state == EP_STATE_IDLE) - -#endif /* __LINUX_USB_GADGET_USBA_UDC_H */ diff --git a/qemu/roms/u-boot/drivers/usb/gadget/ci_udc.c b/qemu/roms/u-boot/drivers/usb/gadget/ci_udc.c deleted file mode 100644 index 02d3fdade..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/ci_udc.c +++ /dev/null @@ -1,760 +0,0 @@ -/* - * Copyright 2011, Marvell Semiconductor Inc. - * Lei Wen <leiwen@marvell.com> - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Back ported to the 8xx platform (from the 8260 platform) by - * Murray.Jensen@cmst.csiro.au, 27-Jan-01. - */ - -#include <common.h> -#include <command.h> -#include <config.h> -#include <net.h> -#include <malloc.h> -#include <asm/byteorder.h> -#include <asm/errno.h> -#include <asm/io.h> -#include <asm/unaligned.h> -#include <linux/types.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <usb/ci_udc.h> -#include "../host/ehci.h" -#include "ci_udc.h" - -/* - * Check if the system has too long cachelines. If the cachelines are - * longer then 128b, the driver will not be able flush/invalidate data - * cache over separate QH entries. We use 128b because one QH entry is - * 64b long and there are always two QH list entries for each endpoint. - */ -#if ARCH_DMA_MINALIGN > 128 -#error This driver can not work on systems with caches longer than 128b -#endif - -#ifndef DEBUG -#define DBG(x...) do {} while (0) -#else -#define DBG(x...) printf(x) -static const char *reqname(unsigned r) -{ - switch (r) { - case USB_REQ_GET_STATUS: return "GET_STATUS"; - case USB_REQ_CLEAR_FEATURE: return "CLEAR_FEATURE"; - case USB_REQ_SET_FEATURE: return "SET_FEATURE"; - case USB_REQ_SET_ADDRESS: return "SET_ADDRESS"; - case USB_REQ_GET_DESCRIPTOR: return "GET_DESCRIPTOR"; - case USB_REQ_SET_DESCRIPTOR: return "SET_DESCRIPTOR"; - case USB_REQ_GET_CONFIGURATION: return "GET_CONFIGURATION"; - case USB_REQ_SET_CONFIGURATION: return "SET_CONFIGURATION"; - case USB_REQ_GET_INTERFACE: return "GET_INTERFACE"; - case USB_REQ_SET_INTERFACE: return "SET_INTERFACE"; - default: return "*UNKNOWN*"; - } -} -#endif - -static struct usb_endpoint_descriptor ep0_out_desc = { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0, - .bmAttributes = USB_ENDPOINT_XFER_CONTROL, -}; - -static struct usb_endpoint_descriptor ep0_in_desc = { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_CONTROL, -}; - -static int ci_pullup(struct usb_gadget *gadget, int is_on); -static int ci_ep_enable(struct usb_ep *ep, - const struct usb_endpoint_descriptor *desc); -static int ci_ep_disable(struct usb_ep *ep); -static int ci_ep_queue(struct usb_ep *ep, - struct usb_request *req, gfp_t gfp_flags); -static struct usb_request * -ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags); -static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *_req); - -static struct usb_gadget_ops ci_udc_ops = { - .pullup = ci_pullup, -}; - -static struct usb_ep_ops ci_ep_ops = { - .enable = ci_ep_enable, - .disable = ci_ep_disable, - .queue = ci_ep_queue, - .alloc_request = ci_ep_alloc_request, - .free_request = ci_ep_free_request, -}; - -/* Init values for USB endpoints. */ -static const struct usb_ep ci_ep_init[2] = { - [0] = { /* EP 0 */ - .maxpacket = 64, - .name = "ep0", - .ops = &ci_ep_ops, - }, - [1] = { /* EP 1..n */ - .maxpacket = 512, - .name = "ep-", - .ops = &ci_ep_ops, - }, -}; - -static struct ci_drv controller = { - .gadget = { - .name = "ci_udc", - .ops = &ci_udc_ops, - .is_dualspeed = 1, - }, -}; - -/** - * ci_get_qh() - return queue head for endpoint - * @ep_num: Endpoint number - * @dir_in: Direction of the endpoint (IN = 1, OUT = 0) - * - * This function returns the QH associated with particular endpoint - * and it's direction. - */ -static struct ept_queue_head *ci_get_qh(int ep_num, int dir_in) -{ - return &controller.epts[(ep_num * 2) + dir_in]; -} - -/** - * ci_get_qtd() - return queue item for endpoint - * @ep_num: Endpoint number - * @dir_in: Direction of the endpoint (IN = 1, OUT = 0) - * - * This function returns the QH associated with particular endpoint - * and it's direction. - */ -static struct ept_queue_item *ci_get_qtd(int ep_num, int dir_in) -{ - return controller.items[(ep_num * 2) + dir_in]; -} - -/** - * ci_flush_qh - flush cache over queue head - * @ep_num: Endpoint number - * - * This function flushes cache over QH for particular endpoint. - */ -static void ci_flush_qh(int ep_num) -{ - struct ept_queue_head *head = ci_get_qh(ep_num, 0); - const uint32_t start = (uint32_t)head; - const uint32_t end = start + 2 * sizeof(*head); - - flush_dcache_range(start, end); -} - -/** - * ci_invalidate_qh - invalidate cache over queue head - * @ep_num: Endpoint number - * - * This function invalidates cache over QH for particular endpoint. - */ -static void ci_invalidate_qh(int ep_num) -{ - struct ept_queue_head *head = ci_get_qh(ep_num, 0); - uint32_t start = (uint32_t)head; - uint32_t end = start + 2 * sizeof(*head); - - invalidate_dcache_range(start, end); -} - -/** - * ci_flush_qtd - flush cache over queue item - * @ep_num: Endpoint number - * - * This function flushes cache over qTD pair for particular endpoint. - */ -static void ci_flush_qtd(int ep_num) -{ - struct ept_queue_item *item = ci_get_qtd(ep_num, 0); - const uint32_t start = (uint32_t)item; - const uint32_t end_raw = start + 2 * sizeof(*item); - const uint32_t end = roundup(end_raw, ARCH_DMA_MINALIGN); - - flush_dcache_range(start, end); -} - -/** - * ci_invalidate_qtd - invalidate cache over queue item - * @ep_num: Endpoint number - * - * This function invalidates cache over qTD pair for particular endpoint. - */ -static void ci_invalidate_qtd(int ep_num) -{ - struct ept_queue_item *item = ci_get_qtd(ep_num, 0); - const uint32_t start = (uint32_t)item; - const uint32_t end_raw = start + 2 * sizeof(*item); - const uint32_t end = roundup(end_raw, ARCH_DMA_MINALIGN); - - invalidate_dcache_range(start, end); -} - -static struct usb_request * -ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags) -{ - struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); - return &ci_ep->req; -} - -static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *_req) -{ - return; -} - -static void ep_enable(int num, int in, int maxpacket) -{ - struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; - unsigned n; - - n = readl(&udc->epctrl[num]); - if (in) - n |= (CTRL_TXE | CTRL_TXR | CTRL_TXT_BULK); - else - n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK); - - if (num != 0) { - struct ept_queue_head *head = ci_get_qh(num, in); - - head->config = CONFIG_MAX_PKT(maxpacket) | CONFIG_ZLT; - ci_flush_qh(num); - } - writel(n, &udc->epctrl[num]); -} - -static int ci_ep_enable(struct usb_ep *ep, - const struct usb_endpoint_descriptor *desc) -{ - struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); - int num, in; - num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - in = (desc->bEndpointAddress & USB_DIR_IN) != 0; - ci_ep->desc = desc; - - if (num) { - int max = get_unaligned_le16(&desc->wMaxPacketSize); - - if ((max > 64) && (controller.gadget.speed == USB_SPEED_FULL)) - max = 64; - if (ep->maxpacket != max) { - DBG("%s: from %d to %d\n", __func__, - ep->maxpacket, max); - ep->maxpacket = max; - } - } - ep_enable(num, in, ep->maxpacket); - DBG("%s: num=%d maxpacket=%d\n", __func__, num, ep->maxpacket); - return 0; -} - -static int ci_ep_disable(struct usb_ep *ep) -{ - struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); - - ci_ep->desc = NULL; - return 0; -} - -static int ci_bounce(struct ci_ep *ep, int in) -{ - uint32_t addr = (uint32_t)ep->req.buf; - uint32_t ba; - - /* Input buffer address is not aligned. */ - if (addr & (ARCH_DMA_MINALIGN - 1)) - goto align; - - /* Input buffer length is not aligned. */ - if (ep->req.length & (ARCH_DMA_MINALIGN - 1)) - goto align; - - /* The buffer is well aligned, only flush cache. */ - ep->b_len = ep->req.length; - ep->b_buf = ep->req.buf; - goto flush; - -align: - /* Use internal buffer for small payloads. */ - if (ep->req.length <= 64) { - ep->b_len = 64; - ep->b_buf = ep->b_fast; - } else { - ep->b_len = roundup(ep->req.length, ARCH_DMA_MINALIGN); - ep->b_buf = memalign(ARCH_DMA_MINALIGN, ep->b_len); - if (!ep->b_buf) - return -ENOMEM; - } - if (in) - memcpy(ep->b_buf, ep->req.buf, ep->req.length); - -flush: - ba = (uint32_t)ep->b_buf; - flush_dcache_range(ba, ba + ep->b_len); - - return 0; -} - -static void ci_debounce(struct ci_ep *ep, int in) -{ - uint32_t addr = (uint32_t)ep->req.buf; - uint32_t ba = (uint32_t)ep->b_buf; - - if (in) { - if (addr == ba) - return; /* not a bounce */ - goto free; - } - invalidate_dcache_range(ba, ba + ep->b_len); - - if (addr == ba) - return; /* not a bounce */ - - memcpy(ep->req.buf, ep->b_buf, ep->req.actual); -free: - /* Large payloads use allocated buffer, free it. */ - if (ep->b_buf != ep->b_fast) - free(ep->b_buf); -} - -static int ci_ep_queue(struct usb_ep *ep, - struct usb_request *req, gfp_t gfp_flags) -{ - struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); - struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; - struct ept_queue_item *item; - struct ept_queue_head *head; - int bit, num, len, in, ret; - num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; - item = ci_get_qtd(num, in); - head = ci_get_qh(num, in); - len = req->length; - - ret = ci_bounce(ci_ep, in); - if (ret) - return ret; - - item->next = TERMINATE; - item->info = INFO_BYTES(len) | INFO_IOC | INFO_ACTIVE; - item->page0 = (uint32_t)ci_ep->b_buf; - item->page1 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x1000; - item->page2 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x2000; - item->page3 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x3000; - item->page4 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x4000; - ci_flush_qtd(num); - - head->next = (unsigned) item; - head->info = 0; - - DBG("ept%d %s queue len %x, buffer %p\n", - num, in ? "in" : "out", len, ci_ep->b_buf); - ci_flush_qh(num); - - if (in) - bit = EPT_TX(num); - else - bit = EPT_RX(num); - - writel(bit, &udc->epprime); - - return 0; -} - -static void handle_ep_complete(struct ci_ep *ep) -{ - struct ept_queue_item *item; - int num, in, len; - num = ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - in = (ep->desc->bEndpointAddress & USB_DIR_IN) != 0; - if (num == 0) - ep->desc = &ep0_out_desc; - item = ci_get_qtd(num, in); - ci_invalidate_qtd(num); - - if (item->info & 0xff) - printf("EP%d/%s FAIL info=%x pg0=%x\n", - num, in ? "in" : "out", item->info, item->page0); - - len = (item->info >> 16) & 0x7fff; - ep->req.actual = ep->req.length - len; - ci_debounce(ep, in); - - DBG("ept%d %s complete %x\n", - num, in ? "in" : "out", len); - ep->req.complete(&ep->ep, &ep->req); - if (num == 0) { - ep->req.length = 0; - usb_ep_queue(&ep->ep, &ep->req, 0); - ep->desc = &ep0_in_desc; - } -} - -#define SETUP(type, request) (((type) << 8) | (request)) - -static void handle_setup(void) -{ - struct usb_request *req = &controller.ep[0].req; - struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; - struct ept_queue_head *head; - struct usb_ctrlrequest r; - int status = 0; - int num, in, _num, _in, i; - char *buf; - head = ci_get_qh(0, 0); /* EP0 OUT */ - - ci_invalidate_qh(0); - memcpy(&r, head->setup_data, sizeof(struct usb_ctrlrequest)); -#ifdef CONFIG_CI_UDC_HAS_HOSTPC - writel(EPT_RX(0), &udc->epsetupstat); -#else - writel(EPT_RX(0), &udc->epstat); -#endif - DBG("handle setup %s, %x, %x index %x value %x\n", reqname(r.bRequest), - r.bRequestType, r.bRequest, r.wIndex, r.wValue); - - switch (SETUP(r.bRequestType, r.bRequest)) { - case SETUP(USB_RECIP_ENDPOINT, USB_REQ_CLEAR_FEATURE): - _num = r.wIndex & 15; - _in = !!(r.wIndex & 0x80); - - if ((r.wValue == 0) && (r.wLength == 0)) { - req->length = 0; - for (i = 0; i < NUM_ENDPOINTS; i++) { - struct ci_ep *ep = &controller.ep[i]; - - if (!ep->desc) - continue; - num = ep->desc->bEndpointAddress - & USB_ENDPOINT_NUMBER_MASK; - in = (ep->desc->bEndpointAddress - & USB_DIR_IN) != 0; - if ((num == _num) && (in == _in)) { - ep_enable(num, in, ep->ep.maxpacket); - usb_ep_queue(controller.gadget.ep0, - req, 0); - break; - } - } - } - return; - - case SETUP(USB_RECIP_DEVICE, USB_REQ_SET_ADDRESS): - /* - * write address delayed (will take effect - * after the next IN txn) - */ - writel((r.wValue << 25) | (1 << 24), &udc->devaddr); - req->length = 0; - usb_ep_queue(controller.gadget.ep0, req, 0); - return; - - case SETUP(USB_DIR_IN | USB_RECIP_DEVICE, USB_REQ_GET_STATUS): - req->length = 2; - buf = (char *)req->buf; - buf[0] = 1 << USB_DEVICE_SELF_POWERED; - buf[1] = 0; - usb_ep_queue(controller.gadget.ep0, req, 0); - return; - } - /* pass request up to the gadget driver */ - if (controller.driver) - status = controller.driver->setup(&controller.gadget, &r); - else - status = -ENODEV; - - if (!status) - return; - DBG("STALL reqname %s type %x value %x, index %x\n", - reqname(r.bRequest), r.bRequestType, r.wValue, r.wIndex); - writel((1<<16) | (1 << 0), &udc->epctrl[0]); -} - -static void stop_activity(void) -{ - int i, num, in; - struct ept_queue_head *head; - struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; - writel(readl(&udc->epcomp), &udc->epcomp); -#ifdef CONFIG_CI_UDC_HAS_HOSTPC - writel(readl(&udc->epsetupstat), &udc->epsetupstat); -#endif - writel(readl(&udc->epstat), &udc->epstat); - writel(0xffffffff, &udc->epflush); - - /* error out any pending reqs */ - for (i = 0; i < NUM_ENDPOINTS; i++) { - if (i != 0) - writel(0, &udc->epctrl[i]); - if (controller.ep[i].desc) { - num = controller.ep[i].desc->bEndpointAddress - & USB_ENDPOINT_NUMBER_MASK; - in = (controller.ep[i].desc->bEndpointAddress - & USB_DIR_IN) != 0; - head = ci_get_qh(num, in); - head->info = INFO_ACTIVE; - ci_flush_qh(num); - } - } -} - -void udc_irq(void) -{ - struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; - unsigned n = readl(&udc->usbsts); - writel(n, &udc->usbsts); - int bit, i, num, in; - - n &= (STS_SLI | STS_URI | STS_PCI | STS_UI | STS_UEI); - if (n == 0) - return; - - if (n & STS_URI) { - DBG("-- reset --\n"); - stop_activity(); - } - if (n & STS_SLI) - DBG("-- suspend --\n"); - - if (n & STS_PCI) { - int max = 64; - int speed = USB_SPEED_FULL; - -#ifdef CONFIG_CI_UDC_HAS_HOSTPC - bit = (readl(&udc->hostpc1_devlc) >> 25) & 3; -#else - bit = (readl(&udc->portsc) >> 26) & 3; -#endif - DBG("-- portchange %x %s\n", bit, (bit == 2) ? "High" : "Full"); - if (bit == 2) { - speed = USB_SPEED_HIGH; - max = 512; - } - controller.gadget.speed = speed; - for (i = 1; i < NUM_ENDPOINTS; i++) { - if (controller.ep[i].ep.maxpacket > max) - controller.ep[i].ep.maxpacket = max; - } - } - - if (n & STS_UEI) - printf("<UEI %x>\n", readl(&udc->epcomp)); - - if ((n & STS_UI) || (n & STS_UEI)) { -#ifdef CONFIG_CI_UDC_HAS_HOSTPC - n = readl(&udc->epsetupstat); -#else - n = readl(&udc->epstat); -#endif - if (n & EPT_RX(0)) - handle_setup(); - - n = readl(&udc->epcomp); - if (n != 0) - writel(n, &udc->epcomp); - - for (i = 0; i < NUM_ENDPOINTS && n; i++) { - if (controller.ep[i].desc) { - num = controller.ep[i].desc->bEndpointAddress - & USB_ENDPOINT_NUMBER_MASK; - in = (controller.ep[i].desc->bEndpointAddress - & USB_DIR_IN) != 0; - bit = (in) ? EPT_TX(num) : EPT_RX(num); - if (n & bit) - handle_ep_complete(&controller.ep[i]); - } - } - } -} - -int usb_gadget_handle_interrupts(void) -{ - u32 value; - struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; - - value = readl(&udc->usbsts); - if (value) - udc_irq(); - - return value; -} - -static int ci_pullup(struct usb_gadget *gadget, int is_on) -{ - struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; - if (is_on) { - /* RESET */ - writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RST, &udc->usbcmd); - udelay(200); - - writel((unsigned)controller.epts, &udc->epinitaddr); - - /* select DEVICE mode */ - writel(USBMODE_DEVICE, &udc->usbmode); - - writel(0xffffffff, &udc->epflush); - - /* Turn on the USB connection by enabling the pullup resistor */ - writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RUN, &udc->usbcmd); - } else { - stop_activity(); - writel(USBCMD_FS2, &udc->usbcmd); - udelay(800); - if (controller.driver) - controller.driver->disconnect(gadget); - } - - return 0; -} - -void udc_disconnect(void) -{ - struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; - /* disable pullup */ - stop_activity(); - writel(USBCMD_FS2, &udc->usbcmd); - udelay(800); - if (controller.driver) - controller.driver->disconnect(&controller.gadget); -} - -static int ci_udc_probe(void) -{ - struct ept_queue_head *head; - uint8_t *imem; - int i; - - const int num = 2 * NUM_ENDPOINTS; - - const int eplist_min_align = 4096; - const int eplist_align = roundup(eplist_min_align, ARCH_DMA_MINALIGN); - const int eplist_raw_sz = num * sizeof(struct ept_queue_head); - const int eplist_sz = roundup(eplist_raw_sz, ARCH_DMA_MINALIGN); - - const int ilist_align = roundup(ARCH_DMA_MINALIGN, 32); - const int ilist_ent_raw_sz = 2 * sizeof(struct ept_queue_item); - const int ilist_ent_sz = roundup(ilist_ent_raw_sz, ARCH_DMA_MINALIGN); - const int ilist_sz = NUM_ENDPOINTS * ilist_ent_sz; - - /* The QH list must be aligned to 4096 bytes. */ - controller.epts = memalign(eplist_align, eplist_sz); - if (!controller.epts) - return -ENOMEM; - memset(controller.epts, 0, eplist_sz); - - /* - * Each qTD item must be 32-byte aligned, each qTD touple must be - * cacheline aligned. There are two qTD items for each endpoint and - * only one of them is used for the endpoint at time, so we can group - * them together. - */ - controller.items_mem = memalign(ilist_align, ilist_sz); - if (!controller.items_mem) { - free(controller.epts); - return -ENOMEM; - } - memset(controller.items_mem, 0, ilist_sz); - - for (i = 0; i < 2 * NUM_ENDPOINTS; i++) { - /* - * Configure QH for each endpoint. The structure of the QH list - * is such that each two subsequent fields, N and N+1 where N is - * even, in the QH list represent QH for one endpoint. The Nth - * entry represents OUT configuration and the N+1th entry does - * represent IN configuration of the endpoint. - */ - head = controller.epts + i; - if (i < 2) - head->config = CONFIG_MAX_PKT(EP0_MAX_PACKET_SIZE) - | CONFIG_ZLT | CONFIG_IOS; - else - head->config = CONFIG_MAX_PKT(EP_MAX_PACKET_SIZE) - | CONFIG_ZLT; - head->next = TERMINATE; - head->info = 0; - - imem = controller.items_mem + ((i >> 1) * ilist_ent_sz); - if (i & 1) - imem += sizeof(struct ept_queue_item); - - controller.items[i] = (struct ept_queue_item *)imem; - - if (i & 1) { - ci_flush_qh(i - 1); - ci_flush_qtd(i - 1); - } - } - - INIT_LIST_HEAD(&controller.gadget.ep_list); - - /* Init EP 0 */ - memcpy(&controller.ep[0].ep, &ci_ep_init[0], sizeof(*ci_ep_init)); - controller.ep[0].desc = &ep0_in_desc; - controller.gadget.ep0 = &controller.ep[0].ep; - INIT_LIST_HEAD(&controller.gadget.ep0->ep_list); - - /* Init EP 1..n */ - for (i = 1; i < NUM_ENDPOINTS; i++) { - memcpy(&controller.ep[i].ep, &ci_ep_init[1], - sizeof(*ci_ep_init)); - list_add_tail(&controller.ep[i].ep.ep_list, - &controller.gadget.ep_list); - } - - return 0; -} - -int usb_gadget_register_driver(struct usb_gadget_driver *driver) -{ - int ret; - - if (!driver) - return -EINVAL; - if (!driver->bind || !driver->setup || !driver->disconnect) - return -EINVAL; - if (driver->speed != USB_SPEED_FULL && driver->speed != USB_SPEED_HIGH) - return -EINVAL; - - ret = usb_lowlevel_init(0, USB_INIT_DEVICE, (void **)&controller.ctrl); - if (ret) - return ret; - - ret = ci_udc_probe(); -#if defined(CONFIG_USB_EHCI_MX6) || defined(CONFIG_USB_EHCI_MXS) - /* - * FIXME: usb_lowlevel_init()->ehci_hcd_init() should be doing all - * HW-specific initialization, e.g. ULPI-vs-UTMI PHY selection - */ - if (!ret) { - struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; - - /* select ULPI phy */ - writel(PTS(PTS_ENABLE) | PFSC, &udc->portsc); - } -#endif - - ret = driver->bind(&controller.gadget); - if (ret) { - DBG("driver->bind() returned %d\n", ret); - return ret; - } - controller.driver = driver; - - return 0; -} - -int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/ci_udc.h b/qemu/roms/u-boot/drivers/usb/gadget/ci_udc.h deleted file mode 100644 index 4425fd934..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/ci_udc.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2011, Marvell Semiconductor Inc. - * - * Licensed under the GPL-2 or later. - */ -#ifndef __GADGET__CI_UDC_H__ -#define __GADGET__CI_UDC_H__ - -#define NUM_ENDPOINTS 6 - -#ifdef CONFIG_CI_UDC_HAS_HOSTPC -struct ci_udc { - u32 usbcmd; /* 0x130 */ - u32 usbsts; /* 0x134 */ - u32 pad1[3]; - u32 devaddr; /* 0x144 */ - u32 epinitaddr; /* 0x148 */ - u32 pad2[10]; - u32 portsc; /* 0x174 */ - u32 pad178[(0x1b4 - (0x174 + 4)) / 4]; - u32 hostpc1_devlc; /* 0x1b4 */ - u32 pad1b8[(0x1f8 - (0x1b4 + 4)) / 4]; - u32 usbmode; /* 0x1f8 */ - u32 pad1fc[(0x208 - (0x1f8 + 4)) / 4]; - u32 epsetupstat; /* 0x208 */ - u32 epprime; /* 0x20c */ - u32 epflush; /* 0x210 */ - u32 epstat; /* 0x214 */ - u32 epcomp; /* 0x218 */ - u32 epctrl[16]; /* 0x21c */ -}; -#else -struct ci_udc { - u32 usbcmd; /* 0x140 */ - u32 usbsts; /* 0x144 */ - u32 pad1[3]; - u32 devaddr; /* 0x154 */ - u32 epinitaddr; /* 0x158 */ - u32 pad2[10]; - u32 portsc; /* 0x184 */ - u32 pad3[8]; - u32 usbmode; /* 0x1a8 */ - u32 epstat; /* 0x1ac */ - u32 epprime; /* 0x1b0 */ - u32 epflush; /* 0x1b4 */ - u32 pad4; - u32 epcomp; /* 0x1bc */ - u32 epctrl[16]; /* 0x1c0 */ -}; - -#define PTS_ENABLE 2 -#define PTS(x) (((x) & 0x3) << 30) -#define PFSC (1 << 24) -#endif - -#define MICRO_8FRAME 0x8 -#define USBCMD_ITC(x) ((((x) > 0xff) ? 0xff : x) << 16) -#define USBCMD_FS2 (1 << 15) -#define USBCMD_RST (1 << 1) -#define USBCMD_RUN (1) - -#define STS_SLI (1 << 8) -#define STS_URI (1 << 6) -#define STS_PCI (1 << 2) -#define STS_UEI (1 << 1) -#define STS_UI (1 << 0) - -#define USBMODE_DEVICE 2 - -#define EPT_TX(x) (1 << (((x) & 0xffff) + 16)) -#define EPT_RX(x) (1 << ((x) & 0xffff)) - -#define CTRL_TXE (1 << 23) -#define CTRL_TXR (1 << 22) -#define CTRL_RXE (1 << 7) -#define CTRL_RXR (1 << 6) -#define CTRL_TXT_BULK (2 << 18) -#define CTRL_RXT_BULK (2 << 2) - -struct ci_ep { - struct usb_ep ep; - struct list_head queue; - const struct usb_endpoint_descriptor *desc; - - struct usb_request req; - uint8_t *b_buf; - uint32_t b_len; - uint8_t b_fast[64] __aligned(ARCH_DMA_MINALIGN); -}; - -struct ci_drv { - struct usb_gadget gadget; - struct usb_gadget_driver *driver; - struct ehci_ctrl *ctrl; - struct ept_queue_head *epts; - struct ept_queue_item *items[2 * NUM_ENDPOINTS]; - uint8_t *items_mem; - struct ci_ep ep[NUM_ENDPOINTS]; -}; - -struct ept_queue_head { - unsigned config; - unsigned current; /* read-only */ - - unsigned next; - unsigned info; - unsigned page0; - unsigned page1; - unsigned page2; - unsigned page3; - unsigned page4; - unsigned reserved_0; - - unsigned char setup_data[8]; - - unsigned reserved_1; - unsigned reserved_2; - unsigned reserved_3; - unsigned reserved_4; -}; - -#define CONFIG_MAX_PKT(n) ((n) << 16) -#define CONFIG_ZLT (1 << 29) /* stop on zero-len xfer */ -#define CONFIG_IOS (1 << 15) /* IRQ on setup */ - -struct ept_queue_item { - unsigned next; - unsigned info; - unsigned page0; - unsigned page1; - unsigned page2; - unsigned page3; - unsigned page4; - unsigned reserved; -}; - -#define TERMINATE 1 -#define INFO_BYTES(n) ((n) << 16) -#define INFO_IOC (1 << 15) -#define INFO_ACTIVE (1 << 7) -#define INFO_HALTED (1 << 6) -#define INFO_BUFFER_ERROR (1 << 5) -#define INFO_TX_ERROR (1 << 3) -#endif diff --git a/qemu/roms/u-boot/drivers/usb/gadget/composite.c b/qemu/roms/u-boot/drivers/usb/gadget/composite.c deleted file mode 100644 index 7bd25629c..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/composite.c +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * composite.c - infrastructure for Composite USB Gadgets - * - * Copyright (C) 2006-2008 David Brownell - * U-boot porting: Lukasz Majewski <l.majewski@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#undef DEBUG - -#include <linux/bitops.h> -#include <linux/usb/composite.h> - -#define USB_BUFSIZ 4096 - -static struct usb_composite_driver *composite; - -/** - * usb_add_function() - add a function to a configuration - * @config: the configuration - * @function: the function being added - * Context: single threaded during gadget setup - * - * After initialization, each configuration must have one or more - * functions added to it. Adding a function involves calling its @bind() - * method to allocate resources such as interface and string identifiers - * and endpoints. - * - * This function returns the value of the function's bind(), which is - * zero for success else a negative errno value. - */ -int usb_add_function(struct usb_configuration *config, - struct usb_function *function) -{ - int value = -EINVAL; - - debug("adding '%s'/%p to config '%s'/%p\n", - function->name, function, - config->label, config); - - if (!function->set_alt || !function->disable) - goto done; - - function->config = config; - list_add_tail(&function->list, &config->functions); - - if (function->bind) { - value = function->bind(config, function); - if (value < 0) { - list_del(&function->list); - function->config = NULL; - } - } else - value = 0; - - if (!config->fullspeed && function->descriptors) - config->fullspeed = 1; - if (!config->highspeed && function->hs_descriptors) - config->highspeed = 1; - -done: - if (value) - debug("adding '%s'/%p --> %d\n", - function->name, function, value); - return value; -} - -/** - * usb_function_deactivate - prevent function and gadget enumeration - * @function: the function that isn't yet ready to respond - * - * Blocks response of the gadget driver to host enumeration by - * preventing the data line pullup from being activated. This is - * normally called during @bind() processing to change from the - * initial "ready to respond" state, or when a required resource - * becomes available. - * - * For example, drivers that serve as a passthrough to a userspace - * daemon can block enumeration unless that daemon (such as an OBEX, - * MTP, or print server) is ready to handle host requests. - * - * Not all systems support software control of their USB peripheral - * data pullups. - * - * Returns zero on success, else negative errno. - */ -int usb_function_deactivate(struct usb_function *function) -{ - struct usb_composite_dev *cdev = function->config->cdev; - int status = 0; - - if (cdev->deactivations == 0) - status = usb_gadget_disconnect(cdev->gadget); - if (status == 0) - cdev->deactivations++; - - return status; -} - -/** - * usb_function_activate - allow function and gadget enumeration - * @function: function on which usb_function_activate() was called - * - * Reverses effect of usb_function_deactivate(). If no more functions - * are delaying their activation, the gadget driver will respond to - * host enumeration procedures. - * - * Returns zero on success, else negative errno. - */ -int usb_function_activate(struct usb_function *function) -{ - struct usb_composite_dev *cdev = function->config->cdev; - int status = 0; - - if (cdev->deactivations == 0) - status = -EINVAL; - else { - cdev->deactivations--; - if (cdev->deactivations == 0) - status = usb_gadget_connect(cdev->gadget); - } - - return status; -} - -/** - * usb_interface_id() - allocate an unused interface ID - * @config: configuration associated with the interface - * @function: function handling the interface - * Context: single threaded during gadget setup - * - * usb_interface_id() is called from usb_function.bind() callbacks to - * allocate new interface IDs. The function driver will then store that - * ID in interface, association, CDC union, and other descriptors. It - * will also handle any control requests targetted at that interface, - * particularly changing its altsetting via set_alt(). There may - * also be class-specific or vendor-specific requests to handle. - * - * All interface identifier should be allocated using this routine, to - * ensure that for example different functions don't wrongly assign - * different meanings to the same identifier. Note that since interface - * identifers are configuration-specific, functions used in more than - * one configuration (or more than once in a given configuration) need - * multiple versions of the relevant descriptors. - * - * Returns the interface ID which was allocated; or -ENODEV if no - * more interface IDs can be allocated. - */ -int usb_interface_id(struct usb_configuration *config, - struct usb_function *function) -{ - unsigned char id = config->next_interface_id; - - if (id < MAX_CONFIG_INTERFACES) { - config->interface[id] = function; - config->next_interface_id = id + 1; - return id; - } - return -ENODEV; -} - -static int config_buf(struct usb_configuration *config, - enum usb_device_speed speed, void *buf, u8 type) -{ - int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE; - void *next = buf + USB_DT_CONFIG_SIZE; - struct usb_descriptor_header **descriptors; - struct usb_config_descriptor *c = buf; - int status; - struct usb_function *f; - - /* write the config descriptor */ - c = buf; - c->bLength = USB_DT_CONFIG_SIZE; - c->bDescriptorType = type; - - c->bNumInterfaces = config->next_interface_id; - c->bConfigurationValue = config->bConfigurationValue; - c->iConfiguration = config->iConfiguration; - c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes; - c->bMaxPower = config->bMaxPower ? : (CONFIG_USB_GADGET_VBUS_DRAW / 2); - - /* There may be e.g. OTG descriptors */ - if (config->descriptors) { - status = usb_descriptor_fillbuf(next, len, - config->descriptors); - if (status < 0) - return status; - len -= status; - next += status; - } - - /* add each function's descriptors */ - list_for_each_entry(f, &config->functions, list) { - if (speed == USB_SPEED_HIGH) - descriptors = f->hs_descriptors; - else - descriptors = f->descriptors; - if (!descriptors) - continue; - status = usb_descriptor_fillbuf(next, len, - (const struct usb_descriptor_header **) descriptors); - if (status < 0) - return status; - len -= status; - next += status; - } - - len = next - buf; - c->wTotalLength = cpu_to_le16(len); - return len; -} - -static int config_desc(struct usb_composite_dev *cdev, unsigned w_value) -{ - enum usb_device_speed speed = USB_SPEED_UNKNOWN; - struct usb_gadget *gadget = cdev->gadget; - u8 type = w_value >> 8; - int hs = 0; - struct usb_configuration *c; - - if (gadget_is_dualspeed(gadget)) { - if (gadget->speed == USB_SPEED_HIGH) - hs = 1; - if (type == USB_DT_OTHER_SPEED_CONFIG) - hs = !hs; - if (hs) - speed = USB_SPEED_HIGH; - } - - w_value &= 0xff; - list_for_each_entry(c, &cdev->configs, list) { - if (speed == USB_SPEED_HIGH) { - if (!c->highspeed) - continue; - } else { - if (!c->fullspeed) - continue; - } - if (w_value == 0) - return config_buf(c, speed, cdev->req->buf, type); - w_value--; - } - return -EINVAL; -} - -static int count_configs(struct usb_composite_dev *cdev, unsigned type) -{ - struct usb_gadget *gadget = cdev->gadget; - unsigned count = 0; - int hs = 0; - struct usb_configuration *c; - - if (gadget_is_dualspeed(gadget)) { - if (gadget->speed == USB_SPEED_HIGH) - hs = 1; - if (type == USB_DT_DEVICE_QUALIFIER) - hs = !hs; - } - list_for_each_entry(c, &cdev->configs, list) { - /* ignore configs that won't work at this speed */ - if (hs) { - if (!c->highspeed) - continue; - } else { - if (!c->fullspeed) - continue; - } - count++; - } - return count; -} - -static void device_qual(struct usb_composite_dev *cdev) -{ - struct usb_qualifier_descriptor *qual = cdev->req->buf; - - qual->bLength = sizeof(*qual); - qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER; - /* POLICY: same bcdUSB and device type info at both speeds */ - qual->bcdUSB = cdev->desc.bcdUSB; - qual->bDeviceClass = cdev->desc.bDeviceClass; - qual->bDeviceSubClass = cdev->desc.bDeviceSubClass; - qual->bDeviceProtocol = cdev->desc.bDeviceProtocol; - /* ASSUME same EP0 fifo size at both speeds */ - qual->bMaxPacketSize0 = cdev->desc.bMaxPacketSize0; - qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER); - qual->bRESERVED = 0; -} - -static void reset_config(struct usb_composite_dev *cdev) -{ - struct usb_function *f; - - debug("%s:\n", __func__); - - list_for_each_entry(f, &cdev->config->functions, list) { - if (f->disable) - f->disable(f); - - bitmap_zero(f->endpoints, 32); - } - cdev->config = NULL; -} - -static int set_config(struct usb_composite_dev *cdev, - const struct usb_ctrlrequest *ctrl, unsigned number) -{ - struct usb_gadget *gadget = cdev->gadget; - unsigned power = gadget_is_otg(gadget) ? 8 : 100; - struct usb_descriptor_header **descriptors; - int result = -EINVAL; - struct usb_endpoint_descriptor *ep; - struct usb_configuration *c = NULL; - int addr; - int tmp; - struct usb_function *f; - - if (cdev->config) - reset_config(cdev); - - if (number) { - list_for_each_entry(c, &cdev->configs, list) { - if (c->bConfigurationValue == number) { - result = 0; - break; - } - } - if (result < 0) - goto done; - } else - result = 0; - - debug("%s: %s speed config #%d: %s\n", __func__, - ({ char *speed; - switch (gadget->speed) { - case USB_SPEED_LOW: - speed = "low"; - break; - case USB_SPEED_FULL: - speed = "full"; - break; - case USB_SPEED_HIGH: - speed = "high"; - break; - default: - speed = "?"; - break; - }; - speed; - }), number, c ? c->label : "unconfigured"); - - if (!c) - goto done; - - cdev->config = c; - - /* Initialize all interfaces by setting them to altsetting zero. */ - for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) { - f = c->interface[tmp]; - if (!f) - break; - - /* - * Record which endpoints are used by the function. This is used - * to dispatch control requests targeted at that endpoint to the - * function's setup callback instead of the current - * configuration's setup callback. - */ - if (gadget->speed == USB_SPEED_HIGH) - descriptors = f->hs_descriptors; - else - descriptors = f->descriptors; - - for (; *descriptors; ++descriptors) { - if ((*descriptors)->bDescriptorType != USB_DT_ENDPOINT) - continue; - - ep = (struct usb_endpoint_descriptor *)*descriptors; - addr = ((ep->bEndpointAddress & 0x80) >> 3) - | (ep->bEndpointAddress & 0x0f); - __set_bit(addr, f->endpoints); - } - - result = f->set_alt(f, tmp, 0); - if (result < 0) { - debug("interface %d (%s/%p) alt 0 --> %d\n", - tmp, f->name, f, result); - - reset_config(cdev); - goto done; - } - } - - /* when we return, be sure our power usage is valid */ - power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW; -done: - usb_gadget_vbus_draw(gadget, power); - return result; -} - -/** - * usb_add_config() - add a configuration to a device. - * @cdev: wraps the USB gadget - * @config: the configuration, with bConfigurationValue assigned - * Context: single threaded during gadget setup - * - * One of the main tasks of a composite driver's bind() routine is to - * add each of the configurations it supports, using this routine. - * - * This function returns the value of the configuration's bind(), which - * is zero for success else a negative errno value. Binding configurations - * assigns global resources including string IDs, and per-configuration - * resources such as interface IDs and endpoints. - */ -int usb_add_config(struct usb_composite_dev *cdev, - struct usb_configuration *config) -{ - int status = -EINVAL; - struct usb_configuration *c; - struct usb_function *f; - unsigned int i; - - debug("%s: adding config #%u '%s'/%p\n", __func__, - config->bConfigurationValue, - config->label, config); - - if (!config->bConfigurationValue || !config->bind) - goto done; - - /* Prevent duplicate configuration identifiers */ - list_for_each_entry(c, &cdev->configs, list) { - if (c->bConfigurationValue == config->bConfigurationValue) { - status = -EBUSY; - goto done; - } - } - - config->cdev = cdev; - list_add_tail(&config->list, &cdev->configs); - - INIT_LIST_HEAD(&config->functions); - config->next_interface_id = 0; - - status = config->bind(config); - if (status < 0) { - list_del(&config->list); - config->cdev = NULL; - } else { - debug("cfg %d/%p speeds:%s%s\n", - config->bConfigurationValue, config, - config->highspeed ? " high" : "", - config->fullspeed - ? (gadget_is_dualspeed(cdev->gadget) - ? " full" - : " full/low") - : ""); - - for (i = 0; i < MAX_CONFIG_INTERFACES; i++) { - f = config->interface[i]; - if (!f) - continue; - debug("%s: interface %d = %s/%p\n", - __func__, i, f->name, f); - } - } - - usb_ep_autoconfig_reset(cdev->gadget); - -done: - if (status) - debug("added config '%s'/%u --> %d\n", config->label, - config->bConfigurationValue, status); - return status; -} - -/* - * We support strings in multiple languages ... string descriptor zero - * says which languages are supported. The typical case will be that - * only one language (probably English) is used, with I18N handled on - * the host side. - */ - -static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf) -{ - const struct usb_gadget_strings *s; - u16 language; - __le16 *tmp; - - while (*sp) { - s = *sp; - language = cpu_to_le16(s->language); - for (tmp = buf; *tmp && tmp < &buf[126]; tmp++) { - if (*tmp == language) - goto repeat; - } - *tmp++ = language; -repeat: - sp++; - } -} - -static int lookup_string( - struct usb_gadget_strings **sp, - void *buf, - u16 language, - int id -) -{ - int value; - struct usb_gadget_strings *s; - - while (*sp) { - s = *sp++; - if (s->language != language) - continue; - value = usb_gadget_get_string(s, id, buf); - if (value > 0) - return value; - } - return -EINVAL; -} - -static int get_string(struct usb_composite_dev *cdev, - void *buf, u16 language, int id) -{ - struct usb_string_descriptor *s = buf; - struct usb_gadget_strings **sp; - int len; - struct usb_configuration *c; - struct usb_function *f; - - /* - * Yes, not only is USB's I18N support probably more than most - * folk will ever care about ... also, it's all supported here. - * (Except for UTF8 support for Unicode's "Astral Planes".) - */ - - /* 0 == report all available language codes */ - if (id == 0) { - memset(s, 0, 256); - s->bDescriptorType = USB_DT_STRING; - - sp = composite->strings; - if (sp) - collect_langs(sp, s->wData); - - list_for_each_entry(c, &cdev->configs, list) { - sp = c->strings; - if (sp) - collect_langs(sp, s->wData); - - list_for_each_entry(f, &c->functions, list) { - sp = f->strings; - if (sp) - collect_langs(sp, s->wData); - } - } - - for (len = 0; len <= 126 && s->wData[len]; len++) - continue; - if (!len) - return -EINVAL; - - s->bLength = 2 * (len + 1); - return s->bLength; - } - - /* - * Otherwise, look up and return a specified string. String IDs - * are device-scoped, so we look up each string table we're told - * about. These lookups are infrequent; simpler-is-better here. - */ - if (composite->strings) { - len = lookup_string(composite->strings, buf, language, id); - if (len > 0) - return len; - } - list_for_each_entry(c, &cdev->configs, list) { - if (c->strings) { - len = lookup_string(c->strings, buf, language, id); - if (len > 0) - return len; - } - list_for_each_entry(f, &c->functions, list) { - if (!f->strings) - continue; - len = lookup_string(f->strings, buf, language, id); - if (len > 0) - return len; - } - } - return -EINVAL; -} - -/** - * usb_string_id() - allocate an unused string ID - * @cdev: the device whose string descriptor IDs are being allocated - * Context: single threaded during gadget setup - * - * @usb_string_id() is called from bind() callbacks to allocate - * string IDs. Drivers for functions, configurations, or gadgets will - * then store that ID in the appropriate descriptors and string table. - * - * All string identifier should be allocated using this, - * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure - * that for example different functions don't wrongly assign different - * meanings to the same identifier. - */ -int usb_string_id(struct usb_composite_dev *cdev) -{ - if (cdev->next_string_id < 254) { - /* - * string id 0 is reserved by USB spec for list of - * supported languages - * 255 reserved as well? -- mina86 - */ - cdev->next_string_id++; - return cdev->next_string_id; - } - return -ENODEV; -} - -/** - * usb_string_ids() - allocate unused string IDs in batch - * @cdev: the device whose string descriptor IDs are being allocated - * @str: an array of usb_string objects to assign numbers to - * Context: single threaded during gadget setup - * - * @usb_string_ids() is called from bind() callbacks to allocate - * string IDs. Drivers for functions, configurations, or gadgets will - * then copy IDs from the string table to the appropriate descriptors - * and string table for other languages. - * - * All string identifier should be allocated using this, - * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for - * example different functions don't wrongly assign different meanings - * to the same identifier. - */ -int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str) -{ - u8 next = cdev->next_string_id; - - for (; str->s; ++str) { - if (next >= 254) - return -ENODEV; - str->id = ++next; - } - - cdev->next_string_id = next; - - return 0; -} - -/** - * usb_string_ids_n() - allocate unused string IDs in batch - * @c: the device whose string descriptor IDs are being allocated - * @n: number of string IDs to allocate - * Context: single threaded during gadget setup - * - * Returns the first requested ID. This ID and next @n-1 IDs are now - * valid IDs. At least provided that @n is non-zero because if it - * is, returns last requested ID which is now very useful information. - * - * @usb_string_ids_n() is called from bind() callbacks to allocate - * string IDs. Drivers for functions, configurations, or gadgets will - * then store that ID in the appropriate descriptors and string table. - * - * All string identifier should be allocated using this, - * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for - * example different functions don't wrongly assign different meanings - * to the same identifier. - */ -int usb_string_ids_n(struct usb_composite_dev *c, unsigned n) -{ - u8 next = c->next_string_id; - - if (n > 254 || next + n > 254) - return -ENODEV; - - c->next_string_id += n; - return next + 1; -} - -static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) - debug("%s: setup complete --> %d, %d/%d\n", __func__, - req->status, req->actual, req->length); -} - -/* - * The setup() callback implements all the ep0 functionality that's - * not handled lower down, in hardware or the hardware driver(like - * device and endpoint feature flags, and their status). It's all - * housekeeping for the gadget function we're implementing. Most of - * the work is in config and function specific setup. - */ -static int -composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) -{ - u16 w_length = le16_to_cpu(ctrl->wLength); - u16 w_index = le16_to_cpu(ctrl->wIndex); - u16 w_value = le16_to_cpu(ctrl->wValue); - struct usb_composite_dev *cdev = get_gadget_data(gadget); - u8 intf = w_index & 0xFF; - int value = -EOPNOTSUPP; - struct usb_request *req = cdev->req; - struct usb_function *f = NULL; - int standard; - u8 endp; - struct usb_configuration *c; - - /* - * partial re-init of the response message; the function or the - * gadget might need to intercept e.g. a control-OUT completion - * when we delegate to it. - */ - req->zero = 0; - req->complete = composite_setup_complete; - req->length = USB_BUFSIZ; - gadget->ep0->driver_data = cdev; - standard = (ctrl->bRequestType & USB_TYPE_MASK) - == USB_TYPE_STANDARD; - if (!standard) - goto unknown; - - switch (ctrl->bRequest) { - - /* we handle all standard USB descriptors */ - case USB_REQ_GET_DESCRIPTOR: - if (ctrl->bRequestType != USB_DIR_IN) - goto unknown; - switch (w_value >> 8) { - - case USB_DT_DEVICE: - cdev->desc.bNumConfigurations = - count_configs(cdev, USB_DT_DEVICE); - value = min(w_length, (u16) sizeof cdev->desc); - memcpy(req->buf, &cdev->desc, value); - break; - case USB_DT_DEVICE_QUALIFIER: - if (!gadget_is_dualspeed(gadget)) - break; - device_qual(cdev); - value = min(w_length, - sizeof(struct usb_qualifier_descriptor)); - break; - case USB_DT_OTHER_SPEED_CONFIG: - if (!gadget_is_dualspeed(gadget)) - break; - - case USB_DT_CONFIG: - value = config_desc(cdev, w_value); - if (value >= 0) - value = min(w_length, (u16) value); - break; - case USB_DT_STRING: - value = get_string(cdev, req->buf, - w_index, w_value & 0xff); - if (value >= 0) - value = min(w_length, (u16) value); - break; - default: - goto unknown; - } - break; - - /* any number of configs can work */ - case USB_REQ_SET_CONFIGURATION: - if (ctrl->bRequestType != 0) - goto unknown; - if (gadget_is_otg(gadget)) { - if (gadget->a_hnp_support) - debug("HNP available\n"); - else if (gadget->a_alt_hnp_support) - debug("HNP on another port\n"); - else - debug("HNP inactive\n"); - } - - value = set_config(cdev, ctrl, w_value); - break; - case USB_REQ_GET_CONFIGURATION: - if (ctrl->bRequestType != USB_DIR_IN) - goto unknown; - if (cdev->config) - *(u8 *)req->buf = cdev->config->bConfigurationValue; - else - *(u8 *)req->buf = 0; - value = min(w_length, (u16) 1); - break; - - /* - * function drivers must handle get/set altsetting; if there's - * no get() method, we know only altsetting zero works. - */ - case USB_REQ_SET_INTERFACE: - if (ctrl->bRequestType != USB_RECIP_INTERFACE) - goto unknown; - if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) - break; - f = cdev->config->interface[intf]; - if (!f) - break; - if (w_value && !f->set_alt) - break; - value = f->set_alt(f, w_index, w_value); - break; - case USB_REQ_GET_INTERFACE: - if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) - goto unknown; - if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) - break; - f = cdev->config->interface[intf]; - if (!f) - break; - /* lots of interfaces only need altsetting zero... */ - value = f->get_alt ? f->get_alt(f, w_index) : 0; - if (value < 0) - break; - *((u8 *)req->buf) = value; - value = min(w_length, (u16) 1); - break; - default: -unknown: - debug("non-core control req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - - /* - * functions always handle their interfaces and endpoints... - * punt other recipients (other, WUSB, ...) to the current - * configuration code. - */ - switch (ctrl->bRequestType & USB_RECIP_MASK) { - case USB_RECIP_INTERFACE: - f = cdev->config->interface[intf]; - break; - - case USB_RECIP_ENDPOINT: - endp = ((w_index & 0x80) >> 3) | (w_index & 0x0f); - list_for_each_entry(f, &cdev->config->functions, list) { - if (test_bit(endp, f->endpoints)) - break; - } - if (&f->list == &cdev->config->functions) - f = NULL; - break; - /* - * dfu-util (version 0.5) sets bmRequestType.Receipent = Device - * for non-standard request (w_value = 0x21, - * bRequest = GET_DESCRIPTOR in this case). - * When only one interface is registered (as it is done now), - * then this request shall be handled as it was requested for - * interface. - * - * In the below code it is checked if only one interface is - * present and proper function for it is extracted. Due to that - * function's setup (f->setup) is called to handle this - * special non-standard request. - */ - case USB_RECIP_DEVICE: - debug("cdev->config->next_interface_id: %d intf: %d\n", - cdev->config->next_interface_id, intf); - if (cdev->config->next_interface_id == 1) - f = cdev->config->interface[intf]; - break; - } - - if (f && f->setup) - value = f->setup(f, ctrl); - else { - c = cdev->config; - if (c && c->setup) - value = c->setup(c, ctrl); - } - - goto done; - } - - /* respond with data transfer before status phase? */ - if (value >= 0) { - req->length = value; - req->zero = value < w_length; - value = usb_ep_queue(gadget->ep0, req, GFP_KERNEL); - if (value < 0) { - debug("ep_queue --> %d\n", value); - req->status = 0; - composite_setup_complete(gadget->ep0, req); - } - } - -done: - /* device either stalls (value < 0) or reports success */ - return value; -} - -static void composite_disconnect(struct usb_gadget *gadget) -{ - struct usb_composite_dev *cdev = get_gadget_data(gadget); - - if (cdev->config) - reset_config(cdev); - if (composite->disconnect) - composite->disconnect(cdev); -} - -static void composite_unbind(struct usb_gadget *gadget) -{ - struct usb_composite_dev *cdev = get_gadget_data(gadget); - struct usb_configuration *c; - struct usb_function *f; - - /* - * composite_disconnect() must already have been called - * by the underlying peripheral controller driver! - * so there's no i/o concurrency that could affect the - * state protected by cdev->lock. - */ - BUG_ON(cdev->config); - - while (!list_empty(&cdev->configs)) { - c = list_first_entry(&cdev->configs, - struct usb_configuration, list); - while (!list_empty(&c->functions)) { - f = list_first_entry(&c->functions, - struct usb_function, list); - list_del(&f->list); - if (f->unbind) { - debug("unbind function '%s'/%p\n", - f->name, f); - f->unbind(c, f); - } - } - list_del(&c->list); - if (c->unbind) { - debug("unbind config '%s'/%p\n", c->label, c); - c->unbind(c); - } - } - if (composite->unbind) - composite->unbind(cdev); - - if (cdev->req) { - kfree(cdev->req->buf); - usb_ep_free_request(gadget->ep0, cdev->req); - } - kfree(cdev); - set_gadget_data(gadget, NULL); - - composite = NULL; -} - -static int composite_bind(struct usb_gadget *gadget) -{ - int status = -ENOMEM; - struct usb_composite_dev *cdev; - - cdev = calloc(sizeof *cdev, 1); - if (!cdev) - return status; - - cdev->gadget = gadget; - set_gadget_data(gadget, cdev); - INIT_LIST_HEAD(&cdev->configs); - - /* preallocate control response and buffer */ - cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); - if (!cdev->req) - goto fail; - cdev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, USB_BUFSIZ); - if (!cdev->req->buf) - goto fail; - cdev->req->complete = composite_setup_complete; - gadget->ep0->driver_data = cdev; - - cdev->bufsiz = USB_BUFSIZ; - cdev->driver = composite; - - usb_gadget_set_selfpowered(gadget); - usb_ep_autoconfig_reset(cdev->gadget); - - status = composite->bind(cdev); - if (status < 0) - goto fail; - - memcpy(&cdev->desc, composite->dev, - sizeof(struct usb_device_descriptor)); - cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; - - debug("%s: ready\n", composite->name); - return 0; - -fail: - composite_unbind(gadget); - return status; -} - -static void -composite_suspend(struct usb_gadget *gadget) -{ - struct usb_composite_dev *cdev = get_gadget_data(gadget); - struct usb_function *f; - - debug("%s: suspend\n", __func__); - if (cdev->config) { - list_for_each_entry(f, &cdev->config->functions, list) { - if (f->suspend) - f->suspend(f); - } - } - if (composite->suspend) - composite->suspend(cdev); - - cdev->suspended = 1; -} - -static void -composite_resume(struct usb_gadget *gadget) -{ - struct usb_composite_dev *cdev = get_gadget_data(gadget); - struct usb_function *f; - - debug("%s: resume\n", __func__); - if (composite->resume) - composite->resume(cdev); - if (cdev->config) { - list_for_each_entry(f, &cdev->config->functions, list) { - if (f->resume) - f->resume(f); - } - } - - cdev->suspended = 0; -} - -static struct usb_gadget_driver composite_driver = { - .speed = USB_SPEED_HIGH, - - .bind = composite_bind, - .unbind = composite_unbind, - - .setup = composite_setup, - .disconnect = composite_disconnect, - - .suspend = composite_suspend, - .resume = composite_resume, -}; - -/** - * usb_composite_register() - register a composite driver - * @driver: the driver to register - * Context: single threaded during gadget setup - * - * This function is used to register drivers using the composite driver - * framework. The return value is zero, or a negative errno value. - * Those values normally come from the driver's @bind method, which does - * all the work of setting up the driver to match the hardware. - * - * On successful return, the gadget is ready to respond to requests from - * the host, unless one of its components invokes usb_gadget_disconnect() - * while it was binding. That would usually be done in order to wait for - * some userspace participation. - */ -int usb_composite_register(struct usb_composite_driver *driver) -{ - if (!driver || !driver->dev || !driver->bind || composite) - return -EINVAL; - - if (!driver->name) - driver->name = "composite"; - composite = driver; - - return usb_gadget_register_driver(&composite_driver); -} - -/** - * usb_composite_unregister() - unregister a composite driver - * @driver: the driver to unregister - * - * This function is used to unregister drivers using the composite - * driver framework. - */ -void usb_composite_unregister(struct usb_composite_driver *driver) -{ - if (composite != driver) - return; - usb_gadget_unregister_driver(&composite_driver); - composite = NULL; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/config.c b/qemu/roms/u-boot/drivers/usb/gadget/config.c deleted file mode 100644 index 014a6791c..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/config.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * usb/gadget/config.c -- simplify building config descriptors - * - * Copyright (C) 2003 David Brownell - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and - * Remy Bohmer <linux@bohmer.net> - */ - -#include <common.h> -#include <asm/unaligned.h> -#include <asm/errno.h> -#include <linux/list.h> -#include <linux/string.h> - -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> - - -/** - * usb_descriptor_fillbuf - fill buffer with descriptors - * @buf: Buffer to be filled - * @buflen: Size of buf - * @src: Array of descriptor pointers, terminated by null pointer. - * - * Copies descriptors into the buffer, returning the length or a - * negative error code if they can't all be copied. Useful when - * assembling descriptors for an associated set of interfaces used - * as part of configuring a composite device; or in other cases where - * sets of descriptors need to be marshaled. - */ -int -usb_descriptor_fillbuf(void *buf, unsigned buflen, - const struct usb_descriptor_header **src) -{ - u8 *dest = buf; - - if (!src) - return -EINVAL; - - /* fill buffer from src[] until null descriptor ptr */ - for (; NULL != *src; src++) { - unsigned len = (*src)->bLength; - - if (len > buflen) - return -EINVAL; - memcpy(dest, *src, len); - buflen -= len; - dest += len; - } - return dest - (u8 *)buf; -} - - -/** - * usb_gadget_config_buf - builts a complete configuration descriptor - * @config: Header for the descriptor, including characteristics such - * as power requirements and number of interfaces. - * @desc: Null-terminated vector of pointers to the descriptors (interface, - * endpoint, etc) defining all functions in this device configuration. - * @buf: Buffer for the resulting configuration descriptor. - * @length: Length of buffer. If this is not big enough to hold the - * entire configuration descriptor, an error code will be returned. - * - * This copies descriptors into the response buffer, building a descriptor - * for that configuration. It returns the buffer length or a negative - * status code. The config.wTotalLength field is set to match the length - * of the result, but other descriptor fields (including power usage and - * interface count) must be set by the caller. - * - * Gadget drivers could use this when constructing a config descriptor - * in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the - * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed. - */ -int usb_gadget_config_buf( - const struct usb_config_descriptor *config, - void *buf, - unsigned length, - const struct usb_descriptor_header **desc -) -{ - struct usb_config_descriptor *cp = buf; - int len; - - /* config descriptor first */ - if (length < USB_DT_CONFIG_SIZE || !desc) - return -EINVAL; - /* config need not be aligned */ - memcpy(cp, config, sizeof(*cp)); - - /* then interface/endpoint/class/vendor/... */ - len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8 *)buf, - length - USB_DT_CONFIG_SIZE, desc); - if (len < 0) - return len; - len += USB_DT_CONFIG_SIZE; - if (len > 0xffff) - return -EINVAL; - - /* patch up the config descriptor */ - cp->bLength = USB_DT_CONFIG_SIZE; - cp->bDescriptorType = USB_DT_CONFIG; - put_unaligned_le16(len, &cp->wTotalLength); - cp->bmAttributes |= USB_CONFIG_ATT_ONE; - return len; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/core.c b/qemu/roms/u-boot/drivers/usb/gadget/core.c deleted file mode 100644 index 30d55a49a..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/core.c +++ /dev/null @@ -1,669 +0,0 @@ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * Based on - * linux/drivers/usbd/usbd.c.c - USB Device Core Layer - * - * Copyright (c) 2000, 2001, 2002 Lineo - * Copyright (c) 2001 Hewlett Packard - * - * By: - * Stuart Lynne <sl@lineo.com>, - * Tom Rushworth <tbr@lineo.com>, - * Bruce Balden <balden@lineo.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <malloc.h> -#include <usbdevice.h> - -#define MAX_INTERFACES 2 - - -int maxstrings = 20; - -/* Global variables ************************************************************************** */ - -struct usb_string_descriptor **usb_strings; - -int usb_devices; - -extern struct usb_function_driver ep0_driver; - -int registered_functions; -int registered_devices; - -char *usbd_device_events[] = { - "DEVICE_UNKNOWN", - "DEVICE_INIT", - "DEVICE_CREATE", - "DEVICE_HUB_CONFIGURED", - "DEVICE_RESET", - "DEVICE_ADDRESS_ASSIGNED", - "DEVICE_CONFIGURED", - "DEVICE_SET_INTERFACE", - "DEVICE_SET_FEATURE", - "DEVICE_CLEAR_FEATURE", - "DEVICE_DE_CONFIGURED", - "DEVICE_BUS_INACTIVE", - "DEVICE_BUS_ACTIVITY", - "DEVICE_POWER_INTERRUPTION", - "DEVICE_HUB_RESET", - "DEVICE_DESTROY", - "DEVICE_FUNCTION_PRIVATE", -}; - -char *usbd_device_states[] = { - "STATE_INIT", - "STATE_CREATED", - "STATE_ATTACHED", - "STATE_POWERED", - "STATE_DEFAULT", - "STATE_ADDRESSED", - "STATE_CONFIGURED", - "STATE_UNKNOWN", -}; - -char *usbd_device_requests[] = { - "GET STATUS", /* 0 */ - "CLEAR FEATURE", /* 1 */ - "RESERVED", /* 2 */ - "SET FEATURE", /* 3 */ - "RESERVED", /* 4 */ - "SET ADDRESS", /* 5 */ - "GET DESCRIPTOR", /* 6 */ - "SET DESCRIPTOR", /* 7 */ - "GET CONFIGURATION", /* 8 */ - "SET CONFIGURATION", /* 9 */ - "GET INTERFACE", /* 10 */ - "SET INTERFACE", /* 11 */ - "SYNC FRAME", /* 12 */ -}; - -char *usbd_device_descriptors[] = { - "UNKNOWN", /* 0 */ - "DEVICE", /* 1 */ - "CONFIG", /* 2 */ - "STRING", /* 3 */ - "INTERFACE", /* 4 */ - "ENDPOINT", /* 5 */ - "DEVICE QUALIFIER", /* 6 */ - "OTHER SPEED", /* 7 */ - "INTERFACE POWER", /* 8 */ -}; - -char *usbd_device_status[] = { - "USBD_OPENING", - "USBD_OK", - "USBD_SUSPENDED", - "USBD_CLOSING", -}; - - -/* Descriptor support functions ************************************************************** */ - - -/** - * usbd_get_string - find and return a string descriptor - * @index: string index to return - * - * Find an indexed string and return a pointer to a it. - */ -struct usb_string_descriptor *usbd_get_string (__u8 index) -{ - if (index >= maxstrings) { - return NULL; - } - return usb_strings[index]; -} - - -/* Access to device descriptor functions ***************************************************** */ - - -/* * - * usbd_device_configuration_instance - find a configuration instance for this device - * @device: - * @configuration: index to configuration, 0 - N-1 - * - * Get specifed device configuration. Index should be bConfigurationValue-1. - */ -static struct usb_configuration_instance *usbd_device_configuration_instance (struct usb_device_instance *device, - unsigned int port, unsigned int configuration) -{ - if (configuration >= device->configurations) - return NULL; - - return device->configuration_instance_array + configuration; -} - - -/* * - * usbd_device_interface_instance - * @device: - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * - * Return the specified interface descriptor for the specified device. - */ -struct usb_interface_instance *usbd_device_interface_instance (struct usb_device_instance *device, int port, int configuration, int interface) -{ - struct usb_configuration_instance *configuration_instance; - - if ((configuration_instance = usbd_device_configuration_instance (device, port, configuration)) == NULL) { - return NULL; - } - if (interface >= configuration_instance->interfaces) { - return NULL; - } - return configuration_instance->interface_instance_array + interface; -} - -/* * - * usbd_device_alternate_descriptor_list - * @device: - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: alternate setting - * - * Return the specified alternate descriptor for the specified device. - */ -struct usb_alternate_instance *usbd_device_alternate_instance (struct usb_device_instance *device, int port, int configuration, int interface, int alternate) -{ - struct usb_interface_instance *interface_instance; - - if ((interface_instance = usbd_device_interface_instance (device, port, configuration, interface)) == NULL) { - return NULL; - } - - if (alternate >= interface_instance->alternates) { - return NULL; - } - - return interface_instance->alternates_instance_array + alternate; -} - - -/* * - * usbd_device_device_descriptor - * @device: which device - * @configuration: index to configuration, 0 - N-1 - * @port: which port - * - * Return the specified configuration descriptor for the specified device. - */ -struct usb_device_descriptor *usbd_device_device_descriptor (struct usb_device_instance *device, int port) -{ - return (device->device_descriptor); -} - -/** - * usbd_device_configuration_descriptor - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * - * Return the specified configuration descriptor for the specified device. - */ -struct usb_configuration_descriptor *usbd_device_configuration_descriptor (struct - usb_device_instance - *device, int port, int configuration) -{ - struct usb_configuration_instance *configuration_instance; - if (!(configuration_instance = usbd_device_configuration_instance (device, port, configuration))) { - return NULL; - } - return (configuration_instance->configuration_descriptor); -} - - -/** - * usbd_device_interface_descriptor - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: alternate setting - * - * Return the specified interface descriptor for the specified device. - */ -struct usb_interface_descriptor *usbd_device_interface_descriptor (struct usb_device_instance - *device, int port, int configuration, int interface, int alternate) -{ - struct usb_interface_instance *interface_instance; - if (!(interface_instance = usbd_device_interface_instance (device, port, configuration, interface))) { - return NULL; - } - if ((alternate < 0) || (alternate >= interface_instance->alternates)) { - return NULL; - } - return (interface_instance->alternates_instance_array[alternate].interface_descriptor); -} - -/** - * usbd_device_endpoint_descriptor_index - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: index setting - * @index: which index - * - * Return the specified endpoint descriptor for the specified device. - */ -struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor_index (struct usb_device_instance - *device, int port, int configuration, int interface, int alternate, int index) -{ - struct usb_alternate_instance *alternate_instance; - - if (!(alternate_instance = usbd_device_alternate_instance (device, port, configuration, interface, alternate))) { - return NULL; - } - if (index >= alternate_instance->endpoints) { - return NULL; - } - return *(alternate_instance->endpoints_descriptor_array + index); -} - - -/** - * usbd_device_endpoint_transfersize - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @index: which index - * - * Return the specified endpoint transfer size; - */ -int usbd_device_endpoint_transfersize (struct usb_device_instance *device, int port, int configuration, int interface, int alternate, int index) -{ - struct usb_alternate_instance *alternate_instance; - - if (!(alternate_instance = usbd_device_alternate_instance (device, port, configuration, interface, alternate))) { - return 0; - } - if (index >= alternate_instance->endpoints) { - return 0; - } - return *(alternate_instance->endpoint_transfersize_array + index); -} - - -/** - * usbd_device_endpoint_descriptor - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: alternate setting - * @endpoint: which endpoint - * - * Return the specified endpoint descriptor for the specified device. - */ -struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor (struct usb_device_instance *device, int port, int configuration, int interface, int alternate, int endpoint) -{ - struct usb_endpoint_descriptor *endpoint_descriptor; - int i; - - for (i = 0; !(endpoint_descriptor = usbd_device_endpoint_descriptor_index (device, port, configuration, interface, alternate, i)); i++) { - if (endpoint_descriptor->bEndpointAddress == endpoint) { - return endpoint_descriptor; - } - } - return NULL; -} - -/** - * usbd_endpoint_halted - * @device: point to struct usb_device_instance - * @endpoint: endpoint to check - * - * Return non-zero if endpoint is halted. - */ -int usbd_endpoint_halted (struct usb_device_instance *device, int endpoint) -{ - return (device->status == USB_STATUS_HALT); -} - - -/** - * usbd_rcv_complete - complete a receive - * @endpoint: - * @len: - * @urb_bad: - * - * Called from rcv interrupt to complete. - */ -void usbd_rcv_complete(struct usb_endpoint_instance *endpoint, int len, int urb_bad) -{ - if (endpoint) { - struct urb *rcv_urb; - - /*usbdbg("len: %d urb: %p\n", len, endpoint->rcv_urb); */ - - /* if we had an urb then update actual_length, dispatch if neccessary */ - if ((rcv_urb = endpoint->rcv_urb)) { - - /*usbdbg("actual: %d buffer: %d\n", */ - /*rcv_urb->actual_length, rcv_urb->buffer_length); */ - - /* check the urb is ok, are we adding data less than the packetsize */ - if (!urb_bad && (len <= endpoint->rcv_packetSize)) { - /*usbdbg("updating actual_length by %d\n",len); */ - - /* increment the received data size */ - rcv_urb->actual_length += len; - - } else { - usberr(" RECV_ERROR actual: %d buffer: %d urb_bad: %d\n", - rcv_urb->actual_length, rcv_urb->buffer_length, urb_bad); - - rcv_urb->actual_length = 0; - rcv_urb->status = RECV_ERROR; - } - } else { - usberr("no rcv_urb!"); - } - } else { - usberr("no endpoint!"); - } - -} - -/** - * usbd_tx_complete - complete a transmit - * @endpoint: - * @resetart: - * - * Called from tx interrupt to complete. - */ -void usbd_tx_complete (struct usb_endpoint_instance *endpoint) -{ - if (endpoint) { - struct urb *tx_urb; - - /* if we have a tx_urb advance or reset, finish if complete */ - if ((tx_urb = endpoint->tx_urb)) { - int sent = endpoint->last; - endpoint->sent += sent; - endpoint->last -= sent; - - if( (endpoint->tx_urb->actual_length - endpoint->sent) <= 0 ) { - tx_urb->actual_length = 0; - endpoint->sent = 0; - endpoint->last = 0; - - /* Remove from active, save for re-use */ - urb_detach(tx_urb); - urb_append(&endpoint->done, tx_urb); - /*usbdbg("done->next %p, tx_urb %p, done %p", */ - /* endpoint->done.next, tx_urb, &endpoint->done); */ - - endpoint->tx_urb = first_urb_detached(&endpoint->tx); - if( endpoint->tx_urb ) { - endpoint->tx_queue--; - usbdbg("got urb from tx list"); - } - if( !endpoint->tx_urb ) { - /*usbdbg("taking urb from done list"); */ - endpoint->tx_urb = first_urb_detached(&endpoint->done); - } - if( !endpoint->tx_urb ) { - usbdbg("allocating new urb for tx_urb"); - endpoint->tx_urb = usbd_alloc_urb(tx_urb->device, endpoint); - } - } - } - } -} - -/* URB linked list functions ***************************************************** */ - -/* - * Initialize an urb_link to be a single element list. - * If the urb_link is being used as a distinguished list head - * the list is empty when the head is the only link in the list. - */ -void urb_link_init (urb_link * ul) -{ - if (ul) { - ul->prev = ul->next = ul; - } -} - -/* - * Detach an urb_link from a list, and set it - * up as a single element list, so no dangling - * pointers can be followed, and so it can be - * joined to another list if so desired. - */ -void urb_detach (struct urb *urb) -{ - if (urb) { - urb_link *ul = &urb->link; - ul->next->prev = ul->prev; - ul->prev->next = ul->next; - urb_link_init (ul); - } -} - -/* - * Return the first urb_link in a list with a distinguished - * head "hd", or NULL if the list is empty. This will also - * work as a predicate, returning NULL if empty, and non-NULL - * otherwise. - */ -urb_link *first_urb_link (urb_link * hd) -{ - urb_link *nx; - if (NULL != hd && NULL != (nx = hd->next) && nx != hd) { - /* There is at least one element in the list */ - /* (besides the distinguished head). */ - return (nx); - } - /* The list is empty */ - return (NULL); -} - -/* - * Return the first urb in a list with a distinguished - * head "hd", or NULL if the list is empty. - */ -struct urb *first_urb (urb_link * hd) -{ - urb_link *nx; - if (NULL == (nx = first_urb_link (hd))) { - /* The list is empty */ - return (NULL); - } - return (p2surround (struct urb, link, nx)); -} - -/* - * Detach and return the first urb in a list with a distinguished - * head "hd", or NULL if the list is empty. - * - */ -struct urb *first_urb_detached (urb_link * hd) -{ - struct urb *urb; - if ((urb = first_urb (hd))) { - urb_detach (urb); - } - return urb; -} - - -/* - * Append an urb_link (or a whole list of - * urb_links) to the tail of another list - * of urb_links. - */ -void urb_append (urb_link * hd, struct urb *urb) -{ - if (hd && urb) { - urb_link *new = &urb->link; - - /* This allows the new urb to be a list of urbs, */ - /* with new pointing at the first, but the link */ - /* must be initialized. */ - /* Order is important here... */ - urb_link *pul = hd->prev; - new->prev->next = hd; - hd->prev = new->prev; - new->prev = pul; - pul->next = new; - } -} - -/* URB create/destroy functions ***************************************************** */ - -/** - * usbd_alloc_urb - allocate an URB appropriate for specified endpoint - * @device: device instance - * @endpoint: endpoint - * - * Allocate an urb structure. The usb device urb structure is used to - * contain all data associated with a transfer, including a setup packet for - * control transfers. - * - * NOTE: endpoint_address MUST contain a direction flag. - */ -struct urb *usbd_alloc_urb (struct usb_device_instance *device, - struct usb_endpoint_instance *endpoint) -{ - struct urb *urb; - - if (!(urb = (struct urb *) malloc (sizeof (struct urb)))) { - usberr (" F A T A L: malloc(%zu) FAILED!!!!", - sizeof (struct urb)); - return NULL; - } - - /* Fill in known fields */ - memset (urb, 0, sizeof (struct urb)); - urb->endpoint = endpoint; - urb->device = device; - urb->buffer = (u8 *) urb->buffer_data; - urb->buffer_length = sizeof (urb->buffer_data); - - urb_link_init (&urb->link); - - return urb; -} - -/** - * usbd_dealloc_urb - deallocate an URB and associated buffer - * @urb: pointer to an urb structure - * - * Deallocate an urb structure and associated data. - */ -void usbd_dealloc_urb (struct urb *urb) -{ - if (urb) { - free (urb); - } -} - -/* Event signaling functions ***************************************************** */ - -/** - * usbd_device_event - called to respond to various usb events - * @device: pointer to struct device - * @event: event to respond to - * - * Used by a Bus driver to indicate an event. - */ -void usbd_device_event_irq (struct usb_device_instance *device, usb_device_event_t event, int data) -{ - usb_device_state_t state; - - if (!device || !device->bus) { - usberr("(%p,%d) NULL device or device->bus", device, event); - return; - } - - state = device->device_state; - - usbinfo("%s", usbd_device_events[event]); - - switch (event) { - case DEVICE_UNKNOWN: - break; - case DEVICE_INIT: - device->device_state = STATE_INIT; - break; - - case DEVICE_CREATE: - device->device_state = STATE_ATTACHED; - break; - - case DEVICE_HUB_CONFIGURED: - device->device_state = STATE_POWERED; - break; - - case DEVICE_RESET: - device->device_state = STATE_DEFAULT; - device->address = 0; - break; - - case DEVICE_ADDRESS_ASSIGNED: - device->device_state = STATE_ADDRESSED; - break; - - case DEVICE_CONFIGURED: - device->device_state = STATE_CONFIGURED; - break; - - case DEVICE_DE_CONFIGURED: - device->device_state = STATE_ADDRESSED; - break; - - case DEVICE_BUS_INACTIVE: - if (device->status != USBD_CLOSING) { - device->status = USBD_SUSPENDED; - } - break; - case DEVICE_BUS_ACTIVITY: - if (device->status != USBD_CLOSING) { - device->status = USBD_OK; - } - break; - - case DEVICE_SET_INTERFACE: - break; - case DEVICE_SET_FEATURE: - break; - case DEVICE_CLEAR_FEATURE: - break; - - case DEVICE_POWER_INTERRUPTION: - device->device_state = STATE_POWERED; - break; - case DEVICE_HUB_RESET: - device->device_state = STATE_ATTACHED; - break; - case DEVICE_DESTROY: - device->device_state = STATE_UNKNOWN; - break; - - case DEVICE_FUNCTION_PRIVATE: - break; - - default: - usbdbg("event %d - not handled",event); - break; - } - debug("%s event: %d oldstate: %d newstate: %d status: %d address: %d", - device->name, event, state, - device->device_state, device->status, device->address); - - /* tell the bus interface driver */ - if( device->event ) { - /* usbdbg("calling device->event"); */ - device->event(device, event, data); - } -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/designware_udc.c b/qemu/roms/u-boot/drivers/usb/gadget/designware_udc.c deleted file mode 100644 index b7c10384a..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/designware_udc.c +++ /dev/null @@ -1,1019 +0,0 @@ -/* - * Based on drivers/usb/gadget/omap1510_udc.c - * TI OMAP1510 USB bus interface driver - * - * (C) Copyright 2009 - * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> - -#include <usbdevice.h> -#include "ep0.h" -#include <usb/designware_udc.h> -#include <usb/udc.h> -#include <asm/arch/hardware.h> - -#define UDC_INIT_MDELAY 80 /* Device settle delay */ - -/* Some kind of debugging output... */ -#ifndef DEBUG_DWUSBTTY -#define UDCDBG(str) -#define UDCDBGA(fmt, args...) -#else -#define UDCDBG(str) serial_printf(str "\n") -#define UDCDBGA(fmt, args...) serial_printf(fmt "\n", ##args) -#endif - -static struct urb *ep0_urb; -static struct usb_device_instance *udc_device; - -static struct plug_regs *const plug_regs_p = - (struct plug_regs * const)CONFIG_SYS_PLUG_BASE; -static struct udc_regs *const udc_regs_p = - (struct udc_regs * const)CONFIG_SYS_USBD_BASE; -static struct udc_endp_regs *const outep_regs_p = - &((struct udc_regs * const)CONFIG_SYS_USBD_BASE)->out_regs[0]; -static struct udc_endp_regs *const inep_regs_p = - &((struct udc_regs * const)CONFIG_SYS_USBD_BASE)->in_regs[0]; - -/* - * udc_state_transition - Write the next packet to TxFIFO. - * @initial: Initial state. - * @final: Final state. - * - * Helper function to implement device state changes. The device states and - * the events that transition between them are: - * - * STATE_ATTACHED - * || /\ - * \/ || - * DEVICE_HUB_CONFIGURED DEVICE_HUB_RESET - * || /\ - * \/ || - * STATE_POWERED - * || /\ - * \/ || - * DEVICE_RESET DEVICE_POWER_INTERRUPTION - * || /\ - * \/ || - * STATE_DEFAULT - * || /\ - * \/ || - * DEVICE_ADDRESS_ASSIGNED DEVICE_RESET - * || /\ - * \/ || - * STATE_ADDRESSED - * || /\ - * \/ || - * DEVICE_CONFIGURED DEVICE_DE_CONFIGURED - * || /\ - * \/ || - * STATE_CONFIGURED - * - * udc_state_transition transitions up (in the direction from STATE_ATTACHED - * to STATE_CONFIGURED) from the specified initial state to the specified final - * state, passing through each intermediate state on the way. If the initial - * state is at or above (i.e. nearer to STATE_CONFIGURED) the final state, then - * no state transitions will take place. - * - * udc_state_transition also transitions down (in the direction from - * STATE_CONFIGURED to STATE_ATTACHED) from the specified initial state to the - * specified final state, passing through each intermediate state on the way. - * If the initial state is at or below (i.e. nearer to STATE_ATTACHED) the final - * state, then no state transitions will take place. - * - * This function must only be called with interrupts disabled. - */ -static void udc_state_transition(usb_device_state_t initial, - usb_device_state_t final) -{ - if (initial < final) { - switch (initial) { - case STATE_ATTACHED: - usbd_device_event_irq(udc_device, - DEVICE_HUB_CONFIGURED, 0); - if (final == STATE_POWERED) - break; - case STATE_POWERED: - usbd_device_event_irq(udc_device, DEVICE_RESET, 0); - if (final == STATE_DEFAULT) - break; - case STATE_DEFAULT: - usbd_device_event_irq(udc_device, - DEVICE_ADDRESS_ASSIGNED, 0); - if (final == STATE_ADDRESSED) - break; - case STATE_ADDRESSED: - usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0); - case STATE_CONFIGURED: - break; - default: - break; - } - } else if (initial > final) { - switch (initial) { - case STATE_CONFIGURED: - usbd_device_event_irq(udc_device, - DEVICE_DE_CONFIGURED, 0); - if (final == STATE_ADDRESSED) - break; - case STATE_ADDRESSED: - usbd_device_event_irq(udc_device, DEVICE_RESET, 0); - if (final == STATE_DEFAULT) - break; - case STATE_DEFAULT: - usbd_device_event_irq(udc_device, - DEVICE_POWER_INTERRUPTION, 0); - if (final == STATE_POWERED) - break; - case STATE_POWERED: - usbd_device_event_irq(udc_device, DEVICE_HUB_RESET, 0); - case STATE_ATTACHED: - break; - default: - break; - } - } -} - -/* Stall endpoint */ -static void udc_stall_ep(u32 ep_num) -{ - writel(readl(&inep_regs_p[ep_num].endp_cntl) | ENDP_CNTL_STALL, - &inep_regs_p[ep_num].endp_cntl); - - writel(readl(&outep_regs_p[ep_num].endp_cntl) | ENDP_CNTL_STALL, - &outep_regs_p[ep_num].endp_cntl); -} - -static void *get_fifo(int ep_num, int in) -{ - u32 *fifo_ptr = (u32 *)CONFIG_SYS_FIFO_BASE; - - switch (ep_num) { - case UDC_EP3: - fifo_ptr += readl(&inep_regs_p[1].endp_bsorfn); - /* break intentionally left out */ - - case UDC_EP1: - fifo_ptr += readl(&inep_regs_p[0].endp_bsorfn); - /* break intentionally left out */ - - case UDC_EP0: - default: - if (in) { - fifo_ptr += - readl(&outep_regs_p[2].endp_maxpacksize) >> 16; - /* break intentionally left out */ - } else { - break; - } - - case UDC_EP2: - fifo_ptr += readl(&outep_regs_p[0].endp_maxpacksize) >> 16; - /* break intentionally left out */ - } - - return (void *)fifo_ptr; -} - -static int usbgetpckfromfifo(int epNum, u8 *bufp, u32 len) -{ - u8 *fifo_ptr = (u8 *)get_fifo(epNum, 0); - u32 i, nw, nb; - u32 *wrdp; - u8 *bytp; - u32 tmp[128]; - - if (readl(&udc_regs_p->dev_stat) & DEV_STAT_RXFIFO_EMPTY) - return -1; - - nw = len / sizeof(u32); - nb = len % sizeof(u32); - - /* use tmp buf if bufp is not word aligned */ - if ((int)bufp & 0x3) - wrdp = (u32 *)&tmp[0]; - else - wrdp = (u32 *)bufp; - - for (i = 0; i < nw; i++) { - writel(readl(fifo_ptr), wrdp); - wrdp++; - } - - bytp = (u8 *)wrdp; - for (i = 0; i < nb; i++) { - writeb(readb(fifo_ptr), bytp); - fifo_ptr++; - bytp++; - } - readl(&outep_regs_p[epNum].write_done); - - /* copy back tmp buffer to bufp if bufp is not word aligned */ - if ((int)bufp & 0x3) - memcpy(bufp, tmp, len); - - return 0; -} - -static void usbputpcktofifo(int epNum, u8 *bufp, u32 len) -{ - u32 i, nw, nb; - u32 *wrdp; - u8 *bytp; - u8 *fifo_ptr = get_fifo(epNum, 1); - - nw = len / sizeof(int); - nb = len % sizeof(int); - wrdp = (u32 *)bufp; - for (i = 0; i < nw; i++) { - writel(*wrdp, fifo_ptr); - wrdp++; - } - - bytp = (u8 *)wrdp; - for (i = 0; i < nb; i++) { - writeb(*bytp, fifo_ptr); - fifo_ptr++; - bytp++; - } -} - -/* - * dw_write_noniso_tx_fifo - Write the next packet to TxFIFO. - * @endpoint: Endpoint pointer. - * - * If the endpoint has an active tx_urb, then the next packet of data from the - * URB is written to the tx FIFO. The total amount of data in the urb is given - * by urb->actual_length. The maximum amount of data that can be sent in any - * one packet is given by endpoint->tx_packetSize. The number of data bytes - * from this URB that have already been transmitted is given by endpoint->sent. - * endpoint->last is updated by this routine with the number of data bytes - * transmitted in this packet. - * - */ -static void dw_write_noniso_tx_fifo(struct usb_endpoint_instance - *endpoint) -{ - struct urb *urb = endpoint->tx_urb; - int align; - - if (urb) { - u32 last; - - UDCDBGA("urb->buffer %p, buffer_length %d, actual_length %d", - urb->buffer, urb->buffer_length, urb->actual_length); - - last = MIN(urb->actual_length - endpoint->sent, - endpoint->tx_packetSize); - - if (last) { - u8 *cp = urb->buffer + endpoint->sent; - - /* - * This ensures that USBD packet fifo is accessed - * - through word aligned pointer or - * - through non word aligned pointer but only - * with a max length to make the next packet - * word aligned - */ - - align = ((ulong)cp % sizeof(int)); - if (align) - last = MIN(last, sizeof(int) - align); - - UDCDBGA("endpoint->sent %d, tx_packetSize %d, last %d", - endpoint->sent, endpoint->tx_packetSize, last); - - usbputpcktofifo(endpoint->endpoint_address & - USB_ENDPOINT_NUMBER_MASK, cp, last); - } - endpoint->last = last; - } -} - -/* - * Handle SETUP USB interrupt. - * This function implements TRM Figure 14-14. - */ -static void dw_udc_setup(struct usb_endpoint_instance *endpoint) -{ - u8 *datap = (u8 *)&ep0_urb->device_request; - int ep_addr = endpoint->endpoint_address; - - UDCDBG("-> Entering device setup"); - usbgetpckfromfifo(ep_addr, datap, 8); - - /* Try to process setup packet */ - if (ep0_recv_setup(ep0_urb)) { - /* Not a setup packet, stall next EP0 transaction */ - udc_stall_ep(0); - UDCDBG("can't parse setup packet, still waiting for setup"); - return; - } - - /* Check direction */ - if ((ep0_urb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK) - == USB_REQ_HOST2DEVICE) { - UDCDBG("control write on EP0"); - if (le16_to_cpu(ep0_urb->device_request.wLength)) { - /* Stall this request */ - UDCDBG("Stalling unsupported EP0 control write data " - "stage."); - udc_stall_ep(0); - } - } else { - - UDCDBG("control read on EP0"); - /* - * The ep0_recv_setup function has already placed our response - * packet data in ep0_urb->buffer and the packet length in - * ep0_urb->actual_length. - */ - endpoint->tx_urb = ep0_urb; - endpoint->sent = 0; - /* - * Write packet data to the FIFO. dw_write_noniso_tx_fifo - * will update endpoint->last with the number of bytes written - * to the FIFO. - */ - dw_write_noniso_tx_fifo(endpoint); - - writel(0x0, &inep_regs_p[ep_addr].write_done); - } - - udc_unset_nak(endpoint->endpoint_address); - - UDCDBG("<- Leaving device setup"); -} - -/* - * Handle endpoint 0 RX interrupt - */ -static void dw_udc_ep0_rx(struct usb_endpoint_instance *endpoint) -{ - u8 dummy[64]; - - UDCDBG("RX on EP0"); - - /* Check direction */ - if ((ep0_urb->device_request.bmRequestType - & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) { - /* - * This rx interrupt must be for a control write data - * stage packet. - * - * We don't support control write data stages. - * We should never end up here. - */ - - UDCDBG("Stalling unexpected EP0 control write " - "data stage packet"); - udc_stall_ep(0); - } else { - /* - * This rx interrupt must be for a control read status - * stage packet. - */ - UDCDBG("ACK on EP0 control read status stage packet"); - u32 len = (readl(&outep_regs_p[0].endp_status) >> 11) & 0xfff; - usbgetpckfromfifo(0, dummy, len); - } -} - -/* - * Handle endpoint 0 TX interrupt - */ -static void dw_udc_ep0_tx(struct usb_endpoint_instance *endpoint) -{ - struct usb_device_request *request = &ep0_urb->device_request; - int ep_addr; - - UDCDBG("TX on EP0"); - - /* Check direction */ - if ((request->bmRequestType & USB_REQ_DIRECTION_MASK) == - USB_REQ_HOST2DEVICE) { - /* - * This tx interrupt must be for a control write status - * stage packet. - */ - UDCDBG("ACK on EP0 control write status stage packet"); - } else { - /* - * This tx interrupt must be for a control read data - * stage packet. - */ - int wLength = le16_to_cpu(request->wLength); - - /* - * Update our count of bytes sent so far in this - * transfer. - */ - endpoint->sent += endpoint->last; - - /* - * We are finished with this transfer if we have sent - * all of the bytes in our tx urb (urb->actual_length) - * unless we need a zero-length terminating packet. We - * need a zero-length terminating packet if we returned - * fewer bytes than were requested (wLength) by the host, - * and the number of bytes we returned is an exact - * multiple of the packet size endpoint->tx_packetSize. - */ - if ((endpoint->sent == ep0_urb->actual_length) && - ((ep0_urb->actual_length == wLength) || - (endpoint->last != endpoint->tx_packetSize))) { - /* Done with control read data stage. */ - UDCDBG("control read data stage complete"); - } else { - /* - * We still have another packet of data to send - * in this control read data stage or else we - * need a zero-length terminating packet. - */ - UDCDBG("ACK control read data stage packet"); - dw_write_noniso_tx_fifo(endpoint); - - ep_addr = endpoint->endpoint_address; - writel(0x0, &inep_regs_p[ep_addr].write_done); - } - } -} - -static struct usb_endpoint_instance *dw_find_ep(int ep) -{ - int i; - - for (i = 0; i < udc_device->bus->max_endpoints; i++) { - if ((udc_device->bus->endpoint_array[i].endpoint_address & - USB_ENDPOINT_NUMBER_MASK) == ep) - return &udc_device->bus->endpoint_array[i]; - } - return NULL; -} - -/* - * Handle RX transaction on non-ISO endpoint. - * The ep argument is a physical endpoint number for a non-ISO IN endpoint - * in the range 1 to 15. - */ -static void dw_udc_epn_rx(int ep) -{ - int nbytes = 0; - struct urb *urb; - struct usb_endpoint_instance *endpoint = dw_find_ep(ep); - - if (endpoint) { - urb = endpoint->rcv_urb; - - if (urb) { - u8 *cp = urb->buffer + urb->actual_length; - - nbytes = (readl(&outep_regs_p[ep].endp_status) >> 11) & - 0xfff; - usbgetpckfromfifo(ep, cp, nbytes); - usbd_rcv_complete(endpoint, nbytes, 0); - } - } -} - -/* - * Handle TX transaction on non-ISO endpoint. - * The ep argument is a physical endpoint number for a non-ISO IN endpoint - * in the range 16 to 30. - */ -static void dw_udc_epn_tx(int ep) -{ - struct usb_endpoint_instance *endpoint = dw_find_ep(ep); - - if (!endpoint) - return; - - /* - * We need to transmit a terminating zero-length packet now if - * we have sent all of the data in this URB and the transfer - * size was an exact multiple of the packet size. - */ - if (endpoint->tx_urb && - (endpoint->last == endpoint->tx_packetSize) && - (endpoint->tx_urb->actual_length - endpoint->sent - - endpoint->last == 0)) { - /* handle zero length packet here */ - writel(0x0, &inep_regs_p[ep].write_done); - - } - - if (endpoint->tx_urb && endpoint->tx_urb->actual_length) { - /* retire the data that was just sent */ - usbd_tx_complete(endpoint); - /* - * Check to see if we have more data ready to transmit - * now. - */ - if (endpoint->tx_urb && endpoint->tx_urb->actual_length) { - /* write data to FIFO */ - dw_write_noniso_tx_fifo(endpoint); - writel(0x0, &inep_regs_p[ep].write_done); - - } else if (endpoint->tx_urb - && (endpoint->tx_urb->actual_length == 0)) { - /* udc_set_nak(ep); */ - } - } -} - -/* - * Start of public functions. - */ - -/* Called to start packet transmission. */ -int udc_endpoint_write(struct usb_endpoint_instance *endpoint) -{ - udc_unset_nak(endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK); - return 0; -} - -/* Start to initialize h/w stuff */ -int udc_init(void) -{ - int i; - u32 plug_st; - - udc_device = NULL; - - UDCDBG("starting"); - - readl(&plug_regs_p->plug_pending); - - for (i = 0; i < UDC_INIT_MDELAY; i++) - udelay(1000); - - plug_st = readl(&plug_regs_p->plug_state); - writel(plug_st | PLUG_STATUS_EN, &plug_regs_p->plug_state); - - writel(~0x0, &udc_regs_p->endp_int); - writel(~0x0, &udc_regs_p->dev_int_mask); - writel(~0x0, &udc_regs_p->endp_int_mask); - -#ifndef CONFIG_USBD_HS - writel(DEV_CONF_FS_SPEED | DEV_CONF_REMWAKEUP | DEV_CONF_SELFPOW | - DEV_CONF_PHYINT_16, &udc_regs_p->dev_conf); -#else - writel(DEV_CONF_HS_SPEED | DEV_CONF_REMWAKEUP | DEV_CONF_SELFPOW | - DEV_CONF_PHYINT_16, &udc_regs_p->dev_conf); -#endif - - writel(DEV_CNTL_SOFTDISCONNECT, &udc_regs_p->dev_cntl); - - /* Clear all interrupts pending */ - writel(DEV_INT_MSK, &udc_regs_p->dev_int); - - return 0; -} - -int is_usbd_high_speed(void) -{ - return (readl(&udc_regs_p->dev_stat) & DEV_STAT_ENUM) ? 0 : 1; -} - -/* - * udc_setup_ep - setup endpoint - * Associate a physical endpoint with endpoint_instance - */ -void udc_setup_ep(struct usb_device_instance *device, - u32 ep, struct usb_endpoint_instance *endpoint) -{ - UDCDBGA("setting up endpoint addr %x", endpoint->endpoint_address); - int ep_addr; - int ep_num, ep_type; - int packet_size; - int buffer_size; - int attributes; - char *tt; - u32 endp_intmask; - - if ((ep != 0) && (udc_device->device_state < STATE_ADDRESSED)) - return; - - tt = getenv("usbtty"); - if (!tt) - tt = "generic"; - - ep_addr = endpoint->endpoint_address; - ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; - - if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { - /* IN endpoint */ - packet_size = endpoint->tx_packetSize; - buffer_size = packet_size * 2; - attributes = endpoint->tx_attributes; - } else { - /* OUT endpoint */ - packet_size = endpoint->rcv_packetSize; - buffer_size = packet_size * 2; - attributes = endpoint->rcv_attributes; - } - - switch (attributes & USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_CONTROL: - ep_type = ENDP_EPTYPE_CNTL; - break; - case USB_ENDPOINT_XFER_BULK: - default: - ep_type = ENDP_EPTYPE_BULK; - break; - case USB_ENDPOINT_XFER_INT: - ep_type = ENDP_EPTYPE_INT; - break; - case USB_ENDPOINT_XFER_ISOC: - ep_type = ENDP_EPTYPE_ISO; - break; - } - - struct udc_endp_regs *out_p = &outep_regs_p[ep_num]; - struct udc_endp_regs *in_p = &inep_regs_p[ep_num]; - - if (!ep_addr) { - /* Setup endpoint 0 */ - buffer_size = packet_size; - - writel(readl(&in_p->endp_cntl) | ENDP_CNTL_CNAK, - &in_p->endp_cntl); - - writel(readl(&out_p->endp_cntl) | ENDP_CNTL_CNAK, - &out_p->endp_cntl); - - writel(ENDP_CNTL_CONTROL | ENDP_CNTL_FLUSH, &in_p->endp_cntl); - - writel(buffer_size / sizeof(int), &in_p->endp_bsorfn); - - writel(packet_size, &in_p->endp_maxpacksize); - - writel(ENDP_CNTL_CONTROL | ENDP_CNTL_RRDY, &out_p->endp_cntl); - - writel(packet_size | ((buffer_size / sizeof(int)) << 16), - &out_p->endp_maxpacksize); - - } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { - /* Setup the IN endpoint */ - writel(0x0, &in_p->endp_status); - writel((ep_type << 4) | ENDP_CNTL_RRDY, &in_p->endp_cntl); - writel(buffer_size / sizeof(int), &in_p->endp_bsorfn); - writel(packet_size, &in_p->endp_maxpacksize); - - if (!strcmp(tt, "cdc_acm")) { - if (ep_type == ENDP_EPTYPE_INT) { - /* Conf no. 1 Interface no. 0 */ - writel((packet_size << 19) | - ENDP_EPDIR_IN | (1 << 7) | - (0 << 11) | (ep_type << 5) | ep_num, - &udc_regs_p->udc_endp_reg[ep_num]); - } else { - /* Conf no. 1 Interface no. 1 */ - writel((packet_size << 19) | - ENDP_EPDIR_IN | (1 << 7) | - (1 << 11) | (ep_type << 5) | ep_num, - &udc_regs_p->udc_endp_reg[ep_num]); - } - } else { - /* Conf no. 1 Interface no. 0 */ - writel((packet_size << 19) | - ENDP_EPDIR_IN | (1 << 7) | - (0 << 11) | (ep_type << 5) | ep_num, - &udc_regs_p->udc_endp_reg[ep_num]); - } - - } else { - /* Setup the OUT endpoint */ - writel(0x0, &out_p->endp_status); - writel((ep_type << 4) | ENDP_CNTL_RRDY, &out_p->endp_cntl); - writel(packet_size | ((buffer_size / sizeof(int)) << 16), - &out_p->endp_maxpacksize); - - if (!strcmp(tt, "cdc_acm")) { - writel((packet_size << 19) | - ENDP_EPDIR_OUT | (1 << 7) | - (1 << 11) | (ep_type << 5) | ep_num, - &udc_regs_p->udc_endp_reg[ep_num]); - } else { - writel((packet_size << 19) | - ENDP_EPDIR_OUT | (1 << 7) | - (0 << 11) | (ep_type << 5) | ep_num, - &udc_regs_p->udc_endp_reg[ep_num]); - } - - } - - endp_intmask = readl(&udc_regs_p->endp_int_mask); - endp_intmask &= ~((1 << ep_num) | 0x10000 << ep_num); - writel(endp_intmask, &udc_regs_p->endp_int_mask); -} - -/* Turn on the USB connection by enabling the pullup resistor */ -void udc_connect(void) -{ - u32 plug_st, dev_cntl; - - dev_cntl = readl(&udc_regs_p->dev_cntl); - dev_cntl |= DEV_CNTL_SOFTDISCONNECT; - writel(dev_cntl, &udc_regs_p->dev_cntl); - - udelay(1000); - - dev_cntl = readl(&udc_regs_p->dev_cntl); - dev_cntl &= ~DEV_CNTL_SOFTDISCONNECT; - writel(dev_cntl, &udc_regs_p->dev_cntl); - - plug_st = readl(&plug_regs_p->plug_state); - plug_st &= ~(PLUG_STATUS_PHY_RESET | PLUG_STATUS_PHY_MODE); - writel(plug_st, &plug_regs_p->plug_state); -} - -/* Turn off the USB connection by disabling the pullup resistor */ -void udc_disconnect(void) -{ - u32 plug_st; - - writel(DEV_CNTL_SOFTDISCONNECT, &udc_regs_p->dev_cntl); - - plug_st = readl(&plug_regs_p->plug_state); - plug_st |= (PLUG_STATUS_PHY_RESET | PLUG_STATUS_PHY_MODE); - writel(plug_st, &plug_regs_p->plug_state); -} - -/* Switch on the UDC */ -void udc_enable(struct usb_device_instance *device) -{ - UDCDBGA("enable device %p, status %d", device, device->status); - - /* Save the device structure pointer */ - udc_device = device; - - /* Setup ep0 urb */ - if (!ep0_urb) { - ep0_urb = - usbd_alloc_urb(udc_device, udc_device->bus->endpoint_array); - } else { - serial_printf("udc_enable: ep0_urb already allocated %p\n", - ep0_urb); - } - - writel(DEV_INT_SOF, &udc_regs_p->dev_int_mask); -} - -/** - * udc_startup - allow udc code to do any additional startup - */ -void udc_startup_events(struct usb_device_instance *device) -{ - /* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */ - usbd_device_event_irq(device, DEVICE_INIT, 0); - - /* - * The DEVICE_CREATE event puts the USB device in the state - * STATE_ATTACHED. - */ - usbd_device_event_irq(device, DEVICE_CREATE, 0); - - /* - * Some USB controller driver implementations signal - * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here. - * DEVICE_HUB_CONFIGURED causes a transition to the state STATE_POWERED, - * and DEVICE_RESET causes a transition to the state STATE_DEFAULT. - * The DW USB client controller has the capability to detect when the - * USB cable is connected to a powered USB bus, so we will defer the - * DEVICE_HUB_CONFIGURED and DEVICE_RESET events until later. - */ - - udc_enable(device); -} - -/* - * Plug detection interrupt handling - */ -static void dw_udc_plug_irq(void) -{ - if (readl(&plug_regs_p->plug_state) & PLUG_STATUS_ATTACHED) { - /* - * USB cable attached - * Turn off PHY reset bit (PLUG detect). - * Switch PHY opmode to normal operation (PLUG detect). - */ - udc_connect(); - writel(DEV_INT_SOF, &udc_regs_p->dev_int_mask); - - UDCDBG("device attached and powered"); - udc_state_transition(udc_device->device_state, STATE_POWERED); - } else { - writel(~0x0, &udc_regs_p->dev_int_mask); - - UDCDBG("device detached or unpowered"); - udc_state_transition(udc_device->device_state, STATE_ATTACHED); - } -} - -/* - * Device interrupt handling - */ -static void dw_udc_dev_irq(void) -{ - if (readl(&udc_regs_p->dev_int) & DEV_INT_USBRESET) { - writel(~0x0, &udc_regs_p->endp_int_mask); - - writel(readl(&inep_regs_p[0].endp_cntl) | ENDP_CNTL_FLUSH, - &inep_regs_p[0].endp_cntl); - - writel(DEV_INT_USBRESET, &udc_regs_p->dev_int); - - /* - * This endpoint0 specific register can be programmed only - * after the phy clock is initialized - */ - writel((EP0_MAX_PACKET_SIZE << 19) | ENDP_EPTYPE_CNTL, - &udc_regs_p->udc_endp_reg[0]); - - UDCDBG("device reset in progess"); - udc_state_transition(udc_device->device_state, STATE_DEFAULT); - } - - /* Device Enumeration completed */ - if (readl(&udc_regs_p->dev_int) & DEV_INT_ENUM) { - writel(DEV_INT_ENUM, &udc_regs_p->dev_int); - - /* Endpoint interrupt enabled for Ctrl IN & Ctrl OUT */ - writel(readl(&udc_regs_p->endp_int_mask) & ~0x10001, - &udc_regs_p->endp_int_mask); - - UDCDBG("default -> addressed"); - udc_state_transition(udc_device->device_state, STATE_ADDRESSED); - } - - /* The USB will be in SUSPEND in 3 ms */ - if (readl(&udc_regs_p->dev_int) & DEV_INT_INACTIVE) { - writel(DEV_INT_INACTIVE, &udc_regs_p->dev_int); - - UDCDBG("entering inactive state"); - /* usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0); */ - } - - /* SetConfiguration command received */ - if (readl(&udc_regs_p->dev_int) & DEV_INT_SETCFG) { - writel(DEV_INT_SETCFG, &udc_regs_p->dev_int); - - UDCDBG("entering configured state"); - udc_state_transition(udc_device->device_state, - STATE_CONFIGURED); - } - - /* SetInterface command received */ - if (readl(&udc_regs_p->dev_int) & DEV_INT_SETINTF) - writel(DEV_INT_SETINTF, &udc_regs_p->dev_int); - - /* USB Suspend detected on cable */ - if (readl(&udc_regs_p->dev_int) & DEV_INT_SUSPUSB) { - writel(DEV_INT_SUSPUSB, &udc_regs_p->dev_int); - - UDCDBG("entering suspended state"); - usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0); - } - - /* USB Start-Of-Frame detected on cable */ - if (readl(&udc_regs_p->dev_int) & DEV_INT_SOF) - writel(DEV_INT_SOF, &udc_regs_p->dev_int); -} - -/* - * Endpoint interrupt handling - */ -static void dw_udc_endpoint_irq(void) -{ - while (readl(&udc_regs_p->endp_int) & ENDP0_INT_CTRLOUT) { - - writel(ENDP0_INT_CTRLOUT, &udc_regs_p->endp_int); - - if ((readl(&outep_regs_p[0].endp_status) & ENDP_STATUS_OUTMSK) - == ENDP_STATUS_OUT_SETUP) { - dw_udc_setup(udc_device->bus->endpoint_array + 0); - writel(ENDP_STATUS_OUT_SETUP, - &outep_regs_p[0].endp_status); - - } else if ((readl(&outep_regs_p[0].endp_status) & - ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_DATA) { - dw_udc_ep0_rx(udc_device->bus->endpoint_array + 0); - writel(ENDP_STATUS_OUT_DATA, - &outep_regs_p[0].endp_status); - - } else if ((readl(&outep_regs_p[0].endp_status) & - ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_NONE) { - /* NONE received */ - } - - writel(0x0, &outep_regs_p[0].endp_status); - } - - if (readl(&udc_regs_p->endp_int) & ENDP0_INT_CTRLIN) { - dw_udc_ep0_tx(udc_device->bus->endpoint_array + 0); - - writel(ENDP_STATUS_IN, &inep_regs_p[0].endp_status); - writel(ENDP0_INT_CTRLIN, &udc_regs_p->endp_int); - } - - if (readl(&udc_regs_p->endp_int) & ENDP_INT_NONISOOUT_MSK) { - u32 epnum = 0; - u32 ep_int = readl(&udc_regs_p->endp_int) & - ENDP_INT_NONISOOUT_MSK; - - ep_int >>= 16; - while (0x0 == (ep_int & 0x1)) { - ep_int >>= 1; - epnum++; - } - - writel((1 << 16) << epnum, &udc_regs_p->endp_int); - - if ((readl(&outep_regs_p[epnum].endp_status) & - ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_DATA) { - - dw_udc_epn_rx(epnum); - writel(ENDP_STATUS_OUT_DATA, - &outep_regs_p[epnum].endp_status); - } else if ((readl(&outep_regs_p[epnum].endp_status) & - ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_NONE) { - writel(0x0, &outep_regs_p[epnum].endp_status); - } - } - - if (readl(&udc_regs_p->endp_int) & ENDP_INT_NONISOIN_MSK) { - u32 epnum = 0; - u32 ep_int = readl(&udc_regs_p->endp_int) & - ENDP_INT_NONISOIN_MSK; - - while (0x0 == (ep_int & 0x1)) { - ep_int >>= 1; - epnum++; - } - - if (readl(&inep_regs_p[epnum].endp_status) & ENDP_STATUS_IN) { - writel(ENDP_STATUS_IN, - &outep_regs_p[epnum].endp_status); - dw_udc_epn_tx(epnum); - - writel(ENDP_STATUS_IN, - &outep_regs_p[epnum].endp_status); - } - - writel((1 << epnum), &udc_regs_p->endp_int); - } -} - -/* - * UDC interrupts - */ -void udc_irq(void) -{ - /* - * Loop while we have interrupts. - * If we don't do this, the input chain - * polling delay is likely to miss - * host requests. - */ - while (readl(&plug_regs_p->plug_pending)) - dw_udc_plug_irq(); - - while (readl(&udc_regs_p->dev_int)) - dw_udc_dev_irq(); - - if (readl(&udc_regs_p->endp_int)) - dw_udc_endpoint_irq(); -} - -/* Flow control */ -void udc_set_nak(int epid) -{ - writel(readl(&inep_regs_p[epid].endp_cntl) | ENDP_CNTL_SNAK, - &inep_regs_p[epid].endp_cntl); - - writel(readl(&outep_regs_p[epid].endp_cntl) | ENDP_CNTL_SNAK, - &outep_regs_p[epid].endp_cntl); -} - -void udc_unset_nak(int epid) -{ - u32 val; - - val = readl(&inep_regs_p[epid].endp_cntl); - val &= ~ENDP_CNTL_SNAK; - val |= ENDP_CNTL_CNAK; - writel(val, &inep_regs_p[epid].endp_cntl); - - val = readl(&outep_regs_p[epid].endp_cntl); - val &= ~ENDP_CNTL_SNAK; - val |= ENDP_CNTL_CNAK; - writel(val, &outep_regs_p[epid].endp_cntl); -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/ep0.c b/qemu/roms/u-boot/drivers/usb/gadget/ep0.c deleted file mode 100644 index b3214882f..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/ep0.c +++ /dev/null @@ -1,597 +0,0 @@ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * (C) Copyright 2006 - * Bryan O'Donoghue, deckard@CodeHermit.ie - * - * Based on - * linux/drivers/usbd/ep0.c - * - * Copyright (c) 2000, 2001, 2002 Lineo - * Copyright (c) 2001 Hewlett Packard - * - * By: - * Stuart Lynne <sl@lineo.com>, - * Tom Rushworth <tbr@lineo.com>, - * Bruce Balden <balden@lineo.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * This is the builtin ep0 control function. It implements all required functionality - * for responding to control requests (SETUP packets). - * - * XXX - * - * Currently we do not pass any SETUP packets (or other) to the configured - * function driver. This may need to change. - * - * XXX - * - * As alluded to above, a simple callback cdc_recv_setup has been implemented - * in the usb_device data structure to facilicate passing - * Common Device Class packets to a function driver. - * - * XXX - */ - -#include <common.h> -#include <usbdevice.h> - -#if 0 -#define dbg_ep0(lvl,fmt,args...) serial_printf("[%s] %s:%d: "fmt"\n",__FILE__,__FUNCTION__,__LINE__,##args) -#else -#define dbg_ep0(lvl,fmt,args...) -#endif - -/* EP0 Configuration Set ********************************************************************* */ - - -/** - * ep0_get_status - fill in URB data with appropriate status - * @device: - * @urb: - * @index: - * @requesttype: - * - */ -static int ep0_get_status (struct usb_device_instance *device, - struct urb *urb, int index, int requesttype) -{ - char *cp; - - urb->actual_length = 2; - cp = (char*)urb->buffer; - cp[0] = cp[1] = 0; - - switch (requesttype) { - case USB_REQ_RECIPIENT_DEVICE: - cp[0] = USB_STATUS_SELFPOWERED; - break; - case USB_REQ_RECIPIENT_INTERFACE: - break; - case USB_REQ_RECIPIENT_ENDPOINT: - cp[0] = usbd_endpoint_halted (device, index); - break; - case USB_REQ_RECIPIENT_OTHER: - urb->actual_length = 0; - default: - break; - } - dbg_ep0 (2, "%02x %02x", cp[0], cp[1]); - return 0; -} - -/** - * ep0_get_one - * @device: - * @urb: - * @result: - * - * Set a single byte value in the urb send buffer. Return non-zero to signal - * a request error. - */ -static int ep0_get_one (struct usb_device_instance *device, struct urb *urb, - __u8 result) -{ - urb->actual_length = 1; /* XXX 2? */ - ((char *) urb->buffer)[0] = result; - return 0; -} - -/** - * copy_config - * @urb: pointer to urb - * @data: pointer to configuration data - * @length: length of data - * - * Copy configuration data to urb transfer buffer if there is room for it. - */ -void copy_config (struct urb *urb, void *data, int max_length, - int max_buf) -{ - int available; - int length; - - /*dbg_ep0(3, "-> actual: %d buf: %d max_buf: %d max_length: %d data: %p", */ - /* urb->actual_length, urb->buffer_length, max_buf, max_length, data); */ - - if (!data) { - dbg_ep0 (1, "data is NULL"); - return; - } - length = max_length; - - if (length > max_length) { - dbg_ep0 (1, "length: %d >= max_length: %d", length, - max_length); - return; - } - /*dbg_ep0(1, " actual: %d buf: %d max_buf: %d max_length: %d length: %d", */ - /* urb->actual_length, urb->buffer_length, max_buf, max_length, length); */ - - if ((available = - /*urb->buffer_length */ max_buf - urb->actual_length) <= 0) { - return; - } - /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */ - /* urb->actual_length, urb->buffer_length, max_buf, length, available); */ - - if (length > available) { - length = available; - } - /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */ - /* urb->actual_length, urb->buffer_length, max_buf, length, available); */ - - memcpy (urb->buffer + urb->actual_length, data, length); - urb->actual_length += length; - - dbg_ep0 (3, - "copy_config: <- actual: %d buf: %d max_buf: %d max_length: %d available: %d", - urb->actual_length, urb->buffer_length, max_buf, max_length, - available); -} - -/** - * ep0_get_descriptor - * @device: - * @urb: - * @max: - * @descriptor_type: - * @index: - * - * Called by ep0_rx_process for a get descriptor device command. Determine what - * descriptor is being requested, copy to send buffer. Return zero if ok to send, - * return non-zero to signal a request error. - */ -static int ep0_get_descriptor (struct usb_device_instance *device, - struct urb *urb, int max, int descriptor_type, - int index) -{ - int port = 0; /* XXX compound device */ - - /*dbg_ep0(3, "max: %x type: %x index: %x", max, descriptor_type, index); */ - - if (!urb || !urb->buffer || !urb->buffer_length - || (urb->buffer_length < 255)) { - dbg_ep0 (2, "invalid urb %p", urb); - return -1L; - } - - /* setup tx urb */ - urb->actual_length = 0; - - dbg_ep0 (2, "%s", USBD_DEVICE_DESCRIPTORS (descriptor_type)); - - switch (descriptor_type) { - case USB_DESCRIPTOR_TYPE_DEVICE: - { - struct usb_device_descriptor *device_descriptor; - if (! - (device_descriptor = - usbd_device_device_descriptor (device, port))) { - return -1; - } - /* copy descriptor for this device */ - copy_config (urb, device_descriptor, - sizeof (struct usb_device_descriptor), - max); - - /* correct the correct control endpoint 0 max packet size into the descriptor */ - device_descriptor = - (struct usb_device_descriptor *) urb->buffer; - - } - dbg_ep0(3, "copied device configuration, actual_length: 0x%x", urb->actual_length); - break; - - case USB_DESCRIPTOR_TYPE_CONFIGURATION: - { - struct usb_configuration_descriptor - *configuration_descriptor; - struct usb_device_descriptor *device_descriptor; - if (! - (device_descriptor = - usbd_device_device_descriptor (device, port))) { - return -1; - } - /*dbg_ep0(2, "%d %d", index, device_descriptor->bNumConfigurations); */ - if (index >= device_descriptor->bNumConfigurations) { - dbg_ep0 (0, "index too large: %d >= %d", index, - device_descriptor-> - bNumConfigurations); - return -1; - } - - if (! - (configuration_descriptor = - usbd_device_configuration_descriptor (device, - port, - index))) { - dbg_ep0 (0, - "usbd_device_configuration_descriptor failed: %d", - index); - return -1; - } - dbg_ep0(0, "attempt to copy %d bytes to urb\n",cpu_to_le16(configuration_descriptor->wTotalLength)); - copy_config (urb, configuration_descriptor, - - cpu_to_le16(configuration_descriptor->wTotalLength), - max); - } - - break; - - case USB_DESCRIPTOR_TYPE_STRING: - { - struct usb_string_descriptor *string_descriptor; - if (!(string_descriptor = usbd_get_string (index))) { - serial_printf("Invalid string index %d\n", index); - return -1; - } - dbg_ep0(3, "string_descriptor: %p length %d", string_descriptor, string_descriptor->bLength); - copy_config (urb, string_descriptor, string_descriptor->bLength, max); - } - break; - case USB_DESCRIPTOR_TYPE_INTERFACE: - serial_printf("USB_DESCRIPTOR_TYPE_INTERFACE - error not implemented\n"); - return -1; - case USB_DESCRIPTOR_TYPE_ENDPOINT: - serial_printf("USB_DESCRIPTOR_TYPE_ENDPOINT - error not implemented\n"); - return -1; - case USB_DESCRIPTOR_TYPE_HID: - { - serial_printf("USB_DESCRIPTOR_TYPE_HID - error not implemented\n"); - return -1; /* unsupported at this time */ -#if 0 - int bNumInterface = - le16_to_cpu (urb->device_request.wIndex); - int bAlternateSetting = 0; - int class = 0; - struct usb_class_descriptor *class_descriptor; - - if (!(class_descriptor = - usbd_device_class_descriptor_index (device, - port, 0, - bNumInterface, - bAlternateSetting, - class)) - || class_descriptor->descriptor.hid.bDescriptorType != USB_DT_HID) { - dbg_ep0 (3, "[%d] interface is not HID", - bNumInterface); - return -1; - } - /* copy descriptor for this class */ - copy_config (urb, class_descriptor, - class_descriptor->descriptor.hid.bLength, - max); -#endif - } - break; - case USB_DESCRIPTOR_TYPE_REPORT: - { - serial_printf("USB_DESCRIPTOR_TYPE_REPORT - error not implemented\n"); - return -1; /* unsupported at this time */ -#if 0 - int bNumInterface = - le16_to_cpu (urb->device_request.wIndex); - int bAlternateSetting = 0; - int class = 0; - struct usb_class_report_descriptor *report_descriptor; - - if (!(report_descriptor = - usbd_device_class_report_descriptor_index - (device, port, 0, bNumInterface, - bAlternateSetting, class)) - || report_descriptor->bDescriptorType != - USB_DT_REPORT) { - dbg_ep0 (3, "[%d] descriptor is not REPORT", - bNumInterface); - return -1; - } - /* copy report descriptor for this class */ - /*copy_config(urb, &report_descriptor->bData[0], report_descriptor->wLength, max); */ - if (max - urb->actual_length > 0) { - int length = - MIN (report_descriptor->wLength, - max - urb->actual_length); - memcpy (urb->buffer + urb->actual_length, - &report_descriptor->bData[0], length); - urb->actual_length += length; - } -#endif - } - break; - case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: -#if defined(CONFIG_USBD_HS) - { - struct usb_qualifier_descriptor *qualifier_descriptor = - device->qualifier_descriptor; - - if (!qualifier_descriptor) - return -1; - - /* copy descriptor for this device */ - copy_config(urb, qualifier_descriptor, - sizeof(struct usb_qualifier_descriptor), - max); - - } - dbg_ep0(3, "copied qualifier descriptor, actual_length: 0x%x", - urb->actual_length); -#else - return -1; -#endif - break; - - default: - return -1; - } - - - dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d tx_packetSize: %2d", - urb->buffer, urb->buffer_length, urb->actual_length, - device->bus->endpoint_array[0].tx_packetSize); -/* - if ((urb->actual_length < max) && !(urb->actual_length % device->bus->endpoint_array[0].tx_packetSize)) { - dbg_ep0(0, "adding null byte"); - urb->buffer[urb->actual_length++] = 0; - dbg_ep0(0, "urb: buffer_length: %2d actual_length: %2d packet size: %2d", - urb->buffer_length, urb->actual_length device->bus->endpoint_array[0].tx_packetSize); - } -*/ - return 0; - -} - -/** - * ep0_recv_setup - called to indicate URB has been received - * @urb: pointer to struct urb - * - * Check if this is a setup packet, process the device request, put results - * back into the urb and return zero or non-zero to indicate success (DATA) - * or failure (STALL). - * - */ -int ep0_recv_setup (struct urb *urb) -{ - /*struct usb_device_request *request = urb->buffer; */ - /*struct usb_device_instance *device = urb->device; */ - - struct usb_device_request *request; - struct usb_device_instance *device; - int address; - - dbg_ep0 (0, "entering ep0_recv_setup()"); - if (!urb || !urb->device) { - dbg_ep0 (3, "invalid URB %p", urb); - return -1; - } - - request = &urb->device_request; - device = urb->device; - - dbg_ep0 (3, "urb: %p device: %p", urb, urb->device); - - - /*dbg_ep0(2, "- - - - - - - - - -"); */ - - dbg_ep0 (2, - "bmRequestType:%02x bRequest:%02x wValue:%04x wIndex:%04x wLength:%04x %s", - request->bmRequestType, request->bRequest, - le16_to_cpu (request->wValue), le16_to_cpu (request->wIndex), - le16_to_cpu (request->wLength), - USBD_DEVICE_REQUESTS (request->bRequest)); - - /* handle USB Standard Request (c.f. USB Spec table 9-2) */ - if ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0) { - if(device->device_state <= STATE_CONFIGURED){ - /* Attempt to handle a CDC specific request if we are - * in the configured state. - */ - return device->cdc_recv_setup(request,urb); - } - dbg_ep0 (1, "non standard request: %x", - request->bmRequestType & USB_REQ_TYPE_MASK); - return -1; /* Stall here */ - } - - switch (device->device_state) { - case STATE_CREATED: - case STATE_ATTACHED: - case STATE_POWERED: - /* It actually is important to allow requests in these states, - * Windows will request descriptors before assigning an - * address to the client. - */ - - /*dbg_ep0 (1, "request %s not allowed in this state: %s", */ - /* USBD_DEVICE_REQUESTS(request->bRequest), */ - /* usbd_device_states[device->device_state]); */ - /*return -1; */ - break; - - case STATE_INIT: - case STATE_DEFAULT: - switch (request->bRequest) { - case USB_REQ_GET_STATUS: - case USB_REQ_GET_INTERFACE: - case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ - case USB_REQ_CLEAR_FEATURE: - case USB_REQ_SET_FEATURE: - case USB_REQ_SET_DESCRIPTOR: - /* case USB_REQ_SET_CONFIGURATION: */ - case USB_REQ_SET_INTERFACE: - dbg_ep0 (1, - "request %s not allowed in DEFAULT state: %s", - USBD_DEVICE_REQUESTS (request->bRequest), - usbd_device_states[device->device_state]); - return -1; - - case USB_REQ_SET_CONFIGURATION: - case USB_REQ_SET_ADDRESS: - case USB_REQ_GET_DESCRIPTOR: - case USB_REQ_GET_CONFIGURATION: - break; - } - case STATE_ADDRESSED: - case STATE_CONFIGURED: - break; - case STATE_UNKNOWN: - dbg_ep0 (1, "request %s not allowed in UNKNOWN state: %s", - USBD_DEVICE_REQUESTS (request->bRequest), - usbd_device_states[device->device_state]); - return -1; - } - - /* handle all requests that return data (direction bit set on bm RequestType) */ - if ((request->bmRequestType & USB_REQ_DIRECTION_MASK)) { - - dbg_ep0 (3, "Device-to-Host"); - - switch (request->bRequest) { - - case USB_REQ_GET_STATUS: - return ep0_get_status (device, urb, request->wIndex, - request->bmRequestType & - USB_REQ_RECIPIENT_MASK); - - case USB_REQ_GET_DESCRIPTOR: - return ep0_get_descriptor (device, urb, - le16_to_cpu (request->wLength), - le16_to_cpu (request->wValue) >> 8, - le16_to_cpu (request->wValue) & 0xff); - - case USB_REQ_GET_CONFIGURATION: - serial_printf("get config %d\n", device->configuration); - return ep0_get_one (device, urb, - device->configuration); - - case USB_REQ_GET_INTERFACE: - return ep0_get_one (device, urb, device->alternate); - - case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ - return -1; - - case USB_REQ_CLEAR_FEATURE: - case USB_REQ_SET_FEATURE: - case USB_REQ_SET_ADDRESS: - case USB_REQ_SET_DESCRIPTOR: - case USB_REQ_SET_CONFIGURATION: - case USB_REQ_SET_INTERFACE: - return -1; - } - } - /* handle the requests that do not return data */ - else { - - - /*dbg_ep0(3, "Host-to-Device"); */ - switch (request->bRequest) { - - case USB_REQ_CLEAR_FEATURE: - case USB_REQ_SET_FEATURE: - dbg_ep0 (0, "Host-to-Device"); - switch (request-> - bmRequestType & USB_REQ_RECIPIENT_MASK) { - case USB_REQ_RECIPIENT_DEVICE: - /* XXX DEVICE_REMOTE_WAKEUP or TEST_MODE would be added here */ - /* XXX fall through for now as we do not support either */ - case USB_REQ_RECIPIENT_INTERFACE: - case USB_REQ_RECIPIENT_OTHER: - dbg_ep0 (0, "request %s not", - USBD_DEVICE_REQUESTS (request->bRequest)); - default: - return -1; - - case USB_REQ_RECIPIENT_ENDPOINT: - dbg_ep0 (0, "ENDPOINT: %x", le16_to_cpu (request->wValue)); - if (le16_to_cpu (request->wValue) == USB_ENDPOINT_HALT) { - /*return usbd_device_feature (device, le16_to_cpu (request->wIndex), */ - /* request->bRequest == USB_REQ_SET_FEATURE); */ - /* NEED TO IMPLEMENT THIS!!! */ - return -1; - } else { - dbg_ep0 (1, "request %s bad wValue: %04x", - USBD_DEVICE_REQUESTS - (request->bRequest), - le16_to_cpu (request->wValue)); - return -1; - } - } - - case USB_REQ_SET_ADDRESS: - /* check if this is a re-address, reset first if it is (this shouldn't be possible) */ - if (device->device_state != STATE_DEFAULT) { - dbg_ep0 (1, "set_address: %02x state: %s", - le16_to_cpu (request->wValue), - usbd_device_states[device->device_state]); - return -1; - } - address = le16_to_cpu (request->wValue); - if ((address & 0x7f) != address) { - dbg_ep0 (1, "invalid address %04x %04x", - address, address & 0x7f); - return -1; - } - device->address = address; - - /*dbg_ep0(2, "address: %d %d %d", */ - /* request->wValue, le16_to_cpu(request->wValue), device->address); */ - - return 0; - - case USB_REQ_SET_DESCRIPTOR: /* XXX should we support this? */ - dbg_ep0 (0, "set descriptor: NOT SUPPORTED"); - return -1; - - case USB_REQ_SET_CONFIGURATION: - /* c.f. 9.4.7 - the top half of wValue is reserved */ - device->configuration = le16_to_cpu(request->wValue) & 0xff; - - /* reset interface and alternate settings */ - device->interface = device->alternate = 0; - - /*dbg_ep0(2, "set configuration: %d", device->configuration); */ - /*serial_printf("DEVICE_CONFIGURED.. event?\n"); */ - return 0; - - case USB_REQ_SET_INTERFACE: - device->interface = le16_to_cpu (request->wIndex); - device->alternate = le16_to_cpu (request->wValue); - /*dbg_ep0(2, "set interface: %d alternate: %d", device->interface, device->alternate); */ - serial_printf ("DEVICE_SET_INTERFACE.. event?\n"); - return 0; - - case USB_REQ_GET_STATUS: - case USB_REQ_GET_DESCRIPTOR: - case USB_REQ_GET_CONFIGURATION: - case USB_REQ_GET_INTERFACE: - case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ - return -1; - } - } - return -1; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/ep0.h b/qemu/roms/u-boot/drivers/usb/gadget/ep0.h deleted file mode 100644 index 6042e7562..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/ep0.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * Based on - * linux/drivers/usbd/ep0.c - * - * Copyright (c) 2000, 2001, 2002 Lineo - * Copyright (c) 2001 Hewlett Packard - * - * By: - * Stuart Lynne <sl@lineo.com>, - * Tom Rushworth <tbr@lineo.com>, - * Bruce Balden <balden@lineo.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __USBDCORE_EP0_H__ -#define __USBDCORE_EP0_H__ - - -int ep0_recv_setup (struct urb *urb); - - -#endif diff --git a/qemu/roms/u-boot/drivers/usb/gadget/epautoconf.c b/qemu/roms/u-boot/drivers/usb/gadget/epautoconf.c deleted file mode 100644 index 0df4b2a10..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/epautoconf.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers - * - * Copyright (C) 2004 David Brownell - * - * SPDX-License-Identifier: GPL-2.0+ - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and - * Remy Bohmer <linux@bohmer.net> - */ - -#include <common.h> -#include <linux/usb/ch9.h> -#include <asm/errno.h> -#include <linux/usb/gadget.h> -#include <asm/unaligned.h> -#include "gadget_chips.h" - -#define isdigit(c) ('0' <= (c) && (c) <= '9') - -/* we must assign addresses for configurable endpoints (like net2280) */ -static unsigned epnum; - -/* #define MANY_ENDPOINTS */ -#ifdef MANY_ENDPOINTS -/* more than 15 configurable endpoints */ -static unsigned in_epnum; -#endif - - -/* - * This should work with endpoints from controller drivers sharing the - * same endpoint naming convention. By example: - * - * - ep1, ep2, ... address is fixed, not direction or type - * - ep1in, ep2out, ... address and direction are fixed, not type - * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction - * - ep1in-bulk, ep2out-iso, ... all three are fixed - * - ep-* ... no functionality restrictions - * - * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal. - * Less common restrictions are implied by gadget_is_*(). - * - * NOTE: each endpoint is unidirectional, as specified by its USB - * descriptor; and isn't specific to a configuration or altsetting. - */ -static int ep_matches( - struct usb_gadget *gadget, - struct usb_ep *ep, - struct usb_endpoint_descriptor *desc -) -{ - u8 type; - const char *tmp; - u16 max; - - /* endpoint already claimed? */ - if (NULL != ep->driver_data) - return 0; - - /* only support ep0 for portable CONTROL traffic */ - type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - if (USB_ENDPOINT_XFER_CONTROL == type) - return 0; - - /* some other naming convention */ - if ('e' != ep->name[0]) - return 0; - - /* type-restriction: "-iso", "-bulk", or "-int". - * direction-restriction: "in", "out". - */ - if ('-' != ep->name[2]) { - tmp = strrchr(ep->name, '-'); - if (tmp) { - switch (type) { - case USB_ENDPOINT_XFER_INT: - /* bulk endpoints handle interrupt transfers, - * except the toggle-quirky iso-synch kind - */ - if ('s' == tmp[2]) /* == "-iso" */ - return 0; - /* for now, avoid PXA "interrupt-in"; - * it's documented as never using DATA1. - */ - if (gadget_is_pxa(gadget) - && 'i' == tmp[1]) - return 0; - break; - case USB_ENDPOINT_XFER_BULK: - if ('b' != tmp[1]) /* != "-bulk" */ - return 0; - break; - case USB_ENDPOINT_XFER_ISOC: - if ('s' != tmp[2]) /* != "-iso" */ - return 0; - } - } else { - tmp = ep->name + strlen(ep->name); - } - - /* direction-restriction: "..in-..", "out-.." */ - tmp--; - if (!isdigit(*tmp)) { - if (desc->bEndpointAddress & USB_DIR_IN) { - if ('n' != *tmp) - return 0; - } else { - if ('t' != *tmp) - return 0; - } - } - } - - /* endpoint maxpacket size is an input parameter, except for bulk - * where it's an output parameter representing the full speed limit. - * the usb spec fixes high speed bulk maxpacket at 512 bytes. - */ - max = 0x7ff & le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)); - switch (type) { - case USB_ENDPOINT_XFER_INT: - /* INT: limit 64 bytes full speed, 1024 high speed */ - if (!gadget->is_dualspeed && max > 64) - return 0; - /* FALLTHROUGH */ - - case USB_ENDPOINT_XFER_ISOC: - /* ISO: limit 1023 bytes full speed, 1024 high speed */ - if (ep->maxpacket < max) - return 0; - if (!gadget->is_dualspeed && max > 1023) - return 0; - - /* BOTH: "high bandwidth" works only at high speed */ - if ((get_unaligned(&desc->wMaxPacketSize) & - __constant_cpu_to_le16(3<<11))) { - if (!gadget->is_dualspeed) - return 0; - /* configure your hardware with enough buffering!! */ - } - break; - } - - /* MATCH!! */ - - /* report address */ - if (isdigit(ep->name[2])) { - u8 num = simple_strtoul(&ep->name[2], NULL, 10); - desc->bEndpointAddress |= num; -#ifdef MANY_ENDPOINTS - } else if (desc->bEndpointAddress & USB_DIR_IN) { - if (++in_epnum > 15) - return 0; - desc->bEndpointAddress = USB_DIR_IN | in_epnum; -#endif - } else { - if (++epnum > 15) - return 0; - desc->bEndpointAddress |= epnum; - } - - /* report (variable) full speed bulk maxpacket */ - if (USB_ENDPOINT_XFER_BULK == type) { - int size = ep->maxpacket; - - /* min() doesn't work on bitfields with gcc-3.5 */ - if (size > 64) - size = 64; - put_unaligned(cpu_to_le16(size), &desc->wMaxPacketSize); - } - return 1; -} - -static struct usb_ep * -find_ep(struct usb_gadget *gadget, const char *name) -{ - struct usb_ep *ep; - - list_for_each_entry(ep, &gadget->ep_list, ep_list) { - if (0 == strcmp(ep->name, name)) - return ep; - } - return NULL; -} - -/** - * usb_ep_autoconfig - choose an endpoint matching the descriptor - * @gadget: The device to which the endpoint must belong. - * @desc: Endpoint descriptor, with endpoint direction and transfer mode - * initialized. For periodic transfers, the maximum packet - * size must also be initialized. This is modified on success. - * - * By choosing an endpoint to use with the specified descriptor, this - * routine simplifies writing gadget drivers that work with multiple - * USB device controllers. The endpoint would be passed later to - * usb_ep_enable(), along with some descriptor. - * - * That second descriptor won't always be the same as the first one. - * For example, isochronous endpoints can be autoconfigured for high - * bandwidth, and then used in several lower bandwidth altsettings. - * Also, high and full speed descriptors will be different. - * - * Be sure to examine and test the results of autoconfiguration on your - * hardware. This code may not make the best choices about how to use the - * USB controller, and it can't know all the restrictions that may apply. - * Some combinations of driver and hardware won't be able to autoconfigure. - * - * On success, this returns an un-claimed usb_ep, and modifies the endpoint - * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value - * is initialized as if the endpoint were used at full speed. To prevent - * the endpoint from being returned by a later autoconfig call, claim it - * by assigning ep->driver_data to some non-null value. - * - * On failure, this returns a null endpoint descriptor. - */ -struct usb_ep *usb_ep_autoconfig( - struct usb_gadget *gadget, - struct usb_endpoint_descriptor *desc -) -{ - struct usb_ep *ep; - u8 type; - - type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - - /* First, apply chip-specific "best usage" knowledge. - * This might make a good usb_gadget_ops hook ... - */ - if (gadget_is_net2280(gadget) && type == USB_ENDPOINT_XFER_INT) { - /* ep-e, ep-f are PIO with only 64 byte fifos */ - ep = find_ep(gadget, "ep-e"); - if (ep && ep_matches(gadget, ep, desc)) - return ep; - ep = find_ep(gadget, "ep-f"); - if (ep && ep_matches(gadget, ep, desc)) - return ep; - - } else if (gadget_is_goku(gadget)) { - if (USB_ENDPOINT_XFER_INT == type) { - /* single buffering is enough */ - ep = find_ep(gadget, "ep3-bulk"); - if (ep && ep_matches(gadget, ep, desc)) - return ep; - } else if (USB_ENDPOINT_XFER_BULK == type - && (USB_DIR_IN & desc->bEndpointAddress)) { - /* DMA may be available */ - ep = find_ep(gadget, "ep2-bulk"); - if (ep && ep_matches(gadget, ep, desc)) - return ep; - } - - } else if (gadget_is_sh(gadget) && USB_ENDPOINT_XFER_INT == type) { - /* single buffering is enough; maybe 8 byte fifo is too */ - ep = find_ep(gadget, "ep3in-bulk"); - if (ep && ep_matches(gadget, ep, desc)) - return ep; - - } else if (gadget_is_mq11xx(gadget) && USB_ENDPOINT_XFER_INT == type) { - ep = find_ep(gadget, "ep1-bulk"); - if (ep && ep_matches(gadget, ep, desc)) - return ep; - } - - /* Second, look at endpoints until an unclaimed one looks usable */ - list_for_each_entry(ep, &gadget->ep_list, ep_list) { - if (ep_matches(gadget, ep, desc)) - return ep; - } - - /* Fail */ - return NULL; -} - -/** - * usb_ep_autoconfig_reset - reset endpoint autoconfig state - * @gadget: device for which autoconfig state will be reset - * - * Use this for devices where one configuration may need to assign - * endpoint resources very differently from the next one. It clears - * state such as ep->driver_data and the record of assigned endpoints - * used by usb_ep_autoconfig(). - */ -void usb_ep_autoconfig_reset(struct usb_gadget *gadget) -{ - struct usb_ep *ep; - - list_for_each_entry(ep, &gadget->ep_list, ep_list) { - ep->driver_data = NULL; - } -#ifdef MANY_ENDPOINTS - in_epnum = 0; -#endif - epnum = 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/ether.c b/qemu/roms/u-boot/drivers/usb/gadget/ether.c deleted file mode 100644 index cc6cc1f32..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/ether.c +++ /dev/null @@ -1,2555 +0,0 @@ -/* - * ether.c -- Ethernet gadget driver, with CDC and non-CDC options - * - * Copyright (C) 2003-2005,2008 David Brownell - * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger - * Copyright (C) 2008 Nokia Corporation - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/errno.h> -#include <linux/netdevice.h> -#include <linux/usb/ch9.h> -#include <linux/usb/cdc.h> -#include <linux/usb/gadget.h> -#include <net.h> -#include <malloc.h> -#include <linux/ctype.h> - -#include "gadget_chips.h" -#include "rndis.h" - -#define USB_NET_NAME "usb_ether" - -#define atomic_read -extern struct platform_data brd; -#define spin_lock(x) -#define spin_unlock(x) - - -unsigned packet_received, packet_sent; - -#define GFP_ATOMIC ((gfp_t) 0) -#define GFP_KERNEL ((gfp_t) 0) - -/* - * Ethernet gadget driver -- with CDC and non-CDC options - * Builds on hardware support for a full duplex link. - * - * CDC Ethernet is the standard USB solution for sending Ethernet frames - * using USB. Real hardware tends to use the same framing protocol but look - * different for control features. This driver strongly prefers to use - * this USB-IF standard as its open-systems interoperability solution; - * most host side USB stacks (except from Microsoft) support it. - * - * This is sometimes called "CDC ECM" (Ethernet Control Model) to support - * TLA-soup. "CDC ACM" (Abstract Control Model) is for modems, and a new - * "CDC EEM" (Ethernet Emulation Model) is starting to spread. - * - * There's some hardware that can't talk CDC ECM. We make that hardware - * implement a "minimalist" vendor-agnostic CDC core: same framing, but - * link-level setup only requires activating the configuration. Only the - * endpoint descriptors, and product/vendor IDs, are relevant; no control - * operations are available. Linux supports it, but other host operating - * systems may not. (This is a subset of CDC Ethernet.) - * - * It turns out that if you add a few descriptors to that "CDC Subset", - * (Windows) host side drivers from MCCI can treat it as one submode of - * a proprietary scheme called "SAFE" ... without needing to know about - * specific product/vendor IDs. So we do that, making it easier to use - * those MS-Windows drivers. Those added descriptors make it resemble a - * CDC MDLM device, but they don't change device behavior at all. (See - * MCCI Engineering report 950198 "SAFE Networking Functions".) - * - * A third option is also in use. Rather than CDC Ethernet, or something - * simpler, Microsoft pushes their own approach: RNDIS. The published - * RNDIS specs are ambiguous and appear to be incomplete, and are also - * needlessly complex. They borrow more from CDC ACM than CDC ECM. - */ -#define ETH_ALEN 6 /* Octets in one ethernet addr */ -#define ETH_HLEN 14 /* Total octets in header. */ -#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ -#define ETH_DATA_LEN 1500 /* Max. octets in payload */ -#define ETH_FRAME_LEN PKTSIZE_ALIGN /* Max. octets in frame sans FCS */ -#define ETH_FCS_LEN 4 /* Octets in the FCS */ - -#define DRIVER_DESC "Ethernet Gadget" -/* Based on linux 2.6.27 version */ -#define DRIVER_VERSION "May Day 2005" - -static const char shortname[] = "ether"; -static const char driver_desc[] = DRIVER_DESC; - -#define RX_EXTRA 20 /* guard against rx overflows */ - -#ifndef CONFIG_USB_ETH_RNDIS -#define rndis_uninit(x) do {} while (0) -#define rndis_deregister(c) do {} while (0) -#define rndis_exit() do {} while (0) -#endif - -/* CDC and RNDIS support the same host-chosen outgoing packet filters. */ -#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ - |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ - |USB_CDC_PACKET_TYPE_PROMISCUOUS \ - |USB_CDC_PACKET_TYPE_DIRECTED) - -#define USB_CONNECT_TIMEOUT (3 * CONFIG_SYS_HZ) - -/*-------------------------------------------------------------------------*/ - -struct eth_dev { - struct usb_gadget *gadget; - struct usb_request *req; /* for control responses */ - struct usb_request *stat_req; /* for cdc & rndis status */ - - u8 config; - struct usb_ep *in_ep, *out_ep, *status_ep; - const struct usb_endpoint_descriptor - *in, *out, *status; - - struct usb_request *tx_req, *rx_req; - - struct eth_device *net; - struct net_device_stats stats; - unsigned int tx_qlen; - - unsigned zlp:1; - unsigned cdc:1; - unsigned rndis:1; - unsigned suspended:1; - unsigned network_started:1; - u16 cdc_filter; - unsigned long todo; - int mtu; -#define WORK_RX_MEMORY 0 - int rndis_config; - u8 host_mac[ETH_ALEN]; -}; - -/* - * This version autoconfigures as much as possible at run-time. - * - * It also ASSUMES a self-powered device, without remote wakeup, - * although remote wakeup support would make sense. - */ - -/*-------------------------------------------------------------------------*/ -static struct eth_dev l_ethdev; -static struct eth_device l_netdev; -static struct usb_gadget_driver eth_driver; - -/*-------------------------------------------------------------------------*/ - -/* "main" config is either CDC, or its simple subset */ -static inline int is_cdc(struct eth_dev *dev) -{ -#if !defined(CONFIG_USB_ETH_SUBSET) - return 1; /* only cdc possible */ -#elif !defined(CONFIG_USB_ETH_CDC) - return 0; /* only subset possible */ -#else - return dev->cdc; /* depends on what hardware we found */ -#endif -} - -/* "secondary" RNDIS config may sometimes be activated */ -static inline int rndis_active(struct eth_dev *dev) -{ -#ifdef CONFIG_USB_ETH_RNDIS - return dev->rndis; -#else - return 0; -#endif -} - -#define subset_active(dev) (!is_cdc(dev) && !rndis_active(dev)) -#define cdc_active(dev) (is_cdc(dev) && !rndis_active(dev)) - -#define DEFAULT_QLEN 2 /* double buffering by default */ - -/* peak bulk transfer bits-per-second */ -#define HS_BPS (13 * 512 * 8 * 1000 * 8) -#define FS_BPS (19 * 64 * 1 * 1000 * 8) - -#ifdef CONFIG_USB_GADGET_DUALSPEED -#define DEVSPEED USB_SPEED_HIGH - -#ifdef CONFIG_USB_ETH_QMULT -#define qmult CONFIG_USB_ETH_QMULT -#else -#define qmult 5 -#endif - -/* for dual-speed hardware, use deeper queues at highspeed */ -#define qlen(gadget) \ - (DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1)) - -static inline int BITRATE(struct usb_gadget *g) -{ - return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS; -} - -#else /* full speed (low speed doesn't do bulk) */ - -#define qmult 1 - -#define DEVSPEED USB_SPEED_FULL - -#define qlen(gadget) DEFAULT_QLEN - -static inline int BITRATE(struct usb_gadget *g) -{ - return FS_BPS; -} -#endif - -/*-------------------------------------------------------------------------*/ - -/* - * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! - * Instead: allocate your own, using normal USB-IF procedures. - */ - -/* - * Thanks to NetChip Technologies for donating this product ID. - * It's for devices with only CDC Ethernet configurations. - */ -#define CDC_VENDOR_NUM 0x0525 /* NetChip */ -#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ - -/* - * For hardware that can't talk CDC, we use the same vendor ID that - * ARM Linux has used for ethernet-over-usb, both with sa1100 and - * with pxa250. We're protocol-compatible, if the host-side drivers - * use the endpoint descriptors. bcdDevice (version) is nonzero, so - * drivers that need to hard-wire endpoint numbers have a hook. - * - * The protocol is a minimal subset of CDC Ether, which works on any bulk - * hardware that's not deeply broken ... even on hardware that can't talk - * RNDIS (like SA-1100, with no interrupt endpoint, or anything that - * doesn't handle control-OUT). - */ -#define SIMPLE_VENDOR_NUM 0x049f /* Compaq Computer Corp. */ -#define SIMPLE_PRODUCT_NUM 0x505a /* Linux-USB "CDC Subset" Device */ - -/* - * For hardware that can talk RNDIS and either of the above protocols, - * use this ID ... the windows INF files will know it. Unless it's - * used with CDC Ethernet, Linux 2.4 hosts will need updates to choose - * the non-RNDIS configuration. - */ -#define RNDIS_VENDOR_NUM 0x0525 /* NetChip */ -#define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */ - -/* - * Some systems will want different product identifers published in the - * device descriptor, either numbers or strings or both. These string - * parameters are in UTF-8 (superset of ASCII's 7 bit characters). - */ - -/* - * Emulating them in eth_bind: - * static ushort idVendor; - * static ushort idProduct; - */ - -#if defined(CONFIG_USBNET_MANUFACTURER) -static char *iManufacturer = CONFIG_USBNET_MANUFACTURER; -#else -static char *iManufacturer = "U-boot"; -#endif - -/* These probably need to be configurable. */ -static ushort bcdDevice; -static char *iProduct; -static char *iSerialNumber; - -static char dev_addr[18]; - -static char host_addr[18]; - - -/*-------------------------------------------------------------------------*/ - -/* - * USB DRIVER HOOKUP (to the hardware driver, below us), mostly - * ep0 implementation: descriptors, config management, setup(). - * also optional class-specific notification interrupt transfer. - */ - -/* - * DESCRIPTORS ... most are static, but strings and (full) configuration - * descriptors are built on demand. For now we do either full CDC, or - * our simple subset, with RNDIS as an optional second configuration. - * - * RNDIS includes some CDC ACM descriptors ... like CDC Ethernet. But - * the class descriptors match a modem (they're ignored; it's really just - * Ethernet functionality), they don't need the NOP altsetting, and the - * status transfer endpoint isn't optional. - */ - -#define STRING_MANUFACTURER 1 -#define STRING_PRODUCT 2 -#define STRING_ETHADDR 3 -#define STRING_DATA 4 -#define STRING_CONTROL 5 -#define STRING_RNDIS_CONTROL 6 -#define STRING_CDC 7 -#define STRING_SUBSET 8 -#define STRING_RNDIS 9 -#define STRING_SERIALNUMBER 10 - -/* holds our biggest descriptor (or RNDIS response) */ -#define USB_BUFSIZ 256 - -/* - * This device advertises one configuration, eth_config, unless RNDIS - * is enabled (rndis_config) on hardware supporting at least two configs. - * - * NOTE: Controllers like superh_udc should probably be able to use - * an RNDIS-only configuration. - * - * FIXME define some higher-powered configurations to make it easier - * to recharge batteries ... - */ - -#define DEV_CONFIG_VALUE 1 /* cdc or subset */ -#define DEV_RNDIS_CONFIG_VALUE 2 /* rndis; optional */ - -static struct usb_device_descriptor -device_desc = { - .bLength = sizeof device_desc, - .bDescriptorType = USB_DT_DEVICE, - - .bcdUSB = __constant_cpu_to_le16(0x0200), - - .bDeviceClass = USB_CLASS_COMM, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, - - .idVendor = __constant_cpu_to_le16(CDC_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(CDC_PRODUCT_NUM), - .iManufacturer = STRING_MANUFACTURER, - .iProduct = STRING_PRODUCT, - .bNumConfigurations = 1, -}; - -static struct usb_otg_descriptor -otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - .bmAttributes = USB_OTG_SRP, -}; - -static struct usb_config_descriptor -eth_config = { - .bLength = sizeof eth_config, - .bDescriptorType = USB_DT_CONFIG, - - /* compute wTotalLength on the fly */ - .bNumInterfaces = 2, - .bConfigurationValue = DEV_CONFIG_VALUE, - .iConfiguration = STRING_CDC, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, -}; - -#ifdef CONFIG_USB_ETH_RNDIS -static struct usb_config_descriptor -rndis_config = { - .bLength = sizeof rndis_config, - .bDescriptorType = USB_DT_CONFIG, - - /* compute wTotalLength on the fly */ - .bNumInterfaces = 2, - .bConfigurationValue = DEV_RNDIS_CONFIG_VALUE, - .iConfiguration = STRING_RNDIS, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, -}; -#endif - -/* - * Compared to the simple CDC subset, the full CDC Ethernet model adds - * three class descriptors, two interface descriptors, optional status - * endpoint. Both have a "data" interface and two bulk endpoints. - * There are also differences in how control requests are handled. - * - * RNDIS shares a lot with CDC-Ethernet, since it's a variant of the - * CDC-ACM (modem) spec. Unfortunately MSFT's RNDIS driver is buggy; it - * may hang or oops. Since bugfixes (or accurate specs, letting Linux - * work around those bugs) are unlikely to ever come from MSFT, you may - * wish to avoid using RNDIS. - * - * MCCI offers an alternative to RNDIS if you need to connect to Windows - * but have hardware that can't support CDC Ethernet. We add descriptors - * to present the CDC Subset as a (nonconformant) CDC MDLM variant called - * "SAFE". That borrows from both CDC Ethernet and CDC MDLM. You can - * get those drivers from MCCI, or bundled with various products. - */ - -#ifdef CONFIG_USB_ETH_CDC -static struct usb_interface_descriptor -control_intf = { - .bLength = sizeof control_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 0, - /* status endpoint is optional; this may be patched later */ - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, - .iInterface = STRING_CONTROL, -}; -#endif - -#ifdef CONFIG_USB_ETH_RNDIS -static const struct usb_interface_descriptor -rndis_control_intf = { - .bLength = sizeof rndis_control_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR, - .iInterface = STRING_RNDIS_CONTROL, -}; -#endif - -static const struct usb_cdc_header_desc header_desc = { - .bLength = sizeof header_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_HEADER_TYPE, - - .bcdCDC = __constant_cpu_to_le16(0x0110), -}; - -#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS) - -static const struct usb_cdc_union_desc union_desc = { - .bLength = sizeof union_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_UNION_TYPE, - - .bMasterInterface0 = 0, /* index of control interface */ - .bSlaveInterface0 = 1, /* index of DATA interface */ -}; - -#endif /* CDC || RNDIS */ - -#ifdef CONFIG_USB_ETH_RNDIS - -static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = { - .bLength = sizeof call_mgmt_descriptor, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, - - .bmCapabilities = 0x00, - .bDataInterface = 0x01, -}; - -static const struct usb_cdc_acm_descriptor acm_descriptor = { - .bLength = sizeof acm_descriptor, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_ACM_TYPE, - - .bmCapabilities = 0x00, -}; - -#endif - -#ifndef CONFIG_USB_ETH_CDC - -/* - * "SAFE" loosely follows CDC WMC MDLM, violating the spec in various - * ways: data endpoints live in the control interface, there's no data - * interface, and it's not used to talk to a cell phone radio. - */ - -static const struct usb_cdc_mdlm_desc mdlm_desc = { - .bLength = sizeof mdlm_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_MDLM_TYPE, - - .bcdVersion = __constant_cpu_to_le16(0x0100), - .bGUID = { - 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, - 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, - }, -}; - -/* - * since "usb_cdc_mdlm_detail_desc" is a variable length structure, we - * can't really use its struct. All we do here is say that we're using - * the submode of "SAFE" which directly matches the CDC Subset. - */ -static const u8 mdlm_detail_desc[] = { - 6, - USB_DT_CS_INTERFACE, - USB_CDC_MDLM_DETAIL_TYPE, - - 0, /* "SAFE" */ - 0, /* network control capabilities (none) */ - 0, /* network data capabilities ("raw" encapsulation) */ -}; - -#endif - -static const struct usb_cdc_ether_desc ether_desc = { - .bLength = sizeof(ether_desc), - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, - - /* this descriptor actually adds value, surprise! */ - .iMACAddress = STRING_ETHADDR, - .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */ - .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN), - .wNumberMCFilters = __constant_cpu_to_le16(0), - .bNumberPowerFilters = 0, -}; - -#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS) - -/* - * include the status endpoint if we can, even where it's optional. - * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one - * packet, to simplify cancellation; and a big transfer interval, to - * waste less bandwidth. - * - * some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even - * if they ignore the connect/disconnect notifications that real aether - * can provide. more advanced cdc configurations might want to support - * encapsulated commands (vendor-specific, using control-OUT). - * - * RNDIS requires the status endpoint, since it uses that encapsulation - * mechanism for its funky RPC scheme. - */ - -#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ -#define STATUS_BYTECOUNT 16 /* 8 byte header + data */ - -static struct usb_endpoint_descriptor -fs_status_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), - .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, -}; -#endif - -#ifdef CONFIG_USB_ETH_CDC - -/* the default data interface has no endpoints ... */ - -static const struct usb_interface_descriptor -data_nop_intf = { - .bLength = sizeof data_nop_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 1, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = USB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, -}; - -/* ... but the "real" data interface has two bulk endpoints */ - -static const struct usb_interface_descriptor -data_intf = { - .bLength = sizeof data_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 1, - .bAlternateSetting = 1, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = STRING_DATA, -}; - -#endif - -#ifdef CONFIG_USB_ETH_RNDIS - -/* RNDIS doesn't activate by changing to the "real" altsetting */ - -static const struct usb_interface_descriptor -rndis_data_intf = { - .bLength = sizeof rndis_data_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 1, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = STRING_DATA, -}; - -#endif - -#ifdef CONFIG_USB_ETH_SUBSET - -/* - * "Simple" CDC-subset option is a simple vendor-neutral model that most - * full speed controllers can handle: one interface, two bulk endpoints. - * - * To assist host side drivers, we fancy it up a bit, and add descriptors - * so some host side drivers will understand it as a "SAFE" variant. - */ - -static const struct usb_interface_descriptor -subset_data_intf = { - .bLength = sizeof subset_data_intf, - .bDescriptorType = USB_DT_INTERFACE, - - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, - .bInterfaceProtocol = 0, - .iInterface = STRING_DATA, -}; - -#endif /* SUBSET */ - -static struct usb_endpoint_descriptor -fs_source_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(64), -}; - -static struct usb_endpoint_descriptor -fs_sink_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(64), -}; - -static const struct usb_descriptor_header *fs_eth_function[11] = { - (struct usb_descriptor_header *) &otg_descriptor, -#ifdef CONFIG_USB_ETH_CDC - /* "cdc" mode descriptors */ - (struct usb_descriptor_header *) &control_intf, - (struct usb_descriptor_header *) &header_desc, - (struct usb_descriptor_header *) &union_desc, - (struct usb_descriptor_header *) ðer_desc, - /* NOTE: status endpoint may need to be removed */ - (struct usb_descriptor_header *) &fs_status_desc, - /* data interface, with altsetting */ - (struct usb_descriptor_header *) &data_nop_intf, - (struct usb_descriptor_header *) &data_intf, - (struct usb_descriptor_header *) &fs_source_desc, - (struct usb_descriptor_header *) &fs_sink_desc, - NULL, -#endif /* CONFIG_USB_ETH_CDC */ -}; - -static inline void fs_subset_descriptors(void) -{ -#ifdef CONFIG_USB_ETH_SUBSET - /* behavior is "CDC Subset"; extra descriptors say "SAFE" */ - fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf; - fs_eth_function[2] = (struct usb_descriptor_header *) &header_desc; - fs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc; - fs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc; - fs_eth_function[5] = (struct usb_descriptor_header *) ðer_desc; - fs_eth_function[6] = (struct usb_descriptor_header *) &fs_source_desc; - fs_eth_function[7] = (struct usb_descriptor_header *) &fs_sink_desc; - fs_eth_function[8] = NULL; -#else - fs_eth_function[1] = NULL; -#endif -} - -#ifdef CONFIG_USB_ETH_RNDIS -static const struct usb_descriptor_header *fs_rndis_function[] = { - (struct usb_descriptor_header *) &otg_descriptor, - /* control interface matches ACM, not Ethernet */ - (struct usb_descriptor_header *) &rndis_control_intf, - (struct usb_descriptor_header *) &header_desc, - (struct usb_descriptor_header *) &call_mgmt_descriptor, - (struct usb_descriptor_header *) &acm_descriptor, - (struct usb_descriptor_header *) &union_desc, - (struct usb_descriptor_header *) &fs_status_desc, - /* data interface has no altsetting */ - (struct usb_descriptor_header *) &rndis_data_intf, - (struct usb_descriptor_header *) &fs_source_desc, - (struct usb_descriptor_header *) &fs_sink_desc, - NULL, -}; -#endif - -/* - * usb 2.0 devices need to expose both high speed and full speed - * descriptors, unless they only run at full speed. - */ - -#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS) -static struct usb_endpoint_descriptor -hs_status_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), - .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, -}; -#endif /* CONFIG_USB_ETH_CDC */ - -static struct usb_endpoint_descriptor -hs_source_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), -}; - -static struct usb_endpoint_descriptor -hs_sink_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), -}; - -static struct usb_qualifier_descriptor -dev_qualifier = { - .bLength = sizeof dev_qualifier, - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - - .bcdUSB = __constant_cpu_to_le16(0x0200), - .bDeviceClass = USB_CLASS_COMM, - - .bNumConfigurations = 1, -}; - -static const struct usb_descriptor_header *hs_eth_function[11] = { - (struct usb_descriptor_header *) &otg_descriptor, -#ifdef CONFIG_USB_ETH_CDC - /* "cdc" mode descriptors */ - (struct usb_descriptor_header *) &control_intf, - (struct usb_descriptor_header *) &header_desc, - (struct usb_descriptor_header *) &union_desc, - (struct usb_descriptor_header *) ðer_desc, - /* NOTE: status endpoint may need to be removed */ - (struct usb_descriptor_header *) &hs_status_desc, - /* data interface, with altsetting */ - (struct usb_descriptor_header *) &data_nop_intf, - (struct usb_descriptor_header *) &data_intf, - (struct usb_descriptor_header *) &hs_source_desc, - (struct usb_descriptor_header *) &hs_sink_desc, - NULL, -#endif /* CONFIG_USB_ETH_CDC */ -}; - -static inline void hs_subset_descriptors(void) -{ -#ifdef CONFIG_USB_ETH_SUBSET - /* behavior is "CDC Subset"; extra descriptors say "SAFE" */ - hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf; - hs_eth_function[2] = (struct usb_descriptor_header *) &header_desc; - hs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc; - hs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc; - hs_eth_function[5] = (struct usb_descriptor_header *) ðer_desc; - hs_eth_function[6] = (struct usb_descriptor_header *) &hs_source_desc; - hs_eth_function[7] = (struct usb_descriptor_header *) &hs_sink_desc; - hs_eth_function[8] = NULL; -#else - hs_eth_function[1] = NULL; -#endif -} - -#ifdef CONFIG_USB_ETH_RNDIS -static const struct usb_descriptor_header *hs_rndis_function[] = { - (struct usb_descriptor_header *) &otg_descriptor, - /* control interface matches ACM, not Ethernet */ - (struct usb_descriptor_header *) &rndis_control_intf, - (struct usb_descriptor_header *) &header_desc, - (struct usb_descriptor_header *) &call_mgmt_descriptor, - (struct usb_descriptor_header *) &acm_descriptor, - (struct usb_descriptor_header *) &union_desc, - (struct usb_descriptor_header *) &hs_status_desc, - /* data interface has no altsetting */ - (struct usb_descriptor_header *) &rndis_data_intf, - (struct usb_descriptor_header *) &hs_source_desc, - (struct usb_descriptor_header *) &hs_sink_desc, - NULL, -}; -#endif - - -/* maxpacket and other transfer characteristics vary by speed. */ -static inline struct usb_endpoint_descriptor * -ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, - struct usb_endpoint_descriptor *fs) -{ - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) - return hs; - return fs; -} - -/*-------------------------------------------------------------------------*/ - -/* descriptors that are built on-demand */ - -static char manufacturer[50]; -static char product_desc[40] = DRIVER_DESC; -static char serial_number[20]; - -/* address that the host will use ... usually assigned at random */ -static char ethaddr[2 * ETH_ALEN + 1]; - -/* static strings, in UTF-8 */ -static struct usb_string strings[] = { - { STRING_MANUFACTURER, manufacturer, }, - { STRING_PRODUCT, product_desc, }, - { STRING_SERIALNUMBER, serial_number, }, - { STRING_DATA, "Ethernet Data", }, - { STRING_ETHADDR, ethaddr, }, -#ifdef CONFIG_USB_ETH_CDC - { STRING_CDC, "CDC Ethernet", }, - { STRING_CONTROL, "CDC Communications Control", }, -#endif -#ifdef CONFIG_USB_ETH_SUBSET - { STRING_SUBSET, "CDC Ethernet Subset", }, -#endif -#ifdef CONFIG_USB_ETH_RNDIS - { STRING_RNDIS, "RNDIS", }, - { STRING_RNDIS_CONTROL, "RNDIS Communications Control", }, -#endif - { } /* end of list */ -}; - -static struct usb_gadget_strings stringtab = { - .language = 0x0409, /* en-us */ - .strings = strings, -}; - -/*============================================================================*/ -DEFINE_CACHE_ALIGN_BUFFER(u8, control_req, USB_BUFSIZ); - -#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS) -DEFINE_CACHE_ALIGN_BUFFER(u8, status_req, STATUS_BYTECOUNT); -#endif - - -/** - * strlcpy - Copy a %NUL terminated string into a sized buffer - * @dest: Where to copy the string to - * @src: Where to copy the string from - * @size: size of destination buffer - * - * Compatible with *BSD: the result is always a valid - * NUL-terminated string that fits in the buffer (unless, - * of course, the buffer size is zero). It does not pad - * out the result like strncpy() does. - */ -size_t strlcpy(char *dest, const char *src, size_t size) -{ - size_t ret = strlen(src); - - if (size) { - size_t len = (ret >= size) ? size - 1 : ret; - memcpy(dest, src, len); - dest[len] = '\0'; - } - return ret; -} - -/*============================================================================*/ - -/* - * one config, two interfaces: control, data. - * complications: class descriptors, and an altsetting. - */ -static int -config_buf(struct usb_gadget *g, u8 *buf, u8 type, unsigned index, int is_otg) -{ - int len; - const struct usb_config_descriptor *config; - const struct usb_descriptor_header **function; - int hs = 0; - - if (gadget_is_dualspeed(g)) { - hs = (g->speed == USB_SPEED_HIGH); - if (type == USB_DT_OTHER_SPEED_CONFIG) - hs = !hs; - } -#define which_fn(t) (hs ? hs_ ## t ## _function : fs_ ## t ## _function) - - if (index >= device_desc.bNumConfigurations) - return -EINVAL; - -#ifdef CONFIG_USB_ETH_RNDIS - /* - * list the RNDIS config first, to make Microsoft's drivers - * happy. DOCSIS 1.0 needs this too. - */ - if (device_desc.bNumConfigurations == 2 && index == 0) { - config = &rndis_config; - function = which_fn(rndis); - } else -#endif - { - config = ð_config; - function = which_fn(eth); - } - - /* for now, don't advertise srp-only devices */ - if (!is_otg) - function++; - - len = usb_gadget_config_buf(config, buf, USB_BUFSIZ, function); - if (len < 0) - return len; - ((struct usb_config_descriptor *) buf)->bDescriptorType = type; - return len; -} - -/*-------------------------------------------------------------------------*/ - -static void eth_start(struct eth_dev *dev, gfp_t gfp_flags); -static int alloc_requests(struct eth_dev *dev, unsigned n, gfp_t gfp_flags); - -static int -set_ether_config(struct eth_dev *dev, gfp_t gfp_flags) -{ - int result = 0; - struct usb_gadget *gadget = dev->gadget; - -#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS) - /* status endpoint used for RNDIS and (optionally) CDC */ - if (!subset_active(dev) && dev->status_ep) { - dev->status = ep_desc(gadget, &hs_status_desc, - &fs_status_desc); - dev->status_ep->driver_data = dev; - - result = usb_ep_enable(dev->status_ep, dev->status); - if (result != 0) { - debug("enable %s --> %d\n", - dev->status_ep->name, result); - goto done; - } - } -#endif - - dev->in = ep_desc(gadget, &hs_source_desc, &fs_source_desc); - dev->in_ep->driver_data = dev; - - dev->out = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc); - dev->out_ep->driver_data = dev; - - /* - * With CDC, the host isn't allowed to use these two data - * endpoints in the default altsetting for the interface. - * so we don't activate them yet. Reset from SET_INTERFACE. - * - * Strictly speaking RNDIS should work the same: activation is - * a side effect of setting a packet filter. Deactivation is - * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG. - */ - if (!cdc_active(dev)) { - result = usb_ep_enable(dev->in_ep, dev->in); - if (result != 0) { - debug("enable %s --> %d\n", - dev->in_ep->name, result); - goto done; - } - - result = usb_ep_enable(dev->out_ep, dev->out); - if (result != 0) { - debug("enable %s --> %d\n", - dev->out_ep->name, result); - goto done; - } - } - -done: - if (result == 0) - result = alloc_requests(dev, qlen(gadget), gfp_flags); - - /* on error, disable any endpoints */ - if (result < 0) { - if (!subset_active(dev) && dev->status_ep) - (void) usb_ep_disable(dev->status_ep); - dev->status = NULL; - (void) usb_ep_disable(dev->in_ep); - (void) usb_ep_disable(dev->out_ep); - dev->in = NULL; - dev->out = NULL; - } else if (!cdc_active(dev)) { - /* - * activate non-CDC configs right away - * this isn't strictly according to the RNDIS spec - */ - eth_start(dev, GFP_ATOMIC); - } - - /* caller is responsible for cleanup on error */ - return result; -} - -static void eth_reset_config(struct eth_dev *dev) -{ - if (dev->config == 0) - return; - - debug("%s\n", __func__); - - rndis_uninit(dev->rndis_config); - - /* - * disable endpoints, forcing (synchronous) completion of - * pending i/o. then free the requests. - */ - - if (dev->in) { - usb_ep_disable(dev->in_ep); - if (dev->tx_req) { - usb_ep_free_request(dev->in_ep, dev->tx_req); - dev->tx_req = NULL; - } - } - if (dev->out) { - usb_ep_disable(dev->out_ep); - if (dev->rx_req) { - usb_ep_free_request(dev->out_ep, dev->rx_req); - dev->rx_req = NULL; - } - } - if (dev->status) - usb_ep_disable(dev->status_ep); - - dev->rndis = 0; - dev->cdc_filter = 0; - dev->config = 0; -} - -/* - * change our operational config. must agree with the code - * that returns config descriptors, and altsetting code. - */ -static int eth_set_config(struct eth_dev *dev, unsigned number, - gfp_t gfp_flags) -{ - int result = 0; - struct usb_gadget *gadget = dev->gadget; - - if (gadget_is_sa1100(gadget) - && dev->config - && dev->tx_qlen != 0) { - /* tx fifo is full, but we can't clear it...*/ - error("can't change configurations"); - return -ESPIPE; - } - eth_reset_config(dev); - - switch (number) { - case DEV_CONFIG_VALUE: - result = set_ether_config(dev, gfp_flags); - break; -#ifdef CONFIG_USB_ETH_RNDIS - case DEV_RNDIS_CONFIG_VALUE: - dev->rndis = 1; - result = set_ether_config(dev, gfp_flags); - break; -#endif - default: - result = -EINVAL; - /* FALL THROUGH */ - case 0: - break; - } - - if (result) { - if (number) - eth_reset_config(dev); - usb_gadget_vbus_draw(dev->gadget, - gadget_is_otg(dev->gadget) ? 8 : 100); - } else { - char *speed; - unsigned power; - - power = 2 * eth_config.bMaxPower; - usb_gadget_vbus_draw(dev->gadget, power); - - switch (gadget->speed) { - case USB_SPEED_FULL: - speed = "full"; break; -#ifdef CONFIG_USB_GADGET_DUALSPEED - case USB_SPEED_HIGH: - speed = "high"; break; -#endif - default: - speed = "?"; break; - } - - dev->config = number; - printf("%s speed config #%d: %d mA, %s, using %s\n", - speed, number, power, driver_desc, - rndis_active(dev) - ? "RNDIS" - : (cdc_active(dev) - ? "CDC Ethernet" - : "CDC Ethernet Subset")); - } - return result; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_USB_ETH_CDC - -/* - * The interrupt endpoint is used in CDC networking models (Ethernet, ATM) - * only to notify the host about link status changes (which we support) or - * report completion of some encapsulated command (as used in RNDIS). Since - * we want this CDC Ethernet code to be vendor-neutral, we don't use that - * command mechanism; and only one status request is ever queued. - */ -static void eth_status_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct usb_cdc_notification *event = req->buf; - int value = req->status; - struct eth_dev *dev = ep->driver_data; - - /* issue the second notification if host reads the first */ - if (event->bNotificationType == USB_CDC_NOTIFY_NETWORK_CONNECTION - && value == 0) { - __le32 *data = req->buf + sizeof *event; - - event->bmRequestType = 0xA1; - event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE; - event->wValue = __constant_cpu_to_le16(0); - event->wIndex = __constant_cpu_to_le16(1); - event->wLength = __constant_cpu_to_le16(8); - - /* SPEED_CHANGE data is up/down speeds in bits/sec */ - data[0] = data[1] = cpu_to_le32(BITRATE(dev->gadget)); - - req->length = STATUS_BYTECOUNT; - value = usb_ep_queue(ep, req, GFP_ATOMIC); - debug("send SPEED_CHANGE --> %d\n", value); - if (value == 0) - return; - } else if (value != -ECONNRESET) { - debug("event %02x --> %d\n", - event->bNotificationType, value); - if (event->bNotificationType == - USB_CDC_NOTIFY_SPEED_CHANGE) { - l_ethdev.network_started = 1; - printf("USB network up!\n"); - } - } - req->context = NULL; -} - -static void issue_start_status(struct eth_dev *dev) -{ - struct usb_request *req = dev->stat_req; - struct usb_cdc_notification *event; - int value; - - /* - * flush old status - * - * FIXME ugly idiom, maybe we'd be better with just - * a "cancel the whole queue" primitive since any - * unlink-one primitive has way too many error modes. - * here, we "know" toggle is already clear... - * - * FIXME iff req->context != null just dequeue it - */ - usb_ep_disable(dev->status_ep); - usb_ep_enable(dev->status_ep, dev->status); - - /* - * 3.8.1 says to issue first NETWORK_CONNECTION, then - * a SPEED_CHANGE. could be useful in some configs. - */ - event = req->buf; - event->bmRequestType = 0xA1; - event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION; - event->wValue = __constant_cpu_to_le16(1); /* connected */ - event->wIndex = __constant_cpu_to_le16(1); - event->wLength = 0; - - req->length = sizeof *event; - req->complete = eth_status_complete; - req->context = dev; - - value = usb_ep_queue(dev->status_ep, req, GFP_ATOMIC); - if (value < 0) - debug("status buf queue --> %d\n", value); -} - -#endif - -/*-------------------------------------------------------------------------*/ - -static void eth_setup_complete(struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) - debug("setup complete --> %d, %d/%d\n", - req->status, req->actual, req->length); -} - -#ifdef CONFIG_USB_ETH_RNDIS - -static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) - debug("rndis response complete --> %d, %d/%d\n", - req->status, req->actual, req->length); - - /* done sending after USB_CDC_GET_ENCAPSULATED_RESPONSE */ -} - -static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct eth_dev *dev = ep->driver_data; - int status; - - /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ - status = rndis_msg_parser(dev->rndis_config, (u8 *) req->buf); - if (status < 0) - error("%s: rndis parse error %d", __func__, status); -} - -#endif /* RNDIS */ - -/* - * The setup() callback implements all the ep0 functionality that's not - * handled lower down. CDC has a number of less-common features: - * - * - two interfaces: control, and ethernet data - * - Ethernet data interface has two altsettings: default, and active - * - class-specific descriptors for the control interface - * - class-specific control requests - */ -static int -eth_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) -{ - struct eth_dev *dev = get_gadget_data(gadget); - struct usb_request *req = dev->req; - int value = -EOPNOTSUPP; - u16 wIndex = le16_to_cpu(ctrl->wIndex); - u16 wValue = le16_to_cpu(ctrl->wValue); - u16 wLength = le16_to_cpu(ctrl->wLength); - - /* - * descriptors just go into the pre-allocated ep0 buffer, - * while config change events may enable network traffic. - */ - - debug("%s\n", __func__); - - req->complete = eth_setup_complete; - switch (ctrl->bRequest) { - - case USB_REQ_GET_DESCRIPTOR: - if (ctrl->bRequestType != USB_DIR_IN) - break; - switch (wValue >> 8) { - - case USB_DT_DEVICE: - value = min(wLength, (u16) sizeof device_desc); - memcpy(req->buf, &device_desc, value); - break; - case USB_DT_DEVICE_QUALIFIER: - if (!gadget_is_dualspeed(gadget)) - break; - value = min(wLength, (u16) sizeof dev_qualifier); - memcpy(req->buf, &dev_qualifier, value); - break; - - case USB_DT_OTHER_SPEED_CONFIG: - if (!gadget_is_dualspeed(gadget)) - break; - /* FALLTHROUGH */ - case USB_DT_CONFIG: - value = config_buf(gadget, req->buf, - wValue >> 8, - wValue & 0xff, - gadget_is_otg(gadget)); - if (value >= 0) - value = min(wLength, (u16) value); - break; - - case USB_DT_STRING: - value = usb_gadget_get_string(&stringtab, - wValue & 0xff, req->buf); - - if (value >= 0) - value = min(wLength, (u16) value); - - break; - } - break; - - case USB_REQ_SET_CONFIGURATION: - if (ctrl->bRequestType != 0) - break; - if (gadget->a_hnp_support) - debug("HNP available\n"); - else if (gadget->a_alt_hnp_support) - debug("HNP needs a different root port\n"); - value = eth_set_config(dev, wValue, GFP_ATOMIC); - break; - case USB_REQ_GET_CONFIGURATION: - if (ctrl->bRequestType != USB_DIR_IN) - break; - *(u8 *)req->buf = dev->config; - value = min(wLength, (u16) 1); - break; - - case USB_REQ_SET_INTERFACE: - if (ctrl->bRequestType != USB_RECIP_INTERFACE - || !dev->config - || wIndex > 1) - break; - if (!cdc_active(dev) && wIndex != 0) - break; - - /* - * PXA hardware partially handles SET_INTERFACE; - * we need to kluge around that interference. - */ - if (gadget_is_pxa(gadget)) { - value = eth_set_config(dev, DEV_CONFIG_VALUE, - GFP_ATOMIC); - /* - * PXA25x driver use non-CDC ethernet gadget. - * But only _CDC and _RNDIS code can signalize - * that network is working. So we signalize it - * here. - */ - l_ethdev.network_started = 1; - debug("USB network up!\n"); - goto done_set_intf; - } - -#ifdef CONFIG_USB_ETH_CDC - switch (wIndex) { - case 0: /* control/master intf */ - if (wValue != 0) - break; - if (dev->status) { - usb_ep_disable(dev->status_ep); - usb_ep_enable(dev->status_ep, dev->status); - } - - value = 0; - break; - case 1: /* data intf */ - if (wValue > 1) - break; - usb_ep_disable(dev->in_ep); - usb_ep_disable(dev->out_ep); - - /* - * CDC requires the data transfers not be done from - * the default interface setting ... also, setting - * the non-default interface resets filters etc. - */ - if (wValue == 1) { - if (!cdc_active(dev)) - break; - usb_ep_enable(dev->in_ep, dev->in); - usb_ep_enable(dev->out_ep, dev->out); - dev->cdc_filter = DEFAULT_FILTER; - if (dev->status) - issue_start_status(dev); - eth_start(dev, GFP_ATOMIC); - } - value = 0; - break; - } -#else - /* - * FIXME this is wrong, as is the assumption that - * all non-PXA hardware talks real CDC ... - */ - debug("set_interface ignored!\n"); -#endif /* CONFIG_USB_ETH_CDC */ - -done_set_intf: - break; - case USB_REQ_GET_INTERFACE: - if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE) - || !dev->config - || wIndex > 1) - break; - if (!(cdc_active(dev) || rndis_active(dev)) && wIndex != 0) - break; - - /* for CDC, iff carrier is on, data interface is active. */ - if (rndis_active(dev) || wIndex != 1) - *(u8 *)req->buf = 0; - else { - /* *(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0; */ - /* carrier always ok ...*/ - *(u8 *)req->buf = 1 ; - } - value = min(wLength, (u16) 1); - break; - -#ifdef CONFIG_USB_ETH_CDC - case USB_CDC_SET_ETHERNET_PACKET_FILTER: - /* - * see 6.2.30: no data, wIndex = interface, - * wValue = packet filter bitmap - */ - if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) - || !cdc_active(dev) - || wLength != 0 - || wIndex > 1) - break; - debug("packet filter %02x\n", wValue); - dev->cdc_filter = wValue; - value = 0; - break; - - /* - * and potentially: - * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS: - * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER: - * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER: - * case USB_CDC_GET_ETHERNET_STATISTIC: - */ - -#endif /* CONFIG_USB_ETH_CDC */ - -#ifdef CONFIG_USB_ETH_RNDIS - /* - * RNDIS uses the CDC command encapsulation mechanism to implement - * an RPC scheme, with much getting/setting of attributes by OID. - */ - case USB_CDC_SEND_ENCAPSULATED_COMMAND: - if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) - || !rndis_active(dev) - || wLength > USB_BUFSIZ - || wValue - || rndis_control_intf.bInterfaceNumber - != wIndex) - break; - /* read the request, then process it */ - value = wLength; - req->complete = rndis_command_complete; - /* later, rndis_control_ack () sends a notification */ - break; - - case USB_CDC_GET_ENCAPSULATED_RESPONSE: - if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE) - == ctrl->bRequestType - && rndis_active(dev) - /* && wLength >= 0x0400 */ - && !wValue - && rndis_control_intf.bInterfaceNumber - == wIndex) { - u8 *buf; - u32 n; - - /* return the result */ - buf = rndis_get_next_response(dev->rndis_config, &n); - if (buf) { - memcpy(req->buf, buf, n); - req->complete = rndis_response_complete; - rndis_free_response(dev->rndis_config, buf); - value = n; - } - /* else stalls ... spec says to avoid that */ - } - break; -#endif /* RNDIS */ - - default: - debug("unknown control req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - wValue, wIndex, wLength); - } - - /* respond with data transfer before status phase? */ - if (value >= 0) { - debug("respond with data transfer before status phase\n"); - req->length = value; - req->zero = value < wLength - && (value % gadget->ep0->maxpacket) == 0; - value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); - if (value < 0) { - debug("ep_queue --> %d\n", value); - req->status = 0; - eth_setup_complete(gadget->ep0, req); - } - } - - /* host either stalls (value < 0) or reports success */ - return value; -} - -/*-------------------------------------------------------------------------*/ - -static void rx_complete(struct usb_ep *ep, struct usb_request *req); - -static int rx_submit(struct eth_dev *dev, struct usb_request *req, - gfp_t gfp_flags) -{ - int retval = -ENOMEM; - size_t size; - - /* - * Padding up to RX_EXTRA handles minor disagreements with host. - * Normally we use the USB "terminate on short read" convention; - * so allow up to (N*maxpacket), since that memory is normally - * already allocated. Some hardware doesn't deal well with short - * reads (e.g. DMA must be N*maxpacket), so for now don't trim a - * byte off the end (to force hardware errors on overflow). - * - * RNDIS uses internal framing, and explicitly allows senders to - * pad to end-of-packet. That's potentially nice for speed, - * but means receivers can't recover synch on their own. - */ - - debug("%s\n", __func__); - if (!req) - return -EINVAL; - - size = (ETHER_HDR_SIZE + dev->mtu + RX_EXTRA); - size += dev->out_ep->maxpacket - 1; - if (rndis_active(dev)) - size += sizeof(struct rndis_packet_msg_type); - size -= size % dev->out_ep->maxpacket; - - /* - * Some platforms perform better when IP packets are aligned, - * but on at least one, checksumming fails otherwise. Note: - * RNDIS headers involve variable numbers of LE32 values. - */ - - req->buf = (u8 *) NetRxPackets[0]; - req->length = size; - req->complete = rx_complete; - - retval = usb_ep_queue(dev->out_ep, req, gfp_flags); - - if (retval) - error("rx submit --> %d", retval); - - return retval; -} - -static void rx_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct eth_dev *dev = ep->driver_data; - - debug("%s: status %d\n", __func__, req->status); - switch (req->status) { - /* normal completion */ - case 0: - if (rndis_active(dev)) { - /* we know MaxPacketsPerTransfer == 1 here */ - int length = rndis_rm_hdr(req->buf, req->actual); - if (length < 0) - goto length_err; - req->length -= length; - req->actual -= length; - } - if (req->actual < ETH_HLEN || ETH_FRAME_LEN < req->actual) { -length_err: - dev->stats.rx_errors++; - dev->stats.rx_length_errors++; - debug("rx length %d\n", req->length); - break; - } - - dev->stats.rx_packets++; - dev->stats.rx_bytes += req->length; - break; - - /* software-driven interface shutdown */ - case -ECONNRESET: /* unlink */ - case -ESHUTDOWN: /* disconnect etc */ - /* for hardware automagic (such as pxa) */ - case -ECONNABORTED: /* endpoint reset */ - break; - - /* data overrun */ - case -EOVERFLOW: - dev->stats.rx_over_errors++; - /* FALLTHROUGH */ - default: - dev->stats.rx_errors++; - break; - } - - packet_received = 1; -} - -static int alloc_requests(struct eth_dev *dev, unsigned n, gfp_t gfp_flags) -{ - - dev->tx_req = usb_ep_alloc_request(dev->in_ep, 0); - - if (!dev->tx_req) - goto fail1; - - dev->rx_req = usb_ep_alloc_request(dev->out_ep, 0); - - if (!dev->rx_req) - goto fail2; - - return 0; - -fail2: - usb_ep_free_request(dev->in_ep, dev->tx_req); -fail1: - error("can't alloc requests"); - return -1; -} - -static void tx_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct eth_dev *dev = ep->driver_data; - - debug("%s: status %s\n", __func__, (req->status) ? "failed" : "ok"); - switch (req->status) { - default: - dev->stats.tx_errors++; - debug("tx err %d\n", req->status); - /* FALLTHROUGH */ - case -ECONNRESET: /* unlink */ - case -ESHUTDOWN: /* disconnect etc */ - break; - case 0: - dev->stats.tx_bytes += req->length; - } - dev->stats.tx_packets++; - - packet_sent = 1; -} - -static inline int eth_is_promisc(struct eth_dev *dev) -{ - /* no filters for the CDC subset; always promisc */ - if (subset_active(dev)) - return 1; - return dev->cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS; -} - -#if 0 -static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) -{ - struct eth_dev *dev = netdev_priv(net); - int length = skb->len; - int retval; - struct usb_request *req = NULL; - unsigned long flags; - - /* apply outgoing CDC or RNDIS filters */ - if (!eth_is_promisc (dev)) { - u8 *dest = skb->data; - - if (is_multicast_ether_addr(dest)) { - u16 type; - - /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host - * SET_ETHERNET_MULTICAST_FILTERS requests - */ - if (is_broadcast_ether_addr(dest)) - type = USB_CDC_PACKET_TYPE_BROADCAST; - else - type = USB_CDC_PACKET_TYPE_ALL_MULTICAST; - if (!(dev->cdc_filter & type)) { - dev_kfree_skb_any (skb); - return 0; - } - } - /* ignores USB_CDC_PACKET_TYPE_DIRECTED */ - } - - spin_lock_irqsave(&dev->req_lock, flags); - /* - * this freelist can be empty if an interrupt triggered disconnect() - * and reconfigured the gadget (shutting down this queue) after the - * network stack decided to xmit but before we got the spinlock. - */ - if (list_empty(&dev->tx_reqs)) { - spin_unlock_irqrestore(&dev->req_lock, flags); - return 1; - } - - req = container_of (dev->tx_reqs.next, struct usb_request, list); - list_del (&req->list); - - /* temporarily stop TX queue when the freelist empties */ - if (list_empty (&dev->tx_reqs)) - netif_stop_queue (net); - spin_unlock_irqrestore(&dev->req_lock, flags); - - /* no buffer copies needed, unless the network stack did it - * or the hardware can't use skb buffers. - * or there's not enough space for any RNDIS headers we need - */ - if (rndis_active(dev)) { - struct sk_buff *skb_rndis; - - skb_rndis = skb_realloc_headroom (skb, - sizeof (struct rndis_packet_msg_type)); - if (!skb_rndis) - goto drop; - - dev_kfree_skb_any (skb); - skb = skb_rndis; - rndis_add_hdr (skb); - length = skb->len; - } - req->buf = skb->data; - req->context = skb; - req->complete = tx_complete; - - /* use zlp framing on tx for strict CDC-Ether conformance, - * though any robust network rx path ignores extra padding. - * and some hardware doesn't like to write zlps. - */ - req->zero = 1; - if (!dev->zlp && (length % dev->in_ep->maxpacket) == 0) - length++; - - req->length = length; - - /* throttle highspeed IRQ rate back slightly */ - if (gadget_is_dualspeed(dev->gadget)) - req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH) - ? ((atomic_read(&dev->tx_qlen) % qmult) != 0) - : 0; - - retval = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC); - switch (retval) { - default: - DEBUG (dev, "tx queue err %d\n", retval); - break; - case 0: - net->trans_start = jiffies; - atomic_inc (&dev->tx_qlen); - } - - if (retval) { -drop: - dev->stats.tx_dropped++; - dev_kfree_skb_any (skb); - spin_lock_irqsave(&dev->req_lock, flags); - if (list_empty (&dev->tx_reqs)) - netif_start_queue (net); - list_add (&req->list, &dev->tx_reqs); - spin_unlock_irqrestore(&dev->req_lock, flags); - } - return 0; -} - -/*-------------------------------------------------------------------------*/ -#endif - -static void eth_unbind(struct usb_gadget *gadget) -{ - struct eth_dev *dev = get_gadget_data(gadget); - - debug("%s...\n", __func__); - rndis_deregister(dev->rndis_config); - rndis_exit(); - - /* we've already been disconnected ... no i/o is active */ - if (dev->req) { - usb_ep_free_request(gadget->ep0, dev->req); - dev->req = NULL; - } - if (dev->stat_req) { - usb_ep_free_request(dev->status_ep, dev->stat_req); - dev->stat_req = NULL; - } - - if (dev->tx_req) { - usb_ep_free_request(dev->in_ep, dev->tx_req); - dev->tx_req = NULL; - } - - if (dev->rx_req) { - usb_ep_free_request(dev->out_ep, dev->rx_req); - dev->rx_req = NULL; - } - -/* unregister_netdev (dev->net);*/ -/* free_netdev(dev->net);*/ - - dev->gadget = NULL; - set_gadget_data(gadget, NULL); -} - -static void eth_disconnect(struct usb_gadget *gadget) -{ - eth_reset_config(get_gadget_data(gadget)); - /* FIXME RNDIS should enter RNDIS_UNINITIALIZED */ -} - -static void eth_suspend(struct usb_gadget *gadget) -{ - /* Not used */ -} - -static void eth_resume(struct usb_gadget *gadget) -{ - /* Not used */ -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_USB_ETH_RNDIS - -/* - * The interrupt endpoint is used in RNDIS to notify the host when messages - * other than data packets are available ... notably the REMOTE_NDIS_*_CMPLT - * messages, but also REMOTE_NDIS_INDICATE_STATUS_MSG and potentially even - * REMOTE_NDIS_KEEPALIVE_MSG. - * - * The RNDIS control queue is processed by GET_ENCAPSULATED_RESPONSE, and - * normally just one notification will be queued. - */ - -static void rndis_control_ack_complete(struct usb_ep *ep, - struct usb_request *req) -{ - struct eth_dev *dev = ep->driver_data; - - debug("%s...\n", __func__); - if (req->status || req->actual != req->length) - debug("rndis control ack complete --> %d, %d/%d\n", - req->status, req->actual, req->length); - - if (!l_ethdev.network_started) { - if (rndis_get_state(dev->rndis_config) - == RNDIS_DATA_INITIALIZED) { - l_ethdev.network_started = 1; - printf("USB RNDIS network up!\n"); - } - } - - req->context = NULL; - - if (req != dev->stat_req) - usb_ep_free_request(ep, req); -} - -static char rndis_resp_buf[8] __attribute__((aligned(sizeof(__le32)))); - -static int rndis_control_ack(struct eth_device *net) -{ - struct eth_dev *dev = &l_ethdev; - int length; - struct usb_request *resp = dev->stat_req; - - /* in case RNDIS calls this after disconnect */ - if (!dev->status) { - debug("status ENODEV\n"); - return -ENODEV; - } - - /* in case queue length > 1 */ - if (resp->context) { - resp = usb_ep_alloc_request(dev->status_ep, GFP_ATOMIC); - if (!resp) - return -ENOMEM; - resp->buf = rndis_resp_buf; - } - - /* - * Send RNDIS RESPONSE_AVAILABLE notification; - * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too - */ - resp->length = 8; - resp->complete = rndis_control_ack_complete; - resp->context = dev; - - *((__le32 *) resp->buf) = __constant_cpu_to_le32(1); - *((__le32 *) (resp->buf + 4)) = __constant_cpu_to_le32(0); - - length = usb_ep_queue(dev->status_ep, resp, GFP_ATOMIC); - if (length < 0) { - resp->status = 0; - rndis_control_ack_complete(dev->status_ep, resp); - } - - return 0; -} - -#else - -#define rndis_control_ack NULL - -#endif /* RNDIS */ - -static void eth_start(struct eth_dev *dev, gfp_t gfp_flags) -{ - if (rndis_active(dev)) { - rndis_set_param_medium(dev->rndis_config, - NDIS_MEDIUM_802_3, - BITRATE(dev->gadget)/100); - rndis_signal_connect(dev->rndis_config); - } -} - -static int eth_stop(struct eth_dev *dev) -{ -#ifdef RNDIS_COMPLETE_SIGNAL_DISCONNECT - unsigned long ts; - unsigned long timeout = CONFIG_SYS_HZ; /* 1 sec to stop RNDIS */ -#endif - - if (rndis_active(dev)) { - rndis_set_param_medium(dev->rndis_config, NDIS_MEDIUM_802_3, 0); - rndis_signal_disconnect(dev->rndis_config); - -#ifdef RNDIS_COMPLETE_SIGNAL_DISCONNECT - /* Wait until host receives OID_GEN_MEDIA_CONNECT_STATUS */ - ts = get_timer(0); - while (get_timer(ts) < timeout) - usb_gadget_handle_interrupts(); -#endif - - rndis_uninit(dev->rndis_config); - dev->rndis = 0; - } - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static int is_eth_addr_valid(char *str) -{ - if (strlen(str) == 17) { - int i; - char *p, *q; - uchar ea[6]; - - /* see if it looks like an ethernet address */ - - p = str; - - for (i = 0; i < 6; i++) { - char term = (i == 5 ? '\0' : ':'); - - ea[i] = simple_strtol(p, &q, 16); - - if ((q - p) != 2 || *q++ != term) - break; - - p = q; - } - - /* Now check the contents. */ - return is_valid_ether_addr(ea); - } - return 0; -} - -static u8 nibble(unsigned char c) -{ - if (likely(isdigit(c))) - return c - '0'; - c = toupper(c); - if (likely(isxdigit(c))) - return 10 + c - 'A'; - return 0; -} - -static int get_ether_addr(const char *str, u8 *dev_addr) -{ - if (str) { - unsigned i; - - for (i = 0; i < 6; i++) { - unsigned char num; - - if ((*str == '.') || (*str == ':')) - str++; - num = nibble(*str++) << 4; - num |= (nibble(*str++)); - dev_addr[i] = num; - } - if (is_valid_ether_addr(dev_addr)) - return 0; - } - return 1; -} - -static int eth_bind(struct usb_gadget *gadget) -{ - struct eth_dev *dev = &l_ethdev; - u8 cdc = 1, zlp = 1, rndis = 1; - struct usb_ep *in_ep, *out_ep, *status_ep = NULL; - int status = -ENOMEM; - int gcnum; - u8 tmp[7]; - - /* these flags are only ever cleared; compiler take note */ -#ifndef CONFIG_USB_ETH_CDC - cdc = 0; -#endif -#ifndef CONFIG_USB_ETH_RNDIS - rndis = 0; -#endif - /* - * Because most host side USB stacks handle CDC Ethernet, that - * standard protocol is _strongly_ preferred for interop purposes. - * (By everyone except Microsoft.) - */ - if (gadget_is_pxa(gadget)) { - /* pxa doesn't support altsettings */ - cdc = 0; - } else if (gadget_is_musbhdrc(gadget)) { - /* reduce tx dma overhead by avoiding special cases */ - zlp = 0; - } else if (gadget_is_sh(gadget)) { - /* sh doesn't support multiple interfaces or configs */ - cdc = 0; - rndis = 0; - } else if (gadget_is_sa1100(gadget)) { - /* hardware can't write zlps */ - zlp = 0; - /* - * sa1100 CAN do CDC, without status endpoint ... we use - * non-CDC to be compatible with ARM Linux-2.4 "usb-eth". - */ - cdc = 0; - } - - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(0x0300 + gcnum); - else { - /* - * can't assume CDC works. don't want to default to - * anything less functional on CDC-capable hardware, - * so we fail in this case. - */ - error("controller '%s' not recognized", - gadget->name); - return -ENODEV; - } - - /* - * If there's an RNDIS configuration, that's what Windows wants to - * be using ... so use these product IDs here and in the "linux.inf" - * needed to install MSFT drivers. Current Linux kernels will use - * the second configuration if it's CDC Ethernet, and need some help - * to choose the right configuration otherwise. - */ - if (rndis) { -#if defined(CONFIG_USB_RNDIS_VENDOR_ID) && defined(CONFIG_USB_RNDIS_PRODUCT_ID) - device_desc.idVendor = - __constant_cpu_to_le16(CONFIG_USB_RNDIS_VENDOR_ID); - device_desc.idProduct = - __constant_cpu_to_le16(CONFIG_USB_RNDIS_PRODUCT_ID); -#else - device_desc.idVendor = - __constant_cpu_to_le16(RNDIS_VENDOR_NUM); - device_desc.idProduct = - __constant_cpu_to_le16(RNDIS_PRODUCT_NUM); -#endif - sprintf(product_desc, "RNDIS/%s", driver_desc); - - /* - * CDC subset ... recognized by Linux since 2.4.10, but Windows - * drivers aren't widely available. (That may be improved by - * supporting one submode of the "SAFE" variant of MDLM.) - */ - } else { -#if defined(CONFIG_USB_CDC_VENDOR_ID) && defined(CONFIG_USB_CDC_PRODUCT_ID) - device_desc.idVendor = cpu_to_le16(CONFIG_USB_CDC_VENDOR_ID); - device_desc.idProduct = cpu_to_le16(CONFIG_USB_CDC_PRODUCT_ID); -#else - if (!cdc) { - device_desc.idVendor = - __constant_cpu_to_le16(SIMPLE_VENDOR_NUM); - device_desc.idProduct = - __constant_cpu_to_le16(SIMPLE_PRODUCT_NUM); - } -#endif - } - /* support optional vendor/distro customization */ - if (bcdDevice) - device_desc.bcdDevice = cpu_to_le16(bcdDevice); - if (iManufacturer) - strlcpy(manufacturer, iManufacturer, sizeof manufacturer); - if (iProduct) - strlcpy(product_desc, iProduct, sizeof product_desc); - if (iSerialNumber) { - device_desc.iSerialNumber = STRING_SERIALNUMBER, - strlcpy(serial_number, iSerialNumber, sizeof serial_number); - } - - /* all we really need is bulk IN/OUT */ - usb_ep_autoconfig_reset(gadget); - in_ep = usb_ep_autoconfig(gadget, &fs_source_desc); - if (!in_ep) { -autoconf_fail: - error("can't autoconfigure on %s\n", - gadget->name); - return -ENODEV; - } - in_ep->driver_data = in_ep; /* claim */ - - out_ep = usb_ep_autoconfig(gadget, &fs_sink_desc); - if (!out_ep) - goto autoconf_fail; - out_ep->driver_data = out_ep; /* claim */ - -#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS) - /* - * CDC Ethernet control interface doesn't require a status endpoint. - * Since some hosts expect one, try to allocate one anyway. - */ - if (cdc || rndis) { - status_ep = usb_ep_autoconfig(gadget, &fs_status_desc); - if (status_ep) { - status_ep->driver_data = status_ep; /* claim */ - } else if (rndis) { - error("can't run RNDIS on %s", gadget->name); - return -ENODEV; -#ifdef CONFIG_USB_ETH_CDC - } else if (cdc) { - control_intf.bNumEndpoints = 0; - /* FIXME remove endpoint from descriptor list */ -#endif - } - } -#endif - - /* one config: cdc, else minimal subset */ - if (!cdc) { - eth_config.bNumInterfaces = 1; - eth_config.iConfiguration = STRING_SUBSET; - - /* - * use functions to set these up, in case we're built to work - * with multiple controllers and must override CDC Ethernet. - */ - fs_subset_descriptors(); - hs_subset_descriptors(); - } - - device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; - usb_gadget_set_selfpowered(gadget); - - /* For now RNDIS is always a second config */ - if (rndis) - device_desc.bNumConfigurations = 2; - - if (gadget_is_dualspeed(gadget)) { - if (rndis) - dev_qualifier.bNumConfigurations = 2; - else if (!cdc) - dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC; - - /* assumes ep0 uses the same value for both speeds ... */ - dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; - - /* and that all endpoints are dual-speed */ - hs_source_desc.bEndpointAddress = - fs_source_desc.bEndpointAddress; - hs_sink_desc.bEndpointAddress = - fs_sink_desc.bEndpointAddress; -#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS) - if (status_ep) - hs_status_desc.bEndpointAddress = - fs_status_desc.bEndpointAddress; -#endif - } - - if (gadget_is_otg(gadget)) { - otg_descriptor.bmAttributes |= USB_OTG_HNP, - eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - eth_config.bMaxPower = 4; -#ifdef CONFIG_USB_ETH_RNDIS - rndis_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - rndis_config.bMaxPower = 4; -#endif - } - - - /* network device setup */ - dev->net = &l_netdev; - - dev->cdc = cdc; - dev->zlp = zlp; - - dev->in_ep = in_ep; - dev->out_ep = out_ep; - dev->status_ep = status_ep; - - /* - * Module params for these addresses should come from ID proms. - * The host side address is used with CDC and RNDIS, and commonly - * ends up in a persistent config database. It's not clear if - * host side code for the SAFE thing cares -- its original BLAN - * thing didn't, Sharp never assigned those addresses on Zaurii. - */ - get_ether_addr(dev_addr, dev->net->enetaddr); - - memset(tmp, 0, sizeof(tmp)); - memcpy(tmp, dev->net->enetaddr, sizeof(dev->net->enetaddr)); - - get_ether_addr(host_addr, dev->host_mac); - - sprintf(ethaddr, "%02X%02X%02X%02X%02X%02X", - dev->host_mac[0], dev->host_mac[1], - dev->host_mac[2], dev->host_mac[3], - dev->host_mac[4], dev->host_mac[5]); - - if (rndis) { - status = rndis_init(); - if (status < 0) { - error("can't init RNDIS, %d", status); - goto fail; - } - } - - /* - * use PKTSIZE (or aligned... from u-boot) and set - * wMaxSegmentSize accordingly - */ - dev->mtu = PKTSIZE_ALIGN; /* RNDIS does not like this, only 1514, TODO*/ - - /* preallocate control message data and buffer */ - dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); - if (!dev->req) - goto fail; - dev->req->buf = control_req; - dev->req->complete = eth_setup_complete; - - /* ... and maybe likewise for status transfer */ -#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS) - if (dev->status_ep) { - dev->stat_req = usb_ep_alloc_request(dev->status_ep, - GFP_KERNEL); - if (!dev->stat_req) { - usb_ep_free_request(dev->status_ep, dev->req); - - goto fail; - } - dev->stat_req->buf = status_req; - dev->stat_req->context = NULL; - } -#endif - - /* finish hookup to lower layer ... */ - dev->gadget = gadget; - set_gadget_data(gadget, dev); - gadget->ep0->driver_data = dev; - - /* - * two kinds of host-initiated state changes: - * - iff DATA transfer is active, carrier is "on" - * - tx queueing enabled if open *and* carrier is "on" - */ - - printf("using %s, OUT %s IN %s%s%s\n", gadget->name, - out_ep->name, in_ep->name, - status_ep ? " STATUS " : "", - status_ep ? status_ep->name : "" - ); - printf("MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->net->enetaddr[0], dev->net->enetaddr[1], - dev->net->enetaddr[2], dev->net->enetaddr[3], - dev->net->enetaddr[4], dev->net->enetaddr[5]); - - if (cdc || rndis) - printf("HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->host_mac[0], dev->host_mac[1], - dev->host_mac[2], dev->host_mac[3], - dev->host_mac[4], dev->host_mac[5]); - - if (rndis) { - u32 vendorID = 0; - - /* FIXME RNDIS vendor id == "vendor NIC code" == ? */ - - dev->rndis_config = rndis_register(rndis_control_ack); - if (dev->rndis_config < 0) { -fail0: - eth_unbind(gadget); - debug("RNDIS setup failed\n"); - status = -ENODEV; - goto fail; - } - - /* these set up a lot of the OIDs that RNDIS needs */ - rndis_set_host_mac(dev->rndis_config, dev->host_mac); - if (rndis_set_param_dev(dev->rndis_config, dev->net, dev->mtu, - &dev->stats, &dev->cdc_filter)) - goto fail0; - if (rndis_set_param_vendor(dev->rndis_config, vendorID, - manufacturer)) - goto fail0; - if (rndis_set_param_medium(dev->rndis_config, - NDIS_MEDIUM_802_3, 0)) - goto fail0; - printf("RNDIS ready\n"); - } - return 0; - -fail: - error("%s failed, status = %d", __func__, status); - eth_unbind(gadget); - return status; -} - -/*-------------------------------------------------------------------------*/ - -static int usb_eth_init(struct eth_device *netdev, bd_t *bd) -{ - struct eth_dev *dev = &l_ethdev; - struct usb_gadget *gadget; - unsigned long ts; - unsigned long timeout = USB_CONNECT_TIMEOUT; - - if (!netdev) { - error("received NULL ptr"); - goto fail; - } - - /* Configure default mac-addresses for the USB ethernet device */ -#ifdef CONFIG_USBNET_DEV_ADDR - strlcpy(dev_addr, CONFIG_USBNET_DEV_ADDR, sizeof(dev_addr)); -#endif -#ifdef CONFIG_USBNET_HOST_ADDR - strlcpy(host_addr, CONFIG_USBNET_HOST_ADDR, sizeof(host_addr)); -#endif - /* Check if the user overruled the MAC addresses */ - if (getenv("usbnet_devaddr")) - strlcpy(dev_addr, getenv("usbnet_devaddr"), - sizeof(dev_addr)); - - if (getenv("usbnet_hostaddr")) - strlcpy(host_addr, getenv("usbnet_hostaddr"), - sizeof(host_addr)); - - if (!is_eth_addr_valid(dev_addr)) { - error("Need valid 'usbnet_devaddr' to be set"); - goto fail; - } - if (!is_eth_addr_valid(host_addr)) { - error("Need valid 'usbnet_hostaddr' to be set"); - goto fail; - } - - if (usb_gadget_register_driver(ð_driver) < 0) - goto fail; - - dev->network_started = 0; - - packet_received = 0; - packet_sent = 0; - - gadget = dev->gadget; - usb_gadget_connect(gadget); - - if (getenv("cdc_connect_timeout")) - timeout = simple_strtoul(getenv("cdc_connect_timeout"), - NULL, 10) * CONFIG_SYS_HZ; - ts = get_timer(0); - while (!l_ethdev.network_started) { - /* Handle control-c and timeouts */ - if (ctrlc() || (get_timer(ts) > timeout)) { - error("The remote end did not respond in time."); - goto fail; - } - usb_gadget_handle_interrupts(); - } - - packet_received = 0; - rx_submit(dev, dev->rx_req, 0); - return 0; -fail: - return -1; -} - -static int usb_eth_send(struct eth_device *netdev, void *packet, int length) -{ - int retval; - void *rndis_pkt = NULL; - struct eth_dev *dev = &l_ethdev; - struct usb_request *req = dev->tx_req; - unsigned long ts; - unsigned long timeout = USB_CONNECT_TIMEOUT; - - debug("%s:...\n", __func__); - - /* new buffer is needed to include RNDIS header */ - if (rndis_active(dev)) { - rndis_pkt = malloc(length + - sizeof(struct rndis_packet_msg_type)); - if (!rndis_pkt) { - error("No memory to alloc RNDIS packet"); - goto drop; - } - rndis_add_hdr(rndis_pkt, length); - memcpy(rndis_pkt + sizeof(struct rndis_packet_msg_type), - packet, length); - packet = rndis_pkt; - length += sizeof(struct rndis_packet_msg_type); - } - req->buf = packet; - req->context = NULL; - req->complete = tx_complete; - - /* - * use zlp framing on tx for strict CDC-Ether conformance, - * though any robust network rx path ignores extra padding. - * and some hardware doesn't like to write zlps. - */ - req->zero = 1; - if (!dev->zlp && (length % dev->in_ep->maxpacket) == 0) - length++; - - req->length = length; -#if 0 - /* throttle highspeed IRQ rate back slightly */ - if (gadget_is_dualspeed(dev->gadget)) - req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH) - ? ((dev->tx_qlen % qmult) != 0) : 0; -#endif - dev->tx_qlen = 1; - ts = get_timer(0); - packet_sent = 0; - - retval = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC); - - if (!retval) - debug("%s: packet queued\n", __func__); - while (!packet_sent) { - if (get_timer(ts) > timeout) { - printf("timeout sending packets to usb ethernet\n"); - return -1; - } - usb_gadget_handle_interrupts(); - } - if (rndis_pkt) - free(rndis_pkt); - - return 0; -drop: - dev->stats.tx_dropped++; - return -ENOMEM; -} - -static int usb_eth_recv(struct eth_device *netdev) -{ - struct eth_dev *dev = &l_ethdev; - - usb_gadget_handle_interrupts(); - - if (packet_received) { - debug("%s: packet received\n", __func__); - if (dev->rx_req) { - NetReceive(NetRxPackets[0], dev->rx_req->length); - packet_received = 0; - - rx_submit(dev, dev->rx_req, 0); - } else - error("dev->rx_req invalid"); - } - return 0; -} - -void usb_eth_halt(struct eth_device *netdev) -{ - struct eth_dev *dev = &l_ethdev; - - if (!netdev) { - error("received NULL ptr"); - return; - } - - /* If the gadget not registered, simple return */ - if (!dev->gadget) - return; - - /* - * Some USB controllers may need additional deinitialization here - * before dropping pull-up (also due to hardware issues). - * For example: unhandled interrupt with status stage started may - * bring the controller to fully broken state (until board reset). - * There are some variants to debug and fix such cases: - * 1) In the case of RNDIS connection eth_stop can perform additional - * interrupt handling. See RNDIS_COMPLETE_SIGNAL_DISCONNECT definition. - * 2) 'pullup' callback in your UDC driver can be improved to perform - * this deinitialization. - */ - eth_stop(dev); - - usb_gadget_disconnect(dev->gadget); - - /* Clear pending interrupt */ - if (dev->network_started) { - usb_gadget_handle_interrupts(); - dev->network_started = 0; - } - - usb_gadget_unregister_driver(ð_driver); -} - -static struct usb_gadget_driver eth_driver = { - .speed = DEVSPEED, - - .bind = eth_bind, - .unbind = eth_unbind, - - .setup = eth_setup, - .disconnect = eth_disconnect, - - .suspend = eth_suspend, - .resume = eth_resume, -}; - -int usb_eth_initialize(bd_t *bi) -{ - struct eth_device *netdev = &l_netdev; - - strlcpy(netdev->name, USB_NET_NAME, sizeof(netdev->name)); - - netdev->init = usb_eth_init; - netdev->send = usb_eth_send; - netdev->recv = usb_eth_recv; - netdev->halt = usb_eth_halt; - -#ifdef CONFIG_MCAST_TFTP - #error not supported -#endif - eth_register(netdev); - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/f_dfu.c b/qemu/roms/u-boot/drivers/usb/gadget/f_dfu.c deleted file mode 100644 index 1b1e1793d..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/f_dfu.c +++ /dev/null @@ -1,822 +0,0 @@ -/* - * f_dfu.c -- Device Firmware Update USB function - * - * Copyright (C) 2012 Samsung Electronics - * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com> - * Lukasz Majewski <l.majewski@samsung.com> - * - * Based on OpenMoko u-boot: drivers/usb/usbdfu.c - * (C) 2007 by OpenMoko, Inc. - * Author: Harald Welte <laforge@openmoko.org> - * - * based on existing SAM7DFU code from OpenPCD: - * (C) Copyright 2006 by Harald Welte <hwelte at hmw-consulting.de> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <errno.h> -#include <common.h> -#include <malloc.h> - -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <linux/usb/composite.h> - -#include <dfu.h> -#include <g_dnl.h> -#include "f_dfu.h" - -struct f_dfu { - struct usb_function usb_function; - - struct usb_descriptor_header **function; - struct usb_string *strings; - - /* when configured, we have one config */ - u8 config; - u8 altsetting; - enum dfu_state dfu_state; - unsigned int dfu_status; - - /* Send/received block number is handy for data integrity check */ - int blk_seq_num; - unsigned int poll_timeout; -}; - -typedef int (*dfu_state_fn) (struct f_dfu *, - const struct usb_ctrlrequest *, - struct usb_gadget *, - struct usb_request *); - -static inline struct f_dfu *func_to_dfu(struct usb_function *f) -{ - return container_of(f, struct f_dfu, usb_function); -} - -static const struct dfu_function_descriptor dfu_func = { - .bLength = sizeof dfu_func, - .bDescriptorType = DFU_DT_FUNC, - .bmAttributes = DFU_BIT_WILL_DETACH | - DFU_BIT_MANIFESTATION_TOLERANT | - DFU_BIT_CAN_UPLOAD | - DFU_BIT_CAN_DNLOAD, - .wDetachTimeOut = 0, - .wTransferSize = DFU_USB_BUFSIZ, - .bcdDFUVersion = __constant_cpu_to_le16(0x0110), -}; - -static struct usb_interface_descriptor dfu_intf_runtime = { - .bLength = sizeof dfu_intf_runtime, - .bDescriptorType = USB_DT_INTERFACE, - .bNumEndpoints = 0, - .bInterfaceClass = USB_CLASS_APP_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 1, - /* .iInterface = DYNAMIC */ -}; - -static struct usb_descriptor_header *dfu_runtime_descs[] = { - (struct usb_descriptor_header *) &dfu_intf_runtime, - NULL, -}; - -static const struct usb_qualifier_descriptor dev_qualifier = { - .bLength = sizeof dev_qualifier, - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = __constant_cpu_to_le16(0x0200), - .bDeviceClass = USB_CLASS_VENDOR_SPEC, - .bNumConfigurations = 1, -}; - -static const char dfu_name[] = "Device Firmware Upgrade"; - -/* - * static strings, in UTF-8 - * - * dfu_generic configuration - */ -static struct usb_string strings_dfu_generic[] = { - [0].s = dfu_name, - { } /* end of list */ -}; - -static struct usb_gadget_strings stringtab_dfu_generic = { - .language = 0x0409, /* en-us */ - .strings = strings_dfu_generic, -}; - -static struct usb_gadget_strings *dfu_generic_strings[] = { - &stringtab_dfu_generic, - NULL, -}; - -/* - * usb_function specific - */ -static struct usb_gadget_strings stringtab_dfu = { - .language = 0x0409, /* en-us */ - /* - * .strings - * - * assigned during initialization, - * depends on number of flash entities - * - */ -}; - -static struct usb_gadget_strings *dfu_strings[] = { - &stringtab_dfu, - NULL, -}; - -static void dfu_set_poll_timeout(struct dfu_status *dstat, unsigned int ms) -{ - /* - * The bwPollTimeout DFU_GETSTATUS request payload provides information - * about minimum time, in milliseconds, that the host should wait before - * sending a subsequent DFU_GETSTATUS request - * - * This permits the device to vary the delay depending on its need to - * erase or program the memory - * - */ - - unsigned char *p = (unsigned char *)&ms; - - if (!ms || (ms & ~DFU_POLL_TIMEOUT_MASK)) { - dstat->bwPollTimeout[0] = 0; - dstat->bwPollTimeout[1] = 0; - dstat->bwPollTimeout[2] = 0; - - return; - } - - dstat->bwPollTimeout[0] = *p++; - dstat->bwPollTimeout[1] = *p++; - dstat->bwPollTimeout[2] = *p; -} - -/*-------------------------------------------------------------------------*/ - -static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct f_dfu *f_dfu = req->context; - - dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf, - req->length, f_dfu->blk_seq_num); -} - -static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req) -{ - struct f_dfu *f_dfu = req->context; - - dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf, - req->length, f_dfu->blk_seq_num); -} - -static void handle_getstatus(struct usb_request *req) -{ - struct dfu_status *dstat = (struct dfu_status *)req->buf; - struct f_dfu *f_dfu = req->context; - - dfu_set_poll_timeout(dstat, 0); - - switch (f_dfu->dfu_state) { - case DFU_STATE_dfuDNLOAD_SYNC: - case DFU_STATE_dfuDNBUSY: - f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE; - break; - case DFU_STATE_dfuMANIFEST_SYNC: - f_dfu->dfu_state = DFU_STATE_dfuMANIFEST; - break; - case DFU_STATE_dfuMANIFEST: - dfu_set_poll_timeout(dstat, DFU_MANIFEST_POLL_TIMEOUT); - default: - break; - } - - if (f_dfu->poll_timeout) - if (!(f_dfu->blk_seq_num % - (dfu_get_buf_size() / DFU_USB_BUFSIZ))) - dfu_set_poll_timeout(dstat, f_dfu->poll_timeout); - - /* send status response */ - dstat->bStatus = f_dfu->dfu_status; - dstat->bState = f_dfu->dfu_state; - dstat->iString = 0; -} - -static void handle_getstate(struct usb_request *req) -{ - struct f_dfu *f_dfu = req->context; - - ((u8 *)req->buf)[0] = f_dfu->dfu_state; - req->actual = sizeof(u8); -} - -static inline void to_dfu_mode(struct f_dfu *f_dfu) -{ - f_dfu->usb_function.strings = dfu_strings; - f_dfu->usb_function.hs_descriptors = f_dfu->function; - f_dfu->dfu_state = DFU_STATE_dfuIDLE; -} - -static inline void to_runtime_mode(struct f_dfu *f_dfu) -{ - f_dfu->usb_function.strings = NULL; - f_dfu->usb_function.hs_descriptors = dfu_runtime_descs; -} - -static int handle_upload(struct usb_request *req, u16 len) -{ - struct f_dfu *f_dfu = req->context; - - return dfu_read(dfu_get_entity(f_dfu->altsetting), req->buf, - req->length, f_dfu->blk_seq_num); -} - -static int handle_dnload(struct usb_gadget *gadget, u16 len) -{ - struct usb_composite_dev *cdev = get_gadget_data(gadget); - struct usb_request *req = cdev->req; - struct f_dfu *f_dfu = req->context; - - if (len == 0) - f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC; - - req->complete = dnload_request_complete; - - return len; -} - -/*-------------------------------------------------------------------------*/ -/* DFU state machine */ -static int state_app_idle(struct f_dfu *f_dfu, - const struct usb_ctrlrequest *ctrl, - struct usb_gadget *gadget, - struct usb_request *req) -{ - int value = 0; - - switch (ctrl->bRequest) { - case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; - break; - case USB_REQ_DFU_GETSTATE: - handle_getstate(req); - break; - case USB_REQ_DFU_DETACH: - f_dfu->dfu_state = DFU_STATE_appDETACH; - to_dfu_mode(f_dfu); - value = RET_ZLP; - break; - default: - value = RET_STALL; - break; - } - - return value; -} - -static int state_app_detach(struct f_dfu *f_dfu, - const struct usb_ctrlrequest *ctrl, - struct usb_gadget *gadget, - struct usb_request *req) -{ - int value = 0; - - switch (ctrl->bRequest) { - case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; - break; - case USB_REQ_DFU_GETSTATE: - handle_getstate(req); - break; - default: - f_dfu->dfu_state = DFU_STATE_appIDLE; - value = RET_STALL; - break; - } - - return value; -} - -static int state_dfu_idle(struct f_dfu *f_dfu, - const struct usb_ctrlrequest *ctrl, - struct usb_gadget *gadget, - struct usb_request *req) -{ - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 len = le16_to_cpu(ctrl->wLength); - int value = 0; - - switch (ctrl->bRequest) { - case USB_REQ_DFU_DNLOAD: - if (len == 0) { - f_dfu->dfu_state = DFU_STATE_dfuERROR; - value = RET_STALL; - break; - } - f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; - f_dfu->blk_seq_num = w_value; - value = handle_dnload(gadget, len); - break; - case USB_REQ_DFU_UPLOAD: - f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE; - f_dfu->blk_seq_num = 0; - value = handle_upload(req, len); - break; - case USB_REQ_DFU_ABORT: - /* no zlp? */ - value = RET_ZLP; - break; - case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; - break; - case USB_REQ_DFU_GETSTATE: - handle_getstate(req); - break; - case USB_REQ_DFU_DETACH: - /* - * Proprietary extension: 'detach' from idle mode and - * get back to runtime mode in case of USB Reset. As - * much as I dislike this, we just can't use every USB - * bus reset to switch back to runtime mode, since at - * least the Linux USB stack likes to send a number of - * resets in a row :( - */ - f_dfu->dfu_state = - DFU_STATE_dfuMANIFEST_WAIT_RST; - to_runtime_mode(f_dfu); - f_dfu->dfu_state = DFU_STATE_appIDLE; - - dfu_trigger_reset(); - break; - default: - f_dfu->dfu_state = DFU_STATE_dfuERROR; - value = RET_STALL; - break; - } - - return value; -} - -static int state_dfu_dnload_sync(struct f_dfu *f_dfu, - const struct usb_ctrlrequest *ctrl, - struct usb_gadget *gadget, - struct usb_request *req) -{ - int value = 0; - - switch (ctrl->bRequest) { - case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; - break; - case USB_REQ_DFU_GETSTATE: - handle_getstate(req); - break; - default: - f_dfu->dfu_state = DFU_STATE_dfuERROR; - value = RET_STALL; - break; - } - - return value; -} - -static int state_dfu_dnbusy(struct f_dfu *f_dfu, - const struct usb_ctrlrequest *ctrl, - struct usb_gadget *gadget, - struct usb_request *req) -{ - int value = 0; - - switch (ctrl->bRequest) { - case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; - break; - default: - f_dfu->dfu_state = DFU_STATE_dfuERROR; - value = RET_STALL; - break; - } - - return value; -} - -static int state_dfu_dnload_idle(struct f_dfu *f_dfu, - const struct usb_ctrlrequest *ctrl, - struct usb_gadget *gadget, - struct usb_request *req) -{ - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 len = le16_to_cpu(ctrl->wLength); - int value = 0; - - switch (ctrl->bRequest) { - case USB_REQ_DFU_DNLOAD: - f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; - f_dfu->blk_seq_num = w_value; - value = handle_dnload(gadget, len); - break; - case USB_REQ_DFU_ABORT: - f_dfu->dfu_state = DFU_STATE_dfuIDLE; - value = RET_ZLP; - break; - case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; - break; - case USB_REQ_DFU_GETSTATE: - handle_getstate(req); - break; - default: - f_dfu->dfu_state = DFU_STATE_dfuERROR; - value = RET_STALL; - break; - } - - return value; -} - -static int state_dfu_manifest_sync(struct f_dfu *f_dfu, - const struct usb_ctrlrequest *ctrl, - struct usb_gadget *gadget, - struct usb_request *req) -{ - int value = 0; - - switch (ctrl->bRequest) { - case USB_REQ_DFU_GETSTATUS: - /* We're MainfestationTolerant */ - f_dfu->dfu_state = DFU_STATE_dfuMANIFEST; - handle_getstatus(req); - f_dfu->blk_seq_num = 0; - value = RET_STAT_LEN; - req->complete = dnload_request_flush; - break; - case USB_REQ_DFU_GETSTATE: - handle_getstate(req); - break; - default: - f_dfu->dfu_state = DFU_STATE_dfuERROR; - value = RET_STALL; - break; - } - - return value; -} - -static int state_dfu_manifest(struct f_dfu *f_dfu, - const struct usb_ctrlrequest *ctrl, - struct usb_gadget *gadget, - struct usb_request *req) -{ - int value = 0; - - switch (ctrl->bRequest) { - case USB_REQ_DFU_GETSTATUS: - /* We're MainfestationTolerant */ - f_dfu->dfu_state = DFU_STATE_dfuIDLE; - handle_getstatus(req); - f_dfu->blk_seq_num = 0; - value = RET_STAT_LEN; - puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n"); - break; - case USB_REQ_DFU_GETSTATE: - handle_getstate(req); - break; - default: - f_dfu->dfu_state = DFU_STATE_dfuERROR; - value = RET_STALL; - break; - } - return value; -} - -static int state_dfu_upload_idle(struct f_dfu *f_dfu, - const struct usb_ctrlrequest *ctrl, - struct usb_gadget *gadget, - struct usb_request *req) -{ - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 len = le16_to_cpu(ctrl->wLength); - int value = 0; - - switch (ctrl->bRequest) { - case USB_REQ_DFU_UPLOAD: - /* state transition if less data then requested */ - f_dfu->blk_seq_num = w_value; - value = handle_upload(req, len); - if (value >= 0 && value < len) - f_dfu->dfu_state = DFU_STATE_dfuIDLE; - break; - case USB_REQ_DFU_ABORT: - f_dfu->dfu_state = DFU_STATE_dfuIDLE; - /* no zlp? */ - value = RET_ZLP; - break; - case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; - break; - case USB_REQ_DFU_GETSTATE: - handle_getstate(req); - break; - default: - f_dfu->dfu_state = DFU_STATE_dfuERROR; - value = RET_STALL; - break; - } - - return value; -} - -static int state_dfu_error(struct f_dfu *f_dfu, - const struct usb_ctrlrequest *ctrl, - struct usb_gadget *gadget, - struct usb_request *req) -{ - int value = 0; - - switch (ctrl->bRequest) { - case USB_REQ_DFU_GETSTATUS: - handle_getstatus(req); - value = RET_STAT_LEN; - break; - case USB_REQ_DFU_GETSTATE: - handle_getstate(req); - break; - case USB_REQ_DFU_CLRSTATUS: - f_dfu->dfu_state = DFU_STATE_dfuIDLE; - f_dfu->dfu_status = DFU_STATUS_OK; - /* no zlp? */ - value = RET_ZLP; - break; - default: - f_dfu->dfu_state = DFU_STATE_dfuERROR; - value = RET_STALL; - break; - } - - return value; -} - -static dfu_state_fn dfu_state[] = { - state_app_idle, /* DFU_STATE_appIDLE */ - state_app_detach, /* DFU_STATE_appDETACH */ - state_dfu_idle, /* DFU_STATE_dfuIDLE */ - state_dfu_dnload_sync, /* DFU_STATE_dfuDNLOAD_SYNC */ - state_dfu_dnbusy, /* DFU_STATE_dfuDNBUSY */ - state_dfu_dnload_idle, /* DFU_STATE_dfuDNLOAD_IDLE */ - state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */ - state_dfu_manifest, /* DFU_STATE_dfuMANIFEST */ - NULL, /* DFU_STATE_dfuMANIFEST_WAIT_RST */ - state_dfu_upload_idle, /* DFU_STATE_dfuUPLOAD_IDLE */ - state_dfu_error /* DFU_STATE_dfuERROR */ -}; - -static int -dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl) -{ - struct usb_gadget *gadget = f->config->cdev->gadget; - struct usb_request *req = f->config->cdev->req; - struct f_dfu *f_dfu = f->config->cdev->req->context; - u16 len = le16_to_cpu(ctrl->wLength); - u16 w_value = le16_to_cpu(ctrl->wValue); - int value = 0; - u8 req_type = ctrl->bRequestType & USB_TYPE_MASK; - - debug("w_value: 0x%x len: 0x%x\n", w_value, len); - debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n", - req_type, ctrl->bRequest, f_dfu->dfu_state); - - if (req_type == USB_TYPE_STANDARD) { - if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR && - (w_value >> 8) == DFU_DT_FUNC) { - value = min(len, (u16) sizeof(dfu_func)); - memcpy(req->buf, &dfu_func, value); - } - } else /* DFU specific request */ - value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req); - - if (value >= 0) { - req->length = value; - req->zero = value < len; - value = usb_ep_queue(gadget->ep0, req, 0); - if (value < 0) { - debug("ep_queue --> %d\n", value); - req->status = 0; - } - } - - return value; -} - -/*-------------------------------------------------------------------------*/ - -static int -dfu_prepare_strings(struct f_dfu *f_dfu, int n) -{ - struct dfu_entity *de = NULL; - int i = 0; - - f_dfu->strings = calloc(sizeof(struct usb_string), n + 1); - if (!f_dfu->strings) - goto enomem; - - for (i = 0; i < n; ++i) { - de = dfu_get_entity(i); - f_dfu->strings[i].s = de->name; - } - - f_dfu->strings[i].id = 0; - f_dfu->strings[i].s = NULL; - - return 0; - -enomem: - while (i) - f_dfu->strings[--i].s = NULL; - - free(f_dfu->strings); - - return -ENOMEM; -} - -static int dfu_prepare_function(struct f_dfu *f_dfu, int n) -{ - struct usb_interface_descriptor *d; - int i = 0; - - f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 1); - if (!f_dfu->function) - goto enomem; - - for (i = 0; i < n; ++i) { - d = calloc(sizeof(*d), 1); - if (!d) - goto enomem; - - d->bLength = sizeof(*d); - d->bDescriptorType = USB_DT_INTERFACE; - d->bAlternateSetting = i; - d->bNumEndpoints = 0; - d->bInterfaceClass = USB_CLASS_APP_SPEC; - d->bInterfaceSubClass = 1; - d->bInterfaceProtocol = 2; - - f_dfu->function[i] = (struct usb_descriptor_header *)d; - } - f_dfu->function[i] = NULL; - - return 0; - -enomem: - while (i) { - free(f_dfu->function[--i]); - f_dfu->function[i] = NULL; - } - free(f_dfu->function); - - return -ENOMEM; -} - -static int dfu_bind(struct usb_configuration *c, struct usb_function *f) -{ - struct usb_composite_dev *cdev = c->cdev; - struct f_dfu *f_dfu = func_to_dfu(f); - int alt_num = dfu_get_alt_number(); - int rv, id, i; - - id = usb_interface_id(c, f); - if (id < 0) - return id; - dfu_intf_runtime.bInterfaceNumber = id; - - f_dfu->dfu_state = DFU_STATE_appIDLE; - f_dfu->dfu_status = DFU_STATUS_OK; - - rv = dfu_prepare_function(f_dfu, alt_num); - if (rv) - goto error; - - rv = dfu_prepare_strings(f_dfu, alt_num); - if (rv) - goto error; - for (i = 0; i < alt_num; i++) { - id = usb_string_id(cdev); - if (id < 0) - return id; - f_dfu->strings[i].id = id; - ((struct usb_interface_descriptor *)f_dfu->function[i]) - ->iInterface = id; - } - - to_dfu_mode(f_dfu); - - stringtab_dfu.strings = f_dfu->strings; - - cdev->req->context = f_dfu; - -error: - return rv; -} - -static void dfu_unbind(struct usb_configuration *c, struct usb_function *f) -{ - struct f_dfu *f_dfu = func_to_dfu(f); - int alt_num = dfu_get_alt_number(); - int i; - - if (f_dfu->strings) { - i = alt_num; - while (i) - f_dfu->strings[--i].s = NULL; - - free(f_dfu->strings); - } - - if (f_dfu->function) { - i = alt_num; - while (i) { - free(f_dfu->function[--i]); - f_dfu->function[i] = NULL; - } - free(f_dfu->function); - } - - free(f_dfu); -} - -static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt) -{ - struct f_dfu *f_dfu = func_to_dfu(f); - - debug("%s: intf:%d alt:%d\n", __func__, intf, alt); - - f_dfu->altsetting = alt; - - return 0; -} - -/* TODO: is this really what we need here? */ -static void dfu_disable(struct usb_function *f) -{ - struct f_dfu *f_dfu = func_to_dfu(f); - if (f_dfu->config == 0) - return; - - debug("%s: reset config\n", __func__); - - f_dfu->config = 0; -} - -static int dfu_bind_config(struct usb_configuration *c) -{ - struct f_dfu *f_dfu; - int status; - - f_dfu = calloc(sizeof(*f_dfu), 1); - if (!f_dfu) - return -ENOMEM; - f_dfu->usb_function.name = "dfu"; - f_dfu->usb_function.hs_descriptors = dfu_runtime_descs; - f_dfu->usb_function.bind = dfu_bind; - f_dfu->usb_function.unbind = dfu_unbind; - f_dfu->usb_function.set_alt = dfu_set_alt; - f_dfu->usb_function.disable = dfu_disable; - f_dfu->usb_function.strings = dfu_generic_strings; - f_dfu->usb_function.setup = dfu_handle; - f_dfu->poll_timeout = DFU_DEFAULT_POLL_TIMEOUT; - - status = usb_add_function(c, &f_dfu->usb_function); - if (status) - free(f_dfu); - - return status; -} - -int dfu_add(struct usb_configuration *c) -{ - int id; - - id = usb_string_id(c->cdev); - if (id < 0) - return id; - strings_dfu_generic[0].id = id; - dfu_intf_runtime.iInterface = id; - - debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__, - c->cdev, c->cdev->gadget, c->cdev->gadget->ep0); - - return dfu_bind_config(c); -} - -DECLARE_GADGET_BIND_CALLBACK(usb_dnl_dfu, dfu_add); diff --git a/qemu/roms/u-boot/drivers/usb/gadget/f_dfu.h b/qemu/roms/u-boot/drivers/usb/gadget/f_dfu.h deleted file mode 100644 index 0c29954ad..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/f_dfu.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * f_dfu.h -- Device Firmware Update gadget - * - * Copyright (C) 2011-2012 Samsung Electronics - * author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __F_DFU_H_ -#define __F_DFU_H_ - -#include <linux/compiler.h> -#include <linux/usb/composite.h> - -#define DFU_CONFIG_VAL 1 -#define DFU_DT_FUNC 0x21 - -#define DFU_BIT_WILL_DETACH (0x1 << 3) -#define DFU_BIT_MANIFESTATION_TOLERANT (0x1 << 2) -#define DFU_BIT_CAN_UPLOAD (0x1 << 1) -#define DFU_BIT_CAN_DNLOAD 0x1 - -/* big enough to hold our biggest descriptor */ -#define DFU_USB_BUFSIZ 4096 - -#define USB_REQ_DFU_DETACH 0x00 -#define USB_REQ_DFU_DNLOAD 0x01 -#define USB_REQ_DFU_UPLOAD 0x02 -#define USB_REQ_DFU_GETSTATUS 0x03 -#define USB_REQ_DFU_CLRSTATUS 0x04 -#define USB_REQ_DFU_GETSTATE 0x05 -#define USB_REQ_DFU_ABORT 0x06 - -#define DFU_STATUS_OK 0x00 -#define DFU_STATUS_errTARGET 0x01 -#define DFU_STATUS_errFILE 0x02 -#define DFU_STATUS_errWRITE 0x03 -#define DFU_STATUS_errERASE 0x04 -#define DFU_STATUS_errCHECK_ERASED 0x05 -#define DFU_STATUS_errPROG 0x06 -#define DFU_STATUS_errVERIFY 0x07 -#define DFU_STATUS_errADDRESS 0x08 -#define DFU_STATUS_errNOTDONE 0x09 -#define DFU_STATUS_errFIRMWARE 0x0a -#define DFU_STATUS_errVENDOR 0x0b -#define DFU_STATUS_errUSBR 0x0c -#define DFU_STATUS_errPOR 0x0d -#define DFU_STATUS_errUNKNOWN 0x0e -#define DFU_STATUS_errSTALLEDPKT 0x0f - -#define RET_STALL -1 -#define RET_ZLP 0 -#define RET_STAT_LEN 6 - -enum dfu_state { - DFU_STATE_appIDLE = 0, - DFU_STATE_appDETACH = 1, - DFU_STATE_dfuIDLE = 2, - DFU_STATE_dfuDNLOAD_SYNC = 3, - DFU_STATE_dfuDNBUSY = 4, - DFU_STATE_dfuDNLOAD_IDLE = 5, - DFU_STATE_dfuMANIFEST_SYNC = 6, - DFU_STATE_dfuMANIFEST = 7, - DFU_STATE_dfuMANIFEST_WAIT_RST = 8, - DFU_STATE_dfuUPLOAD_IDLE = 9, - DFU_STATE_dfuERROR = 10, -}; - -struct dfu_status { - __u8 bStatus; - __u8 bwPollTimeout[3]; - __u8 bState; - __u8 iString; -} __packed; - -struct dfu_function_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bmAttributes; - __le16 wDetachTimeOut; - __le16 wTransferSize; - __le16 bcdDFUVersion; -} __packed; - -#define DFU_POLL_TIMEOUT_MASK (0xFFFFFFUL) -#endif /* __F_DFU_H_ */ diff --git a/qemu/roms/u-boot/drivers/usb/gadget/f_mass_storage.c b/qemu/roms/u-boot/drivers/usb/gadget/f_mass_storage.c deleted file mode 100644 index 6374bb953..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/f_mass_storage.c +++ /dev/null @@ -1,2783 +0,0 @@ -/* - * f_mass_storage.c -- Mass Storage USB Composite Function - * - * Copyright (C) 2003-2008 Alan Stern - * Copyright (C) 2009 Samsung Electronics - * Author: Michal Nazarewicz <m.nazarewicz@samsung.com> - * All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause - */ - -/* - * The Mass Storage Function acts as a USB Mass Storage device, - * appearing to the host as a disk drive or as a CD-ROM drive. In - * addition to providing an example of a genuinely useful composite - * function for a USB device, it also illustrates a technique of - * double-buffering for increased throughput. - * - * Function supports multiple logical units (LUNs). Backing storage - * for each LUN is provided by a regular file or a block device. - * Access for each LUN can be limited to read-only. Moreover, the - * function can indicate that LUN is removable and/or CD-ROM. (The - * later implies read-only access.) - * - * MSF is configured by specifying a fsg_config structure. It has the - * following fields: - * - * nluns Number of LUNs function have (anywhere from 1 - * to FSG_MAX_LUNS which is 8). - * luns An array of LUN configuration values. This - * should be filled for each LUN that - * function will include (ie. for "nluns" - * LUNs). Each element of the array has - * the following fields: - * ->filename The path to the backing file for the LUN. - * Required if LUN is not marked as - * removable. - * ->ro Flag specifying access to the LUN shall be - * read-only. This is implied if CD-ROM - * emulation is enabled as well as when - * it was impossible to open "filename" - * in R/W mode. - * ->removable Flag specifying that LUN shall be indicated as - * being removable. - * ->cdrom Flag specifying that LUN shall be reported as - * being a CD-ROM. - * - * lun_name_format A printf-like format for names of the LUN - * devices. This determines how the - * directory in sysfs will be named. - * Unless you are using several MSFs in - * a single gadget (as opposed to single - * MSF in many configurations) you may - * leave it as NULL (in which case - * "lun%d" will be used). In the format - * you can use "%d" to index LUNs for - * MSF's with more than one LUN. (Beware - * that there is only one integer given - * as an argument for the format and - * specifying invalid format may cause - * unspecified behaviour.) - * thread_name Name of the kernel thread process used by the - * MSF. You can safely set it to NULL - * (in which case default "file-storage" - * will be used). - * - * vendor_name - * product_name - * release Information used as a reply to INQUIRY - * request. To use default set to NULL, - * NULL, 0xffff respectively. The first - * field should be 8 and the second 16 - * characters or less. - * - * can_stall Set to permit function to halt bulk endpoints. - * Disabled on some USB devices known not - * to work correctly. You should set it - * to true. - * - * If "removable" is not set for a LUN then a backing file must be - * specified. If it is set, then NULL filename means the LUN's medium - * is not loaded (an empty string as "filename" in the fsg_config - * structure causes error). The CD-ROM emulation includes a single - * data track and no audio tracks; hence there need be only one - * backing file per LUN. Note also that the CD-ROM block length is - * set to 512 rather than the more common value 2048. - * - * - * MSF includes support for module parameters. If gadget using it - * decides to use it, the following module parameters will be - * available: - * - * file=filename[,filename...] - * Names of the files or block devices used for - * backing storage. - * ro=b[,b...] Default false, boolean for read-only access. - * removable=b[,b...] - * Default true, boolean for removable media. - * cdrom=b[,b...] Default false, boolean for whether to emulate - * a CD-ROM drive. - * luns=N Default N = number of filenames, number of - * LUNs to support. - * stall Default determined according to the type of - * USB device controller (usually true), - * boolean to permit the driver to halt - * bulk endpoints. - * - * The module parameters may be prefixed with some string. You need - * to consult gadget's documentation or source to verify whether it is - * using those module parameters and if it does what are the prefixes - * (look for FSG_MODULE_PARAMETERS() macro usage, what's inside it is - * the prefix). - * - * - * Requirements are modest; only a bulk-in and a bulk-out endpoint are - * needed. The memory requirement amounts to two 16K buffers, size - * configurable by a parameter. Support is included for both - * full-speed and high-speed operation. - * - * Note that the driver is slightly non-portable in that it assumes a - * single memory/DMA buffer will be useable for bulk-in, bulk-out, and - * interrupt-in endpoints. With most device controllers this isn't an - * issue, but there may be some with hardware restrictions that prevent - * a buffer from being used by more than one endpoint. - * - * - * The pathnames of the backing files and the ro settings are - * available in the attribute files "file" and "ro" in the lun<n> (or - * to be more precise in a directory which name comes from - * "lun_name_format" option!) subdirectory of the gadget's sysfs - * directory. If the "removable" option is set, writing to these - * files will simulate ejecting/loading the medium (writing an empty - * line means eject) and adjusting a write-enable tab. Changes to the - * ro setting are not allowed when the medium is loaded or if CD-ROM - * emulation is being used. - * - * When a LUN receive an "eject" SCSI request (Start/Stop Unit), - * if the LUN is removable, the backing file is released to simulate - * ejection. - * - * - * This function is heavily based on "File-backed Storage Gadget" by - * Alan Stern which in turn is heavily based on "Gadget Zero" by David - * Brownell. The driver's SCSI command interface was based on the - * "Information technology - Small Computer System Interface - 2" - * document from X3T9.2 Project 375D, Revision 10L, 7-SEP-93, - * available at <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. - * The single exception is opcode 0x23 (READ FORMAT CAPACITIES), which - * was based on the "Universal Serial Bus Mass Storage Class UFI - * Command Specification" document, Revision 1.0, December 14, 1998, - * available at - * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>. - */ - -/* - * Driver Design - * - * The MSF is fairly straightforward. There is a main kernel - * thread that handles most of the work. Interrupt routines field - * callbacks from the controller driver: bulk- and interrupt-request - * completion notifications, endpoint-0 events, and disconnect events. - * Completion events are passed to the main thread by wakeup calls. Many - * ep0 requests are handled at interrupt time, but SetInterface, - * SetConfiguration, and device reset requests are forwarded to the - * thread in the form of "exceptions" using SIGUSR1 signals (since they - * should interrupt any ongoing file I/O operations). - * - * The thread's main routine implements the standard command/data/status - * parts of a SCSI interaction. It and its subroutines are full of tests - * for pending signals/exceptions -- all this polling is necessary since - * the kernel has no setjmp/longjmp equivalents. (Maybe this is an - * indication that the driver really wants to be running in userspace.) - * An important point is that so long as the thread is alive it keeps an - * open reference to the backing file. This will prevent unmounting - * the backing file's underlying filesystem and could cause problems - * during system shutdown, for example. To prevent such problems, the - * thread catches INT, TERM, and KILL signals and converts them into - * an EXIT exception. - * - * In normal operation the main thread is started during the gadget's - * fsg_bind() callback and stopped during fsg_unbind(). But it can - * also exit when it receives a signal, and there's no point leaving - * the gadget running when the thread is dead. At of this moment, MSF - * provides no way to deregister the gadget when thread dies -- maybe - * a callback functions is needed. - * - * To provide maximum throughput, the driver uses a circular pipeline of - * buffer heads (struct fsg_buffhd). In principle the pipeline can be - * arbitrarily long; in practice the benefits don't justify having more - * than 2 stages (i.e., double buffering). But it helps to think of the - * pipeline as being a long one. Each buffer head contains a bulk-in and - * a bulk-out request pointer (since the buffer can be used for both - * output and input -- directions always are given from the host's - * point of view) as well as a pointer to the buffer and various state - * variables. - * - * Use of the pipeline follows a simple protocol. There is a variable - * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. - * At any time that buffer head may still be in use from an earlier - * request, so each buffer head has a state variable indicating whether - * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the - * buffer head to be EMPTY, filling the buffer either by file I/O or by - * USB I/O (during which the buffer head is BUSY), and marking the buffer - * head FULL when the I/O is complete. Then the buffer will be emptied - * (again possibly by USB I/O, during which it is marked BUSY) and - * finally marked EMPTY again (possibly by a completion routine). - * - * A module parameter tells the driver to avoid stalling the bulk - * endpoints wherever the transport specification allows. This is - * necessary for some UDCs like the SuperH, which cannot reliably clear a - * halt on a bulk endpoint. However, under certain circumstances the - * Bulk-only specification requires a stall. In such cases the driver - * will halt the endpoint and set a flag indicating that it should clear - * the halt in software during the next device reset. Hopefully this - * will permit everything to work correctly. Furthermore, although the - * specification allows the bulk-out endpoint to halt when the host sends - * too much data, implementing this would cause an unavoidable race. - * The driver will always use the "no-stall" approach for OUT transfers. - * - * One subtle point concerns sending status-stage responses for ep0 - * requests. Some of these requests, such as device reset, can involve - * interrupting an ongoing file I/O operation, which might take an - * arbitrarily long time. During that delay the host might give up on - * the original ep0 request and issue a new one. When that happens the - * driver should not notify the host about completion of the original - * request, as the host will no longer be waiting for it. So the driver - * assigns to each ep0 request a unique tag, and it keeps track of the - * tag value of the request associated with a long-running exception - * (device-reset, interface-change, or configuration-change). When the - * exception handler is finished, the status-stage response is submitted - * only if the current ep0 request tag is equal to the exception request - * tag. Thus only the most recently received ep0 request will get a - * status-stage response. - * - * Warning: This driver source file is too long. It ought to be split up - * into a header file plus about 3 separate .c files, to handle the details - * of the Gadget, USB Mass Storage, and SCSI protocols. - */ - -/* #define VERBOSE_DEBUG */ -/* #define DUMP_MSGS */ - -#include <config.h> -#include <malloc.h> -#include <common.h> -#include <g_dnl.h> - -#include <linux/err.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <usb_mass_storage.h> - -#include <asm/unaligned.h> -#include <linux/usb/gadget.h> -#include <linux/usb/gadget.h> -#include <linux/usb/composite.h> -#include <usb/lin_gadget_compat.h> -#include <g_dnl.h> - -/*------------------------------------------------------------------------*/ - -#define FSG_DRIVER_DESC "Mass Storage Function" -#define FSG_DRIVER_VERSION "2012/06/5" - -static const char fsg_string_interface[] = "Mass Storage"; - -#define FSG_NO_INTR_EP 1 -#define FSG_NO_DEVICE_STRINGS 1 -#define FSG_NO_OTG 1 -#define FSG_NO_INTR_EP 1 - -#include "storage_common.c" - -/*-------------------------------------------------------------------------*/ - -#define GFP_ATOMIC ((gfp_t) 0) -#define PAGE_CACHE_SHIFT 12 -#define PAGE_CACHE_SIZE (1 << PAGE_CACHE_SHIFT) -#define kthread_create(...) __builtin_return_address(0) -#define wait_for_completion(...) do {} while (0) - -struct kref {int x; }; -struct completion {int x; }; - -inline void set_bit(int nr, volatile void *addr) -{ - int mask; - unsigned int *a = (unsigned int *) addr; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - *a |= mask; -} - -inline void clear_bit(int nr, volatile void *addr) -{ - int mask; - unsigned int *a = (unsigned int *) addr; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - *a &= ~mask; -} - -struct fsg_dev; -struct fsg_common; - -/* Data shared by all the FSG instances. */ -struct fsg_common { - struct usb_gadget *gadget; - struct fsg_dev *fsg, *new_fsg; - - struct usb_ep *ep0; /* Copy of gadget->ep0 */ - struct usb_request *ep0req; /* Copy of cdev->req */ - unsigned int ep0_req_tag; - - struct fsg_buffhd *next_buffhd_to_fill; - struct fsg_buffhd *next_buffhd_to_drain; - struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; - - int cmnd_size; - u8 cmnd[MAX_COMMAND_SIZE]; - - unsigned int nluns; - unsigned int lun; - struct fsg_lun luns[FSG_MAX_LUNS]; - - unsigned int bulk_out_maxpacket; - enum fsg_state state; /* For exception handling */ - unsigned int exception_req_tag; - - enum data_direction data_dir; - u32 data_size; - u32 data_size_from_cmnd; - u32 tag; - u32 residue; - u32 usb_amount_left; - - unsigned int can_stall:1; - unsigned int free_storage_on_release:1; - unsigned int phase_error:1; - unsigned int short_packet_received:1; - unsigned int bad_lun_okay:1; - unsigned int running:1; - - int thread_wakeup_needed; - struct completion thread_notifier; - struct task_struct *thread_task; - - /* Callback functions. */ - const struct fsg_operations *ops; - /* Gadget's private data. */ - void *private_data; - - const char *vendor_name; /* 8 characters or less */ - const char *product_name; /* 16 characters or less */ - u16 release; - - /* Vendor (8 chars), product (16 chars), release (4 - * hexadecimal digits) and NUL byte */ - char inquiry_string[8 + 16 + 4 + 1]; - - struct kref ref; -}; - -struct fsg_config { - unsigned nluns; - struct fsg_lun_config { - const char *filename; - char ro; - char removable; - char cdrom; - char nofua; - } luns[FSG_MAX_LUNS]; - - /* Callback functions. */ - const struct fsg_operations *ops; - /* Gadget's private data. */ - void *private_data; - - const char *vendor_name; /* 8 characters or less */ - const char *product_name; /* 16 characters or less */ - - char can_stall; -}; - -struct fsg_dev { - struct usb_function function; - struct usb_gadget *gadget; /* Copy of cdev->gadget */ - struct fsg_common *common; - - u16 interface_number; - - unsigned int bulk_in_enabled:1; - unsigned int bulk_out_enabled:1; - - unsigned long atomic_bitflags; -#define IGNORE_BULK_OUT 0 - - struct usb_ep *bulk_in; - struct usb_ep *bulk_out; -}; - - -static inline int __fsg_is_set(struct fsg_common *common, - const char *func, unsigned line) -{ - if (common->fsg) - return 1; - ERROR(common, "common->fsg is NULL in %s at %u\n", func, line); - WARN_ON(1); - return 0; -} - -#define fsg_is_set(common) likely(__fsg_is_set(common, __func__, __LINE__)) - - -static inline struct fsg_dev *fsg_from_func(struct usb_function *f) -{ - return container_of(f, struct fsg_dev, function); -} - - -typedef void (*fsg_routine_t)(struct fsg_dev *); - -static int exception_in_progress(struct fsg_common *common) -{ - return common->state > FSG_STATE_IDLE; -} - -/* Make bulk-out requests be divisible by the maxpacket size */ -static void set_bulk_out_req_length(struct fsg_common *common, - struct fsg_buffhd *bh, unsigned int length) -{ - unsigned int rem; - - bh->bulk_out_intended_length = length; - rem = length % common->bulk_out_maxpacket; - if (rem > 0) - length += common->bulk_out_maxpacket - rem; - bh->outreq->length = length; -} - -/*-------------------------------------------------------------------------*/ - -struct ums *ums; -struct fsg_common *the_fsg_common; - -static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) -{ - const char *name; - - if (ep == fsg->bulk_in) - name = "bulk-in"; - else if (ep == fsg->bulk_out) - name = "bulk-out"; - else - name = ep->name; - DBG(fsg, "%s set halt\n", name); - return usb_ep_set_halt(ep); -} - -/*-------------------------------------------------------------------------*/ - -/* These routines may be called in process context or in_irq */ - -/* Caller must hold fsg->lock */ -static void wakeup_thread(struct fsg_common *common) -{ - common->thread_wakeup_needed = 1; -} - -static void raise_exception(struct fsg_common *common, enum fsg_state new_state) -{ - /* Do nothing if a higher-priority exception is already in progress. - * If a lower-or-equal priority exception is in progress, preempt it - * and notify the main thread by sending it a signal. */ - if (common->state <= new_state) { - common->exception_req_tag = common->ep0_req_tag; - common->state = new_state; - common->thread_wakeup_needed = 1; - } -} - -/*-------------------------------------------------------------------------*/ - -static int ep0_queue(struct fsg_common *common) -{ - int rc; - - rc = usb_ep_queue(common->ep0, common->ep0req, GFP_ATOMIC); - common->ep0->driver_data = common; - if (rc != 0 && rc != -ESHUTDOWN) { - /* We can't do much more than wait for a reset */ - WARNING(common, "error in submission: %s --> %d\n", - common->ep0->name, rc); - } - return rc; -} - -/*-------------------------------------------------------------------------*/ - -/* Bulk and interrupt endpoint completion handlers. - * These always run in_irq. */ - -static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct fsg_common *common = ep->driver_data; - struct fsg_buffhd *bh = req->context; - - if (req->status || req->actual != req->length) - DBG(common, "%s --> %d, %u/%u\n", __func__, - req->status, req->actual, req->length); - if (req->status == -ECONNRESET) /* Request was cancelled */ - usb_ep_fifo_flush(ep); - - /* Hold the lock while we update the request and buffer states */ - bh->inreq_busy = 0; - bh->state = BUF_STATE_EMPTY; - wakeup_thread(common); -} - -static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct fsg_common *common = ep->driver_data; - struct fsg_buffhd *bh = req->context; - - dump_msg(common, "bulk-out", req->buf, req->actual); - if (req->status || req->actual != bh->bulk_out_intended_length) - DBG(common, "%s --> %d, %u/%u\n", __func__, - req->status, req->actual, - bh->bulk_out_intended_length); - if (req->status == -ECONNRESET) /* Request was cancelled */ - usb_ep_fifo_flush(ep); - - /* Hold the lock while we update the request and buffer states */ - bh->outreq_busy = 0; - bh->state = BUF_STATE_FULL; - wakeup_thread(common); -} - -/*-------------------------------------------------------------------------*/ - -/* Ep0 class-specific handlers. These always run in_irq. */ - -static int fsg_setup(struct usb_function *f, - const struct usb_ctrlrequest *ctrl) -{ - struct fsg_dev *fsg = fsg_from_func(f); - struct usb_request *req = fsg->common->ep0req; - u16 w_index = get_unaligned_le16(&ctrl->wIndex); - u16 w_value = get_unaligned_le16(&ctrl->wValue); - u16 w_length = get_unaligned_le16(&ctrl->wLength); - - if (!fsg_is_set(fsg->common)) - return -EOPNOTSUPP; - - switch (ctrl->bRequest) { - - case USB_BULK_RESET_REQUEST: - if (ctrl->bRequestType != - (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) - break; - if (w_index != fsg->interface_number || w_value != 0) - return -EDOM; - - /* Raise an exception to stop the current operation - * and reinitialize our state. */ - DBG(fsg, "bulk reset request\n"); - raise_exception(fsg->common, FSG_STATE_RESET); - return DELAYED_STATUS; - - case USB_BULK_GET_MAX_LUN_REQUEST: - if (ctrl->bRequestType != - (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) - break; - if (w_index != fsg->interface_number || w_value != 0) - return -EDOM; - VDBG(fsg, "get max LUN\n"); - *(u8 *) req->buf = fsg->common->nluns - 1; - - /* Respond with data/status */ - req->length = min((u16)1, w_length); - return ep0_queue(fsg->common); - } - - VDBG(fsg, - "unknown class-specific control req " - "%02x.%02x v%04x i%04x l%u\n", - ctrl->bRequestType, ctrl->bRequest, - get_unaligned_le16(&ctrl->wValue), w_index, w_length); - return -EOPNOTSUPP; -} - -/*-------------------------------------------------------------------------*/ - -/* All the following routines run in process context */ - -/* Use this for bulk or interrupt transfers, not ep0 */ -static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, - struct usb_request *req, int *pbusy, - enum fsg_buffer_state *state) -{ - int rc; - - if (ep == fsg->bulk_in) - dump_msg(fsg, "bulk-in", req->buf, req->length); - - *pbusy = 1; - *state = BUF_STATE_BUSY; - rc = usb_ep_queue(ep, req, GFP_KERNEL); - if (rc != 0) { - *pbusy = 0; - *state = BUF_STATE_EMPTY; - - /* We can't do much more than wait for a reset */ - - /* Note: currently the net2280 driver fails zero-length - * submissions if DMA is enabled. */ - if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && - req->length == 0)) - WARNING(fsg, "error in submission: %s --> %d\n", - ep->name, rc); - } -} - -#define START_TRANSFER_OR(common, ep_name, req, pbusy, state) \ - if (fsg_is_set(common)) \ - start_transfer((common)->fsg, (common)->fsg->ep_name, \ - req, pbusy, state); \ - else - -#define START_TRANSFER(common, ep_name, req, pbusy, state) \ - START_TRANSFER_OR(common, ep_name, req, pbusy, state) (void)0 - -static void busy_indicator(void) -{ - static int state; - - switch (state) { - case 0: - puts("\r|"); break; - case 1: - puts("\r/"); break; - case 2: - puts("\r-"); break; - case 3: - puts("\r\\"); break; - case 4: - puts("\r|"); break; - case 5: - puts("\r/"); break; - case 6: - puts("\r-"); break; - case 7: - puts("\r\\"); break; - default: - state = 0; - } - if (state++ == 8) - state = 0; -} - -static int sleep_thread(struct fsg_common *common) -{ - int rc = 0; - int i = 0, k = 0; - - /* Wait until a signal arrives or we are woken up */ - for (;;) { - if (common->thread_wakeup_needed) - break; - - if (++i == 50000) { - busy_indicator(); - i = 0; - k++; - } - - if (k == 10) { - /* Handle CTRL+C */ - if (ctrlc()) - return -EPIPE; - - /* Check cable connection */ - if (!g_dnl_board_usb_cable_connected()) - return -EIO; - - k = 0; - } - - usb_gadget_handle_interrupts(); - } - common->thread_wakeup_needed = 0; - return rc; -} - -/*-------------------------------------------------------------------------*/ - -static int do_read(struct fsg_common *common) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - u32 lba; - struct fsg_buffhd *bh; - int rc; - u32 amount_left; - loff_t file_offset; - unsigned int amount; - unsigned int partial_page; - ssize_t nread; - - /* Get the starting Logical Block Address and check that it's - * not too big */ - if (common->cmnd[0] == SC_READ_6) - lba = get_unaligned_be24(&common->cmnd[1]); - else { - lba = get_unaligned_be32(&common->cmnd[2]); - - /* We allow DPO (Disable Page Out = don't save data in the - * cache) and FUA (Force Unit Access = don't read from the - * cache), but we don't implement them. */ - if ((common->cmnd[1] & ~0x18) != 0) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - } - if (lba >= curlun->num_sectors) { - curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -EINVAL; - } - file_offset = ((loff_t) lba) << 9; - - /* Carry out the file reads */ - amount_left = common->data_size_from_cmnd; - if (unlikely(amount_left == 0)) - return -EIO; /* No default reply */ - - for (;;) { - - /* Figure out how much we need to read: - * Try to read the remaining amount. - * But don't read more than the buffer size. - * And don't try to read past the end of the file. - * Finally, if we're not at a page boundary, don't read past - * the next page. - * If this means reading 0 then we were asked to read past - * the end of file. */ - amount = min(amount_left, FSG_BUFLEN); - partial_page = file_offset & (PAGE_CACHE_SIZE - 1); - if (partial_page > 0) - amount = min(amount, (unsigned int) PAGE_CACHE_SIZE - - partial_page); - - /* Wait for the next buffer to become available */ - bh = common->next_buffhd_to_fill; - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); - if (rc) - return rc; - } - - /* If we were asked to read past the end of file, - * end with an empty buffer. */ - if (amount == 0) { - curlun->sense_data = - SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - curlun->info_valid = 1; - bh->inreq->length = 0; - bh->state = BUF_STATE_FULL; - break; - } - - /* Perform the read */ - rc = ums->read_sector(ums, - file_offset / SECTOR_SIZE, - amount / SECTOR_SIZE, - (char __user *)bh->buf); - if (!rc) - return -EIO; - - nread = rc * SECTOR_SIZE; - - VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, - (unsigned long long) file_offset, - (int) nread); - - if (nread < 0) { - LDBG(curlun, "error in file read: %d\n", - (int) nread); - nread = 0; - } else if (nread < amount) { - LDBG(curlun, "partial file read: %d/%u\n", - (int) nread, amount); - nread -= (nread & 511); /* Round down to a block */ - } - file_offset += nread; - amount_left -= nread; - common->residue -= nread; - bh->inreq->length = nread; - bh->state = BUF_STATE_FULL; - - /* If an error occurred, report it and its position */ - if (nread < amount) { - curlun->sense_data = SS_UNRECOVERED_READ_ERROR; - curlun->info_valid = 1; - break; - } - - if (amount_left == 0) - break; /* No more left to read */ - - /* Send this buffer and go read some more */ - bh->inreq->zero = 0; - START_TRANSFER_OR(common, bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state) - /* Don't know what to do if - * common->fsg is NULL */ - return -EIO; - common->next_buffhd_to_fill = bh->next; - } - - return -EIO; /* No default reply */ -} - -/*-------------------------------------------------------------------------*/ - -static int do_write(struct fsg_common *common) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - u32 lba; - struct fsg_buffhd *bh; - int get_some_more; - u32 amount_left_to_req, amount_left_to_write; - loff_t usb_offset, file_offset; - unsigned int amount; - unsigned int partial_page; - ssize_t nwritten; - int rc; - - if (curlun->ro) { - curlun->sense_data = SS_WRITE_PROTECTED; - return -EINVAL; - } - - /* Get the starting Logical Block Address and check that it's - * not too big */ - if (common->cmnd[0] == SC_WRITE_6) - lba = get_unaligned_be24(&common->cmnd[1]); - else { - lba = get_unaligned_be32(&common->cmnd[2]); - - /* We allow DPO (Disable Page Out = don't save data in the - * cache) and FUA (Force Unit Access = write directly to the - * medium). We don't implement DPO; we implement FUA by - * performing synchronous output. */ - if (common->cmnd[1] & ~0x18) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - } - if (lba >= curlun->num_sectors) { - curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -EINVAL; - } - - /* Carry out the file writes */ - get_some_more = 1; - file_offset = usb_offset = ((loff_t) lba) << 9; - amount_left_to_req = common->data_size_from_cmnd; - amount_left_to_write = common->data_size_from_cmnd; - - while (amount_left_to_write > 0) { - - /* Queue a request for more data from the host */ - bh = common->next_buffhd_to_fill; - if (bh->state == BUF_STATE_EMPTY && get_some_more) { - - /* Figure out how much we want to get: - * Try to get the remaining amount. - * But don't get more than the buffer size. - * And don't try to go past the end of the file. - * If we're not at a page boundary, - * don't go past the next page. - * If this means getting 0, then we were asked - * to write past the end of file. - * Finally, round down to a block boundary. */ - amount = min(amount_left_to_req, FSG_BUFLEN); - partial_page = usb_offset & (PAGE_CACHE_SIZE - 1); - if (partial_page > 0) - amount = min(amount, - (unsigned int) PAGE_CACHE_SIZE - partial_page); - - if (amount == 0) { - get_some_more = 0; - curlun->sense_data = - SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - curlun->info_valid = 1; - continue; - } - amount -= (amount & 511); - if (amount == 0) { - - /* Why were we were asked to transfer a - * partial block? */ - get_some_more = 0; - continue; - } - - /* Get the next buffer */ - usb_offset += amount; - common->usb_amount_left -= amount; - amount_left_to_req -= amount; - if (amount_left_to_req == 0) - get_some_more = 0; - - /* amount is always divisible by 512, hence by - * the bulk-out maxpacket size */ - bh->outreq->length = amount; - bh->bulk_out_intended_length = amount; - bh->outreq->short_not_ok = 1; - START_TRANSFER_OR(common, bulk_out, bh->outreq, - &bh->outreq_busy, &bh->state) - /* Don't know what to do if - * common->fsg is NULL */ - return -EIO; - common->next_buffhd_to_fill = bh->next; - continue; - } - - /* Write the received data to the backing file */ - bh = common->next_buffhd_to_drain; - if (bh->state == BUF_STATE_EMPTY && !get_some_more) - break; /* We stopped early */ - if (bh->state == BUF_STATE_FULL) { - common->next_buffhd_to_drain = bh->next; - bh->state = BUF_STATE_EMPTY; - - /* Did something go wrong with the transfer? */ - if (bh->outreq->status != 0) { - curlun->sense_data = SS_COMMUNICATION_FAILURE; - curlun->info_valid = 1; - break; - } - - amount = bh->outreq->actual; - - /* Perform the write */ - rc = ums->write_sector(ums, - file_offset / SECTOR_SIZE, - amount / SECTOR_SIZE, - (char __user *)bh->buf); - if (!rc) - return -EIO; - nwritten = rc * SECTOR_SIZE; - - VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, - (unsigned long long) file_offset, - (int) nwritten); - - if (nwritten < 0) { - LDBG(curlun, "error in file write: %d\n", - (int) nwritten); - nwritten = 0; - } else if (nwritten < amount) { - LDBG(curlun, "partial file write: %d/%u\n", - (int) nwritten, amount); - nwritten -= (nwritten & 511); - /* Round down to a block */ - } - file_offset += nwritten; - amount_left_to_write -= nwritten; - common->residue -= nwritten; - - /* If an error occurred, report it and its position */ - if (nwritten < amount) { - printf("nwritten:%d amount:%d\n", nwritten, - amount); - curlun->sense_data = SS_WRITE_ERROR; - curlun->info_valid = 1; - break; - } - - /* Did the host decide to stop early? */ - if (bh->outreq->actual != bh->outreq->length) { - common->short_packet_received = 1; - break; - } - continue; - } - - /* Wait for something to happen */ - rc = sleep_thread(common); - if (rc) - return rc; - } - - return -EIO; /* No default reply */ -} - -/*-------------------------------------------------------------------------*/ - -static int do_synchronize_cache(struct fsg_common *common) -{ - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static int do_verify(struct fsg_common *common) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - u32 lba; - u32 verification_length; - struct fsg_buffhd *bh = common->next_buffhd_to_fill; - loff_t file_offset; - u32 amount_left; - unsigned int amount; - ssize_t nread; - int rc; - - /* Get the starting Logical Block Address and check that it's - * not too big */ - lba = get_unaligned_be32(&common->cmnd[2]); - if (lba >= curlun->num_sectors) { - curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -EINVAL; - } - - /* We allow DPO (Disable Page Out = don't save data in the - * cache) but we don't implement it. */ - if (common->cmnd[1] & ~0x10) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - - verification_length = get_unaligned_be16(&common->cmnd[7]); - if (unlikely(verification_length == 0)) - return -EIO; /* No default reply */ - - /* Prepare to carry out the file verify */ - amount_left = verification_length << 9; - file_offset = ((loff_t) lba) << 9; - - /* Write out all the dirty buffers before invalidating them */ - - /* Just try to read the requested blocks */ - while (amount_left > 0) { - - /* Figure out how much we need to read: - * Try to read the remaining amount, but not more than - * the buffer size. - * And don't try to read past the end of the file. - * If this means reading 0 then we were asked to read - * past the end of file. */ - amount = min(amount_left, FSG_BUFLEN); - if (amount == 0) { - curlun->sense_data = - SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - curlun->info_valid = 1; - break; - } - - /* Perform the read */ - rc = ums->read_sector(ums, - file_offset / SECTOR_SIZE, - amount / SECTOR_SIZE, - (char __user *)bh->buf); - if (!rc) - return -EIO; - nread = rc * SECTOR_SIZE; - - VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, - (unsigned long long) file_offset, - (int) nread); - if (nread < 0) { - LDBG(curlun, "error in file verify: %d\n", - (int) nread); - nread = 0; - } else if (nread < amount) { - LDBG(curlun, "partial file verify: %d/%u\n", - (int) nread, amount); - nread -= (nread & 511); /* Round down to a sector */ - } - if (nread == 0) { - curlun->sense_data = SS_UNRECOVERED_READ_ERROR; - curlun->info_valid = 1; - break; - } - file_offset += nread; - amount_left -= nread; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - static const char vendor_id[] = "Linux "; - u8 *buf = (u8 *) bh->buf; - - if (!curlun) { /* Unsupported LUNs are okay */ - common->bad_lun_okay = 1; - memset(buf, 0, 36); - buf[0] = 0x7f; /* Unsupported, no device-type */ - buf[4] = 31; /* Additional length */ - return 36; - } - - memset(buf, 0, 8); - buf[0] = TYPE_DISK; - buf[2] = 2; /* ANSI SCSI level 2 */ - buf[3] = 2; /* SCSI-2 INQUIRY data format */ - buf[4] = 31; /* Additional length */ - /* No special options */ - sprintf((char *) (buf + 8), "%-8s%-16s%04x", (char*) vendor_id , - ums->name, (u16) 0xffff); - - return 36; -} - - -static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - u8 *buf = (u8 *) bh->buf; - u32 sd, sdinfo; - int valid; - - /* - * From the SCSI-2 spec., section 7.9 (Unit attention condition): - * - * If a REQUEST SENSE command is received from an initiator - * with a pending unit attention condition (before the target - * generates the contingent allegiance condition), then the - * target shall either: - * a) report any pending sense data and preserve the unit - * attention condition on the logical unit, or, - * b) report the unit attention condition, may discard any - * pending sense data, and clear the unit attention - * condition on the logical unit for that initiator. - * - * FSG normally uses option a); enable this code to use option b). - */ -#if 0 - if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { - curlun->sense_data = curlun->unit_attention_data; - curlun->unit_attention_data = SS_NO_SENSE; - } -#endif - - if (!curlun) { /* Unsupported LUNs are okay */ - common->bad_lun_okay = 1; - sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; - sdinfo = 0; - valid = 0; - } else { - sd = curlun->sense_data; - valid = curlun->info_valid << 7; - curlun->sense_data = SS_NO_SENSE; - curlun->info_valid = 0; - } - - memset(buf, 0, 18); - buf[0] = valid | 0x70; /* Valid, current error */ - buf[2] = SK(sd); - put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */ - buf[7] = 18 - 8; /* Additional sense length */ - buf[12] = ASC(sd); - buf[13] = ASCQ(sd); - return 18; -} - -static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - u32 lba = get_unaligned_be32(&common->cmnd[2]); - int pmi = common->cmnd[8]; - u8 *buf = (u8 *) bh->buf; - - /* Check the PMI and LBA fields */ - if (pmi > 1 || (pmi == 0 && lba != 0)) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - - put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); - /* Max logical block */ - put_unaligned_be32(512, &buf[4]); /* Block length */ - return 8; -} - -static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - int msf = common->cmnd[1] & 0x02; - u32 lba = get_unaligned_be32(&common->cmnd[2]); - u8 *buf = (u8 *) bh->buf; - - if (common->cmnd[1] & ~0x02) { /* Mask away MSF */ - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - if (lba >= curlun->num_sectors) { - curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -EINVAL; - } - - memset(buf, 0, 8); - buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ - store_cdrom_address(&buf[4], msf, lba); - return 8; -} - - -static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - int msf = common->cmnd[1] & 0x02; - int start_track = common->cmnd[6]; - u8 *buf = (u8 *) bh->buf; - - if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ - start_track > 1) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - - memset(buf, 0, 20); - buf[1] = (20-2); /* TOC data length */ - buf[2] = 1; /* First track number */ - buf[3] = 1; /* Last track number */ - buf[5] = 0x16; /* Data track, copying allowed */ - buf[6] = 0x01; /* Only track is number 1 */ - store_cdrom_address(&buf[8], msf, 0); - - buf[13] = 0x16; /* Lead-out track is data */ - buf[14] = 0xAA; /* Lead-out track number */ - store_cdrom_address(&buf[16], msf, curlun->num_sectors); - - return 20; -} - -static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - int mscmnd = common->cmnd[0]; - u8 *buf = (u8 *) bh->buf; - u8 *buf0 = buf; - int pc, page_code; - int changeable_values, all_pages; - int valid_page = 0; - int len, limit; - - if ((common->cmnd[1] & ~0x08) != 0) { /* Mask away DBD */ - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - pc = common->cmnd[2] >> 6; - page_code = common->cmnd[2] & 0x3f; - if (pc == 3) { - curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; - return -EINVAL; - } - changeable_values = (pc == 1); - all_pages = (page_code == 0x3f); - - /* Write the mode parameter header. Fixed values are: default - * medium type, no cache control (DPOFUA), and no block descriptors. - * The only variable value is the WriteProtect bit. We will fill in - * the mode data length later. */ - memset(buf, 0, 8); - if (mscmnd == SC_MODE_SENSE_6) { - buf[2] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ - buf += 4; - limit = 255; - } else { /* SC_MODE_SENSE_10 */ - buf[3] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ - buf += 8; - limit = 65535; /* Should really be FSG_BUFLEN */ - } - - /* No block descriptors */ - - /* The mode pages, in numerical order. The only page we support - * is the Caching page. */ - if (page_code == 0x08 || all_pages) { - valid_page = 1; - buf[0] = 0x08; /* Page code */ - buf[1] = 10; /* Page length */ - memset(buf+2, 0, 10); /* None of the fields are changeable */ - - if (!changeable_values) { - buf[2] = 0x04; /* Write cache enable, */ - /* Read cache not disabled */ - /* No cache retention priorities */ - put_unaligned_be16(0xffff, &buf[4]); - /* Don't disable prefetch */ - /* Minimum prefetch = 0 */ - put_unaligned_be16(0xffff, &buf[8]); - /* Maximum prefetch */ - put_unaligned_be16(0xffff, &buf[10]); - /* Maximum prefetch ceiling */ - } - buf += 12; - } - - /* Check that a valid page was requested and the mode data length - * isn't too long. */ - len = buf - buf0; - if (!valid_page || len > limit) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - - /* Store the mode data length */ - if (mscmnd == SC_MODE_SENSE_6) - buf0[0] = len - 1; - else - put_unaligned_be16(len - 2, buf0); - return len; -} - - -static int do_start_stop(struct fsg_common *common) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - - if (!curlun) { - return -EINVAL; - } else if (!curlun->removable) { - curlun->sense_data = SS_INVALID_COMMAND; - return -EINVAL; - } - - return 0; -} - -static int do_prevent_allow(struct fsg_common *common) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - int prevent; - - if (!curlun->removable) { - curlun->sense_data = SS_INVALID_COMMAND; - return -EINVAL; - } - - prevent = common->cmnd[4] & 0x01; - if ((common->cmnd[4] & ~0x01) != 0) { /* Mask away Prevent */ - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - - if (curlun->prevent_medium_removal && !prevent) - fsg_lun_fsync_sub(curlun); - curlun->prevent_medium_removal = prevent; - return 0; -} - - -static int do_read_format_capacities(struct fsg_common *common, - struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - u8 *buf = (u8 *) bh->buf; - - buf[0] = buf[1] = buf[2] = 0; - buf[3] = 8; /* Only the Current/Maximum Capacity Descriptor */ - buf += 4; - - put_unaligned_be32(curlun->num_sectors, &buf[0]); - /* Number of blocks */ - put_unaligned_be32(512, &buf[4]); /* Block length */ - buf[4] = 0x02; /* Current capacity */ - return 12; -} - - -static int do_mode_select(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - - /* We don't support MODE SELECT */ - if (curlun) - curlun->sense_data = SS_INVALID_COMMAND; - return -EINVAL; -} - - -/*-------------------------------------------------------------------------*/ - -static int halt_bulk_in_endpoint(struct fsg_dev *fsg) -{ - int rc; - - rc = fsg_set_halt(fsg, fsg->bulk_in); - if (rc == -EAGAIN) - VDBG(fsg, "delayed bulk-in endpoint halt\n"); - while (rc != 0) { - if (rc != -EAGAIN) { - WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); - rc = 0; - break; - } - - rc = usb_ep_set_halt(fsg->bulk_in); - } - return rc; -} - -static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) -{ - int rc; - - DBG(fsg, "bulk-in set wedge\n"); - rc = 0; /* usb_ep_set_wedge(fsg->bulk_in); */ - if (rc == -EAGAIN) - VDBG(fsg, "delayed bulk-in endpoint wedge\n"); - while (rc != 0) { - if (rc != -EAGAIN) { - WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); - rc = 0; - break; - } - } - return rc; -} - -static int pad_with_zeros(struct fsg_dev *fsg) -{ - struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill; - u32 nkeep = bh->inreq->length; - u32 nsend; - int rc; - - bh->state = BUF_STATE_EMPTY; /* For the first iteration */ - fsg->common->usb_amount_left = nkeep + fsg->common->residue; - while (fsg->common->usb_amount_left > 0) { - - /* Wait for the next buffer to be free */ - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(fsg->common); - if (rc) - return rc; - } - - nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN); - memset(bh->buf + nkeep, 0, nsend - nkeep); - bh->inreq->length = nsend; - bh->inreq->zero = 0; - start_transfer(fsg, fsg->bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state); - bh = fsg->common->next_buffhd_to_fill = bh->next; - fsg->common->usb_amount_left -= nsend; - nkeep = 0; - } - return 0; -} - -static int throw_away_data(struct fsg_common *common) -{ - struct fsg_buffhd *bh; - u32 amount; - int rc; - - for (bh = common->next_buffhd_to_drain; - bh->state != BUF_STATE_EMPTY || common->usb_amount_left > 0; - bh = common->next_buffhd_to_drain) { - - /* Throw away the data in a filled buffer */ - if (bh->state == BUF_STATE_FULL) { - bh->state = BUF_STATE_EMPTY; - common->next_buffhd_to_drain = bh->next; - - /* A short packet or an error ends everything */ - if (bh->outreq->actual != bh->outreq->length || - bh->outreq->status != 0) { - raise_exception(common, - FSG_STATE_ABORT_BULK_OUT); - return -EINTR; - } - continue; - } - - /* Try to submit another request if we need one */ - bh = common->next_buffhd_to_fill; - if (bh->state == BUF_STATE_EMPTY - && common->usb_amount_left > 0) { - amount = min(common->usb_amount_left, FSG_BUFLEN); - - /* amount is always divisible by 512, hence by - * the bulk-out maxpacket size */ - bh->outreq->length = amount; - bh->bulk_out_intended_length = amount; - bh->outreq->short_not_ok = 1; - START_TRANSFER_OR(common, bulk_out, bh->outreq, - &bh->outreq_busy, &bh->state) - /* Don't know what to do if - * common->fsg is NULL */ - return -EIO; - common->next_buffhd_to_fill = bh->next; - common->usb_amount_left -= amount; - continue; - } - - /* Otherwise wait for something to happen */ - rc = sleep_thread(common); - if (rc) - return rc; - } - return 0; -} - - -static int finish_reply(struct fsg_common *common) -{ - struct fsg_buffhd *bh = common->next_buffhd_to_fill; - int rc = 0; - - switch (common->data_dir) { - case DATA_DIR_NONE: - break; /* Nothing to send */ - - /* If we don't know whether the host wants to read or write, - * this must be CB or CBI with an unknown command. We mustn't - * try to send or receive any data. So stall both bulk pipes - * if we can and wait for a reset. */ - case DATA_DIR_UNKNOWN: - if (!common->can_stall) { - /* Nothing */ - } else if (fsg_is_set(common)) { - fsg_set_halt(common->fsg, common->fsg->bulk_out); - rc = halt_bulk_in_endpoint(common->fsg); - } else { - /* Don't know what to do if common->fsg is NULL */ - rc = -EIO; - } - break; - - /* All but the last buffer of data must have already been sent */ - case DATA_DIR_TO_HOST: - if (common->data_size == 0) { - /* Nothing to send */ - - /* If there's no residue, simply send the last buffer */ - } else if (common->residue == 0) { - bh->inreq->zero = 0; - START_TRANSFER_OR(common, bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state) - return -EIO; - common->next_buffhd_to_fill = bh->next; - - /* For Bulk-only, if we're allowed to stall then send the - * short packet and halt the bulk-in endpoint. If we can't - * stall, pad out the remaining data with 0's. */ - } else if (common->can_stall) { - bh->inreq->zero = 1; - START_TRANSFER_OR(common, bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state) - /* Don't know what to do if - * common->fsg is NULL */ - rc = -EIO; - common->next_buffhd_to_fill = bh->next; - if (common->fsg) - rc = halt_bulk_in_endpoint(common->fsg); - } else if (fsg_is_set(common)) { - rc = pad_with_zeros(common->fsg); - } else { - /* Don't know what to do if common->fsg is NULL */ - rc = -EIO; - } - break; - - /* We have processed all we want from the data the host has sent. - * There may still be outstanding bulk-out requests. */ - case DATA_DIR_FROM_HOST: - if (common->residue == 0) { - /* Nothing to receive */ - - /* Did the host stop sending unexpectedly early? */ - } else if (common->short_packet_received) { - raise_exception(common, FSG_STATE_ABORT_BULK_OUT); - rc = -EINTR; - - /* We haven't processed all the incoming data. Even though - * we may be allowed to stall, doing so would cause a race. - * The controller may already have ACK'ed all the remaining - * bulk-out packets, in which case the host wouldn't see a - * STALL. Not realizing the endpoint was halted, it wouldn't - * clear the halt -- leading to problems later on. */ -#if 0 - } else if (common->can_stall) { - if (fsg_is_set(common)) - fsg_set_halt(common->fsg, - common->fsg->bulk_out); - raise_exception(common, FSG_STATE_ABORT_BULK_OUT); - rc = -EINTR; -#endif - - /* We can't stall. Read in the excess data and throw it - * all away. */ - } else { - rc = throw_away_data(common); - } - break; - } - return rc; -} - - -static int send_status(struct fsg_common *common) -{ - struct fsg_lun *curlun = &common->luns[common->lun]; - struct fsg_buffhd *bh; - struct bulk_cs_wrap *csw; - int rc; - u8 status = USB_STATUS_PASS; - u32 sd, sdinfo = 0; - - /* Wait for the next buffer to become available */ - bh = common->next_buffhd_to_fill; - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); - if (rc) - return rc; - } - - if (curlun) - sd = curlun->sense_data; - else if (common->bad_lun_okay) - sd = SS_NO_SENSE; - else - sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; - - if (common->phase_error) { - DBG(common, "sending phase-error status\n"); - status = USB_STATUS_PHASE_ERROR; - sd = SS_INVALID_COMMAND; - } else if (sd != SS_NO_SENSE) { - DBG(common, "sending command-failure status\n"); - status = USB_STATUS_FAIL; - VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" - " info x%x\n", - SK(sd), ASC(sd), ASCQ(sd), sdinfo); - } - - /* Store and send the Bulk-only CSW */ - csw = (void *)bh->buf; - - csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); - csw->Tag = common->tag; - csw->Residue = cpu_to_le32(common->residue); - csw->Status = status; - - bh->inreq->length = USB_BULK_CS_WRAP_LEN; - bh->inreq->zero = 0; - START_TRANSFER_OR(common, bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state) - /* Don't know what to do if common->fsg is NULL */ - return -EIO; - - common->next_buffhd_to_fill = bh->next; - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -/* Check whether the command is properly formed and whether its data size - * and direction agree with the values we already have. */ -static int check_command(struct fsg_common *common, int cmnd_size, - enum data_direction data_dir, unsigned int mask, - int needs_medium, const char *name) -{ - int i; - int lun = common->cmnd[1] >> 5; - static const char dirletter[4] = {'u', 'o', 'i', 'n'}; - char hdlen[20]; - struct fsg_lun *curlun; - - hdlen[0] = 0; - if (common->data_dir != DATA_DIR_UNKNOWN) - sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir], - common->data_size); - VDBG(common, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", - name, cmnd_size, dirletter[(int) data_dir], - common->data_size_from_cmnd, common->cmnd_size, hdlen); - - /* We can't reply at all until we know the correct data direction - * and size. */ - if (common->data_size_from_cmnd == 0) - data_dir = DATA_DIR_NONE; - if (common->data_size < common->data_size_from_cmnd) { - /* Host data size < Device data size is a phase error. - * Carry out the command, but only transfer as much as - * we are allowed. */ - common->data_size_from_cmnd = common->data_size; - common->phase_error = 1; - } - common->residue = common->data_size; - common->usb_amount_left = common->data_size; - - /* Conflicting data directions is a phase error */ - if (common->data_dir != data_dir - && common->data_size_from_cmnd > 0) { - common->phase_error = 1; - return -EINVAL; - } - - /* Verify the length of the command itself */ - if (cmnd_size != common->cmnd_size) { - - /* Special case workaround: There are plenty of buggy SCSI - * implementations. Many have issues with cbw->Length - * field passing a wrong command size. For those cases we - * always try to work around the problem by using the length - * sent by the host side provided it is at least as large - * as the correct command length. - * Examples of such cases would be MS-Windows, which issues - * REQUEST SENSE with cbw->Length == 12 where it should - * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and - * REQUEST SENSE with cbw->Length == 10 where it should - * be 6 as well. - */ - if (cmnd_size <= common->cmnd_size) { - DBG(common, "%s is buggy! Expected length %d " - "but we got %d\n", name, - cmnd_size, common->cmnd_size); - cmnd_size = common->cmnd_size; - } else { - common->phase_error = 1; - return -EINVAL; - } - } - - /* Check that the LUN values are consistent */ - if (common->lun != lun) - DBG(common, "using LUN %d from CBW, not LUN %d from CDB\n", - common->lun, lun); - - /* Check the LUN */ - if (common->lun >= 0 && common->lun < common->nluns) { - curlun = &common->luns[common->lun]; - if (common->cmnd[0] != SC_REQUEST_SENSE) { - curlun->sense_data = SS_NO_SENSE; - curlun->info_valid = 0; - } - } else { - curlun = NULL; - common->bad_lun_okay = 0; - - /* INQUIRY and REQUEST SENSE commands are explicitly allowed - * to use unsupported LUNs; all others may not. */ - if (common->cmnd[0] != SC_INQUIRY && - common->cmnd[0] != SC_REQUEST_SENSE) { - DBG(common, "unsupported LUN %d\n", common->lun); - return -EINVAL; - } - } -#if 0 - /* If a unit attention condition exists, only INQUIRY and - * REQUEST SENSE commands are allowed; anything else must fail. */ - if (curlun && curlun->unit_attention_data != SS_NO_SENSE && - common->cmnd[0] != SC_INQUIRY && - common->cmnd[0] != SC_REQUEST_SENSE) { - curlun->sense_data = curlun->unit_attention_data; - curlun->unit_attention_data = SS_NO_SENSE; - return -EINVAL; - } -#endif - /* Check that only command bytes listed in the mask are non-zero */ - common->cmnd[1] &= 0x1f; /* Mask away the LUN */ - for (i = 1; i < cmnd_size; ++i) { - if (common->cmnd[i] && !(mask & (1 << i))) { - if (curlun) - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - } - - return 0; -} - - -static int do_scsi_command(struct fsg_common *common) -{ - struct fsg_buffhd *bh; - int rc; - int reply = -EINVAL; - int i; - static char unknown[16]; - struct fsg_lun *curlun = &common->luns[common->lun]; - - dump_cdb(common); - - /* Wait for the next buffer to become available for data or status */ - bh = common->next_buffhd_to_fill; - common->next_buffhd_to_drain = bh; - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); - if (rc) - return rc; - } - common->phase_error = 0; - common->short_packet_received = 0; - - down_read(&common->filesem); /* We're using the backing file */ - switch (common->cmnd[0]) { - - case SC_INQUIRY: - common->data_size_from_cmnd = common->cmnd[4]; - reply = check_command(common, 6, DATA_DIR_TO_HOST, - (1<<4), 0, - "INQUIRY"); - if (reply == 0) - reply = do_inquiry(common, bh); - break; - - case SC_MODE_SELECT_6: - common->data_size_from_cmnd = common->cmnd[4]; - reply = check_command(common, 6, DATA_DIR_FROM_HOST, - (1<<1) | (1<<4), 0, - "MODE SELECT(6)"); - if (reply == 0) - reply = do_mode_select(common, bh); - break; - - case SC_MODE_SELECT_10: - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]); - reply = check_command(common, 10, DATA_DIR_FROM_HOST, - (1<<1) | (3<<7), 0, - "MODE SELECT(10)"); - if (reply == 0) - reply = do_mode_select(common, bh); - break; - - case SC_MODE_SENSE_6: - common->data_size_from_cmnd = common->cmnd[4]; - reply = check_command(common, 6, DATA_DIR_TO_HOST, - (1<<1) | (1<<2) | (1<<4), 0, - "MODE SENSE(6)"); - if (reply == 0) - reply = do_mode_sense(common, bh); - break; - - case SC_MODE_SENSE_10: - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]); - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (1<<1) | (1<<2) | (3<<7), 0, - "MODE SENSE(10)"); - if (reply == 0) - reply = do_mode_sense(common, bh); - break; - - case SC_PREVENT_ALLOW_MEDIUM_REMOVAL: - common->data_size_from_cmnd = 0; - reply = check_command(common, 6, DATA_DIR_NONE, - (1<<4), 0, - "PREVENT-ALLOW MEDIUM REMOVAL"); - if (reply == 0) - reply = do_prevent_allow(common); - break; - - case SC_READ_6: - i = common->cmnd[4]; - common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; - reply = check_command(common, 6, DATA_DIR_TO_HOST, - (7<<1) | (1<<4), 1, - "READ(6)"); - if (reply == 0) - reply = do_read(common); - break; - - case SC_READ_10: - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]) << 9; - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (1<<1) | (0xf<<2) | (3<<7), 1, - "READ(10)"); - if (reply == 0) - reply = do_read(common); - break; - - case SC_READ_12: - common->data_size_from_cmnd = - get_unaligned_be32(&common->cmnd[6]) << 9; - reply = check_command(common, 12, DATA_DIR_TO_HOST, - (1<<1) | (0xf<<2) | (0xf<<6), 1, - "READ(12)"); - if (reply == 0) - reply = do_read(common); - break; - - case SC_READ_CAPACITY: - common->data_size_from_cmnd = 8; - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (0xf<<2) | (1<<8), 1, - "READ CAPACITY"); - if (reply == 0) - reply = do_read_capacity(common, bh); - break; - - case SC_READ_HEADER: - if (!common->luns[common->lun].cdrom) - goto unknown_cmnd; - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]); - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (3<<7) | (0x1f<<1), 1, - "READ HEADER"); - if (reply == 0) - reply = do_read_header(common, bh); - break; - - case SC_READ_TOC: - if (!common->luns[common->lun].cdrom) - goto unknown_cmnd; - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]); - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (7<<6) | (1<<1), 1, - "READ TOC"); - if (reply == 0) - reply = do_read_toc(common, bh); - break; - - case SC_READ_FORMAT_CAPACITIES: - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]); - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (3<<7), 1, - "READ FORMAT CAPACITIES"); - if (reply == 0) - reply = do_read_format_capacities(common, bh); - break; - - case SC_REQUEST_SENSE: - common->data_size_from_cmnd = common->cmnd[4]; - reply = check_command(common, 6, DATA_DIR_TO_HOST, - (1<<4), 0, - "REQUEST SENSE"); - if (reply == 0) - reply = do_request_sense(common, bh); - break; - - case SC_START_STOP_UNIT: - common->data_size_from_cmnd = 0; - reply = check_command(common, 6, DATA_DIR_NONE, - (1<<1) | (1<<4), 0, - "START-STOP UNIT"); - if (reply == 0) - reply = do_start_stop(common); - break; - - case SC_SYNCHRONIZE_CACHE: - common->data_size_from_cmnd = 0; - reply = check_command(common, 10, DATA_DIR_NONE, - (0xf<<2) | (3<<7), 1, - "SYNCHRONIZE CACHE"); - if (reply == 0) - reply = do_synchronize_cache(common); - break; - - case SC_TEST_UNIT_READY: - common->data_size_from_cmnd = 0; - reply = check_command(common, 6, DATA_DIR_NONE, - 0, 1, - "TEST UNIT READY"); - break; - - /* Although optional, this command is used by MS-Windows. We - * support a minimal version: BytChk must be 0. */ - case SC_VERIFY: - common->data_size_from_cmnd = 0; - reply = check_command(common, 10, DATA_DIR_NONE, - (1<<1) | (0xf<<2) | (3<<7), 1, - "VERIFY"); - if (reply == 0) - reply = do_verify(common); - break; - - case SC_WRITE_6: - i = common->cmnd[4]; - common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; - reply = check_command(common, 6, DATA_DIR_FROM_HOST, - (7<<1) | (1<<4), 1, - "WRITE(6)"); - if (reply == 0) - reply = do_write(common); - break; - - case SC_WRITE_10: - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]) << 9; - reply = check_command(common, 10, DATA_DIR_FROM_HOST, - (1<<1) | (0xf<<2) | (3<<7), 1, - "WRITE(10)"); - if (reply == 0) - reply = do_write(common); - break; - - case SC_WRITE_12: - common->data_size_from_cmnd = - get_unaligned_be32(&common->cmnd[6]) << 9; - reply = check_command(common, 12, DATA_DIR_FROM_HOST, - (1<<1) | (0xf<<2) | (0xf<<6), 1, - "WRITE(12)"); - if (reply == 0) - reply = do_write(common); - break; - - /* Some mandatory commands that we recognize but don't implement. - * They don't mean much in this setting. It's left as an exercise - * for anyone interested to implement RESERVE and RELEASE in terms - * of Posix locks. */ - case SC_FORMAT_UNIT: - case SC_RELEASE: - case SC_RESERVE: - case SC_SEND_DIAGNOSTIC: - /* Fall through */ - - default: -unknown_cmnd: - common->data_size_from_cmnd = 0; - sprintf(unknown, "Unknown x%02x", common->cmnd[0]); - reply = check_command(common, common->cmnd_size, - DATA_DIR_UNKNOWN, 0xff, 0, unknown); - if (reply == 0) { - curlun->sense_data = SS_INVALID_COMMAND; - reply = -EINVAL; - } - break; - } - up_read(&common->filesem); - - if (reply == -EINTR) - return -EINTR; - - /* Set up the single reply buffer for finish_reply() */ - if (reply == -EINVAL) - reply = 0; /* Error reply length */ - if (reply >= 0 && common->data_dir == DATA_DIR_TO_HOST) { - reply = min((u32) reply, common->data_size_from_cmnd); - bh->inreq->length = reply; - bh->state = BUF_STATE_FULL; - common->residue -= reply; - } /* Otherwise it's already set */ - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{ - struct usb_request *req = bh->outreq; - struct fsg_bulk_cb_wrap *cbw = req->buf; - struct fsg_common *common = fsg->common; - - /* Was this a real packet? Should it be ignored? */ - if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) - return -EINVAL; - - /* Is the CBW valid? */ - if (req->actual != USB_BULK_CB_WRAP_LEN || - cbw->Signature != cpu_to_le32( - USB_BULK_CB_SIG)) { - DBG(fsg, "invalid CBW: len %u sig 0x%x\n", - req->actual, - le32_to_cpu(cbw->Signature)); - - /* The Bulk-only spec says we MUST stall the IN endpoint - * (6.6.1), so it's unavoidable. It also says we must - * retain this state until the next reset, but there's - * no way to tell the controller driver it should ignore - * Clear-Feature(HALT) requests. - * - * We aren't required to halt the OUT endpoint; instead - * we can simply accept and discard any data received - * until the next reset. */ - wedge_bulk_in_endpoint(fsg); - set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); - return -EINVAL; - } - - /* Is the CBW meaningful? */ - if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || - cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { - DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " - "cmdlen %u\n", - cbw->Lun, cbw->Flags, cbw->Length); - - /* We can do anything we want here, so let's stall the - * bulk pipes if we are allowed to. */ - if (common->can_stall) { - fsg_set_halt(fsg, fsg->bulk_out); - halt_bulk_in_endpoint(fsg); - } - return -EINVAL; - } - - /* Save the command for later */ - common->cmnd_size = cbw->Length; - memcpy(common->cmnd, cbw->CDB, common->cmnd_size); - if (cbw->Flags & USB_BULK_IN_FLAG) - common->data_dir = DATA_DIR_TO_HOST; - else - common->data_dir = DATA_DIR_FROM_HOST; - common->data_size = le32_to_cpu(cbw->DataTransferLength); - if (common->data_size == 0) - common->data_dir = DATA_DIR_NONE; - common->lun = cbw->Lun; - common->tag = cbw->Tag; - return 0; -} - - -static int get_next_command(struct fsg_common *common) -{ - struct fsg_buffhd *bh; - int rc = 0; - - /* Wait for the next buffer to become available */ - bh = common->next_buffhd_to_fill; - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); - if (rc) - return rc; - } - - /* Queue a request to read a Bulk-only CBW */ - set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN); - bh->outreq->short_not_ok = 1; - START_TRANSFER_OR(common, bulk_out, bh->outreq, - &bh->outreq_busy, &bh->state) - /* Don't know what to do if common->fsg is NULL */ - return -EIO; - - /* We will drain the buffer in software, which means we - * can reuse it for the next filling. No need to advance - * next_buffhd_to_fill. */ - - /* Wait for the CBW to arrive */ - while (bh->state != BUF_STATE_FULL) { - rc = sleep_thread(common); - if (rc) - return rc; - } - - rc = fsg_is_set(common) ? received_cbw(common->fsg, bh) : -EIO; - bh->state = BUF_STATE_EMPTY; - - return rc; -} - - -/*-------------------------------------------------------------------------*/ - -static int enable_endpoint(struct fsg_common *common, struct usb_ep *ep, - const struct usb_endpoint_descriptor *d) -{ - int rc; - - ep->driver_data = common; - rc = usb_ep_enable(ep, d); - if (rc) - ERROR(common, "can't enable %s, result %d\n", ep->name, rc); - return rc; -} - -static int alloc_request(struct fsg_common *common, struct usb_ep *ep, - struct usb_request **preq) -{ - *preq = usb_ep_alloc_request(ep, GFP_ATOMIC); - if (*preq) - return 0; - ERROR(common, "can't allocate request for %s\n", ep->name); - return -ENOMEM; -} - -/* Reset interface setting and re-init endpoint state (toggle etc). */ -static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) -{ - const struct usb_endpoint_descriptor *d; - struct fsg_dev *fsg; - int i, rc = 0; - - if (common->running) - DBG(common, "reset interface\n"); - -reset: - /* Deallocate the requests */ - if (common->fsg) { - fsg = common->fsg; - - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - struct fsg_buffhd *bh = &common->buffhds[i]; - - if (bh->inreq) { - usb_ep_free_request(fsg->bulk_in, bh->inreq); - bh->inreq = NULL; - } - if (bh->outreq) { - usb_ep_free_request(fsg->bulk_out, bh->outreq); - bh->outreq = NULL; - } - } - - /* Disable the endpoints */ - if (fsg->bulk_in_enabled) { - usb_ep_disable(fsg->bulk_in); - fsg->bulk_in_enabled = 0; - } - if (fsg->bulk_out_enabled) { - usb_ep_disable(fsg->bulk_out); - fsg->bulk_out_enabled = 0; - } - - common->fsg = NULL; - /* wake_up(&common->fsg_wait); */ - } - - common->running = 0; - if (!new_fsg || rc) - return rc; - - common->fsg = new_fsg; - fsg = common->fsg; - - /* Enable the endpoints */ - d = fsg_ep_desc(common->gadget, - &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); - rc = enable_endpoint(common, fsg->bulk_in, d); - if (rc) - goto reset; - fsg->bulk_in_enabled = 1; - - d = fsg_ep_desc(common->gadget, - &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); - rc = enable_endpoint(common, fsg->bulk_out, d); - if (rc) - goto reset; - fsg->bulk_out_enabled = 1; - common->bulk_out_maxpacket = - le16_to_cpu(get_unaligned(&d->wMaxPacketSize)); - clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); - - /* Allocate the requests */ - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - struct fsg_buffhd *bh = &common->buffhds[i]; - - rc = alloc_request(common, fsg->bulk_in, &bh->inreq); - if (rc) - goto reset; - rc = alloc_request(common, fsg->bulk_out, &bh->outreq); - if (rc) - goto reset; - bh->inreq->buf = bh->outreq->buf = bh->buf; - bh->inreq->context = bh->outreq->context = bh; - bh->inreq->complete = bulk_in_complete; - bh->outreq->complete = bulk_out_complete; - } - - common->running = 1; - - return rc; -} - - -/****************************** ALT CONFIGS ******************************/ - - -static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) -{ - struct fsg_dev *fsg = fsg_from_func(f); - fsg->common->new_fsg = fsg; - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); - return 0; -} - -static void fsg_disable(struct usb_function *f) -{ - struct fsg_dev *fsg = fsg_from_func(f); - fsg->common->new_fsg = NULL; - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); -} - -/*-------------------------------------------------------------------------*/ - -static void handle_exception(struct fsg_common *common) -{ - int i; - struct fsg_buffhd *bh; - enum fsg_state old_state; - struct fsg_lun *curlun; - unsigned int exception_req_tag; - - /* Cancel all the pending transfers */ - if (common->fsg) { - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - bh = &common->buffhds[i]; - if (bh->inreq_busy) - usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); - if (bh->outreq_busy) - usb_ep_dequeue(common->fsg->bulk_out, - bh->outreq); - } - - /* Wait until everything is idle */ - for (;;) { - int num_active = 0; - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - bh = &common->buffhds[i]; - num_active += bh->inreq_busy + bh->outreq_busy; - } - if (num_active == 0) - break; - if (sleep_thread(common)) - return; - } - - /* Clear out the controller's fifos */ - if (common->fsg->bulk_in_enabled) - usb_ep_fifo_flush(common->fsg->bulk_in); - if (common->fsg->bulk_out_enabled) - usb_ep_fifo_flush(common->fsg->bulk_out); - } - - /* Reset the I/O buffer states and pointers, the SCSI - * state, and the exception. Then invoke the handler. */ - - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - bh = &common->buffhds[i]; - bh->state = BUF_STATE_EMPTY; - } - common->next_buffhd_to_fill = &common->buffhds[0]; - common->next_buffhd_to_drain = &common->buffhds[0]; - exception_req_tag = common->exception_req_tag; - old_state = common->state; - - if (old_state == FSG_STATE_ABORT_BULK_OUT) - common->state = FSG_STATE_STATUS_PHASE; - else { - for (i = 0; i < common->nluns; ++i) { - curlun = &common->luns[i]; - curlun->sense_data = SS_NO_SENSE; - curlun->info_valid = 0; - } - common->state = FSG_STATE_IDLE; - } - - /* Carry out any extra actions required for the exception */ - switch (old_state) { - case FSG_STATE_ABORT_BULK_OUT: - send_status(common); - - if (common->state == FSG_STATE_STATUS_PHASE) - common->state = FSG_STATE_IDLE; - break; - - case FSG_STATE_RESET: - /* In case we were forced against our will to halt a - * bulk endpoint, clear the halt now. (The SuperH UDC - * requires this.) */ - if (!fsg_is_set(common)) - break; - if (test_and_clear_bit(IGNORE_BULK_OUT, - &common->fsg->atomic_bitflags)) - usb_ep_clear_halt(common->fsg->bulk_in); - - if (common->ep0_req_tag == exception_req_tag) - ep0_queue(common); /* Complete the status stage */ - - break; - - case FSG_STATE_CONFIG_CHANGE: - do_set_interface(common, common->new_fsg); - break; - - case FSG_STATE_EXIT: - case FSG_STATE_TERMINATED: - do_set_interface(common, NULL); /* Free resources */ - common->state = FSG_STATE_TERMINATED; /* Stop the thread */ - break; - - case FSG_STATE_INTERFACE_CHANGE: - case FSG_STATE_DISCONNECT: - case FSG_STATE_COMMAND_PHASE: - case FSG_STATE_DATA_PHASE: - case FSG_STATE_STATUS_PHASE: - case FSG_STATE_IDLE: - break; - } -} - -/*-------------------------------------------------------------------------*/ - -int fsg_main_thread(void *common_) -{ - int ret; - struct fsg_common *common = the_fsg_common; - /* The main loop */ - do { - if (exception_in_progress(common)) { - handle_exception(common); - continue; - } - - if (!common->running) { - ret = sleep_thread(common); - if (ret) - return ret; - - continue; - } - - ret = get_next_command(common); - if (ret) - return ret; - - if (!exception_in_progress(common)) - common->state = FSG_STATE_DATA_PHASE; - - if (do_scsi_command(common) || finish_reply(common)) - continue; - - if (!exception_in_progress(common)) - common->state = FSG_STATE_STATUS_PHASE; - - if (send_status(common)) - continue; - - if (!exception_in_progress(common)) - common->state = FSG_STATE_IDLE; - } while (0); - - common->thread_task = NULL; - - return 0; -} - -static void fsg_common_release(struct kref *ref); - -static struct fsg_common *fsg_common_init(struct fsg_common *common, - struct usb_composite_dev *cdev) -{ - struct usb_gadget *gadget = cdev->gadget; - struct fsg_buffhd *bh; - struct fsg_lun *curlun; - int nluns, i, rc; - - /* Find out how many LUNs there should be */ - nluns = 1; - if (nluns < 1 || nluns > FSG_MAX_LUNS) { - printf("invalid number of LUNs: %u\n", nluns); - return ERR_PTR(-EINVAL); - } - - /* Allocate? */ - if (!common) { - common = calloc(sizeof *common, 1); - if (!common) - return ERR_PTR(-ENOMEM); - common->free_storage_on_release = 1; - } else { - memset(common, 0, sizeof common); - common->free_storage_on_release = 0; - } - - common->ops = NULL; - common->private_data = NULL; - - common->gadget = gadget; - common->ep0 = gadget->ep0; - common->ep0req = cdev->req; - - /* Maybe allocate device-global string IDs, and patch descriptors */ - if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { - rc = usb_string_id(cdev); - if (unlikely(rc < 0)) - goto error_release; - fsg_strings[FSG_STRING_INTERFACE].id = rc; - fsg_intf_desc.iInterface = rc; - } - - /* Create the LUNs, open their backing files, and register the - * LUN devices in sysfs. */ - curlun = calloc(nluns, sizeof *curlun); - if (!curlun) { - rc = -ENOMEM; - goto error_release; - } - common->nluns = nluns; - - for (i = 0; i < nluns; i++) { - common->luns[i].removable = 1; - - rc = fsg_lun_open(&common->luns[i], ""); - if (rc) - goto error_luns; - } - common->lun = 0; - - /* Data buffers cyclic list */ - bh = common->buffhds; - - i = FSG_NUM_BUFFERS; - goto buffhds_first_it; - do { - bh->next = bh + 1; - ++bh; -buffhds_first_it: - bh->inreq_busy = 0; - bh->outreq_busy = 0; - bh->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, FSG_BUFLEN); - if (unlikely(!bh->buf)) { - rc = -ENOMEM; - goto error_release; - } - } while (--i); - bh->next = common->buffhds; - - snprintf(common->inquiry_string, sizeof common->inquiry_string, - "%-8s%-16s%04x", - "Linux ", - "File-Store Gadget", - 0xffff); - - /* Some peripheral controllers are known not to be able to - * halt bulk endpoints correctly. If one of them is present, - * disable stalls. - */ - - /* Tell the thread to start working */ - common->thread_task = - kthread_create(fsg_main_thread, common, - OR(cfg->thread_name, "file-storage")); - if (IS_ERR(common->thread_task)) { - rc = PTR_ERR(common->thread_task); - goto error_release; - } - -#undef OR - /* Information */ - INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); - INFO(common, "Number of LUNs=%d\n", common->nluns); - - return common; - -error_luns: - common->nluns = i + 1; -error_release: - common->state = FSG_STATE_TERMINATED; /* The thread is dead */ - /* Call fsg_common_release() directly, ref might be not - * initialised */ - fsg_common_release(&common->ref); - return ERR_PTR(rc); -} - -static void fsg_common_release(struct kref *ref) -{ - struct fsg_common *common = container_of(ref, struct fsg_common, ref); - - /* If the thread isn't already dead, tell it to exit now */ - if (common->state != FSG_STATE_TERMINATED) { - raise_exception(common, FSG_STATE_EXIT); - wait_for_completion(&common->thread_notifier); - } - - if (likely(common->luns)) { - struct fsg_lun *lun = common->luns; - unsigned i = common->nluns; - - /* In error recovery common->nluns may be zero. */ - for (; i; --i, ++lun) - fsg_lun_close(lun); - - kfree(common->luns); - } - - { - struct fsg_buffhd *bh = common->buffhds; - unsigned i = FSG_NUM_BUFFERS; - do { - kfree(bh->buf); - } while (++bh, --i); - } - - if (common->free_storage_on_release) - kfree(common); -} - - -/*-------------------------------------------------------------------------*/ - -/** - * usb_copy_descriptors - copy a vector of USB descriptors - * @src: null-terminated vector to copy - * Context: initialization code, which may sleep - * - * This makes a copy of a vector of USB descriptors. Its primary use - * is to support usb_function objects which can have multiple copies, - * each needing different descriptors. Functions may have static - * tables of descriptors, which are used as templates and customized - * with identifiers (for interfaces, strings, endpoints, and more) - * as needed by a given function instance. - */ -struct usb_descriptor_header ** -usb_copy_descriptors(struct usb_descriptor_header **src) -{ - struct usb_descriptor_header **tmp; - unsigned bytes; - unsigned n_desc; - void *mem; - struct usb_descriptor_header **ret; - - /* count descriptors and their sizes; then add vector size */ - for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++) - bytes += (*tmp)->bLength; - bytes += (n_desc + 1) * sizeof(*tmp); - - mem = memalign(CONFIG_SYS_CACHELINE_SIZE, bytes); - if (!mem) - return NULL; - - /* fill in pointers starting at "tmp", - * to descriptors copied starting at "mem"; - * and return "ret" - */ - tmp = mem; - ret = mem; - mem += (n_desc + 1) * sizeof(*tmp); - while (*src) { - memcpy(mem, *src, (*src)->bLength); - *tmp = mem; - tmp++; - mem += (*src)->bLength; - src++; - } - *tmp = NULL; - - return ret; -} - -static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) -{ - struct fsg_dev *fsg = fsg_from_func(f); - - DBG(fsg, "unbind\n"); - if (fsg->common->fsg == fsg) { - fsg->common->new_fsg = NULL; - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); - } - - free(fsg->function.descriptors); - free(fsg->function.hs_descriptors); - kfree(fsg); -} - -static int fsg_bind(struct usb_configuration *c, struct usb_function *f) -{ - struct fsg_dev *fsg = fsg_from_func(f); - struct usb_gadget *gadget = c->cdev->gadget; - int i; - struct usb_ep *ep; - fsg->gadget = gadget; - - /* New interface */ - i = usb_interface_id(c, f); - if (i < 0) - return i; - fsg_intf_desc.bInterfaceNumber = i; - fsg->interface_number = i; - - /* Find all the endpoints we will use */ - ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); - if (!ep) - goto autoconf_fail; - ep->driver_data = fsg->common; /* claim the endpoint */ - fsg->bulk_in = ep; - - ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); - if (!ep) - goto autoconf_fail; - ep->driver_data = fsg->common; /* claim the endpoint */ - fsg->bulk_out = ep; - - /* Copy descriptors */ - f->descriptors = usb_copy_descriptors(fsg_fs_function); - if (unlikely(!f->descriptors)) - return -ENOMEM; - - if (gadget_is_dualspeed(gadget)) { - /* Assume endpoint addresses are the same for both speeds */ - fsg_hs_bulk_in_desc.bEndpointAddress = - fsg_fs_bulk_in_desc.bEndpointAddress; - fsg_hs_bulk_out_desc.bEndpointAddress = - fsg_fs_bulk_out_desc.bEndpointAddress; - f->hs_descriptors = usb_copy_descriptors(fsg_hs_function); - if (unlikely(!f->hs_descriptors)) { - free(f->descriptors); - return -ENOMEM; - } - } - return 0; - -autoconf_fail: - ERROR(fsg, "unable to autoconfigure all endpoints\n"); - return -ENOTSUPP; -} - - -/****************************** ADD FUNCTION ******************************/ - -static struct usb_gadget_strings *fsg_strings_array[] = { - &fsg_stringtab, - NULL, -}; - -static int fsg_bind_config(struct usb_composite_dev *cdev, - struct usb_configuration *c, - struct fsg_common *common) -{ - struct fsg_dev *fsg; - int rc; - - fsg = calloc(1, sizeof *fsg); - if (!fsg) - return -ENOMEM; - fsg->function.name = FSG_DRIVER_DESC; - fsg->function.strings = fsg_strings_array; - fsg->function.bind = fsg_bind; - fsg->function.unbind = fsg_unbind; - fsg->function.setup = fsg_setup; - fsg->function.set_alt = fsg_set_alt; - fsg->function.disable = fsg_disable; - - fsg->common = common; - common->fsg = fsg; - /* Our caller holds a reference to common structure so we - * don't have to be worry about it being freed until we return - * from this function. So instead of incrementing counter now - * and decrement in error recovery we increment it only when - * call to usb_add_function() was successful. */ - - rc = usb_add_function(c, &fsg->function); - - if (rc) - kfree(fsg); - - return rc; -} - -int fsg_add(struct usb_configuration *c) -{ - struct fsg_common *fsg_common; - - fsg_common = fsg_common_init(NULL, c->cdev); - - fsg_common->vendor_name = 0; - fsg_common->product_name = 0; - fsg_common->release = 0xffff; - - fsg_common->ops = NULL; - fsg_common->private_data = NULL; - - the_fsg_common = fsg_common; - - return fsg_bind_config(c->cdev, c, fsg_common); -} - -int fsg_init(struct ums *ums_dev) -{ - ums = ums_dev; - - return 0; -} - -DECLARE_GADGET_BIND_CALLBACK(usb_dnl_ums, fsg_add); diff --git a/qemu/roms/u-boot/drivers/usb/gadget/f_thor.c b/qemu/roms/u-boot/drivers/usb/gadget/f_thor.c deleted file mode 100644 index feef9e461..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/f_thor.c +++ /dev/null @@ -1,1008 +0,0 @@ -/* - * f_thor.c -- USB TIZEN THOR Downloader gadget function - * - * Copyright (C) 2013 Samsung Electronics - * Lukasz Majewski <l.majewski@samsung.com> - * - * Based on code from: - * git://review.tizen.org/kernel/u-boot - * - * Developed by: - * Copyright (C) 2009 Samsung Electronics - * Minkyu Kang <mk7.kang@samsung.com> - * Sanghee Kim <sh0130.kim@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <errno.h> -#include <common.h> -#include <malloc.h> -#include <version.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <linux/usb/composite.h> -#include <linux/usb/cdc.h> -#include <g_dnl.h> -#include <dfu.h> - -#include "f_thor.h" - -static void thor_tx_data(unsigned char *data, int len); -static void thor_set_dma(void *addr, int len); -static int thor_rx_data(void); - -static struct f_thor *thor_func; -static inline struct f_thor *func_to_thor(struct usb_function *f) -{ - return container_of(f, struct f_thor, usb_function); -} - -DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_tx_data_buf, - sizeof(struct rsp_box)); -DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_rx_data_buf, - sizeof(struct rqt_box)); - -/* ********************************************************** */ -/* THOR protocol - transmission handling */ -/* ********************************************************** */ -DEFINE_CACHE_ALIGN_BUFFER(char, f_name, F_NAME_BUF_SIZE); -static unsigned long long int thor_file_size; -static int alt_setting_num; - -static void send_rsp(const struct rsp_box *rsp) -{ - memcpy(thor_tx_data_buf, rsp, sizeof(struct rsp_box)); - thor_tx_data(thor_tx_data_buf, sizeof(struct rsp_box)); - - debug("-RSP: %d, %d\n", rsp->rsp, rsp->rsp_data); -} - -static void send_data_rsp(s32 ack, s32 count) -{ - ALLOC_CACHE_ALIGN_BUFFER(struct data_rsp_box, rsp, - sizeof(struct data_rsp_box)); - - rsp->ack = ack; - rsp->count = count; - - memcpy(thor_tx_data_buf, rsp, sizeof(struct data_rsp_box)); - thor_tx_data(thor_tx_data_buf, sizeof(struct data_rsp_box)); - - debug("-DATA RSP: %d, %d\n", ack, count); -} - -static int process_rqt_info(const struct rqt_box *rqt) -{ - ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box)); - memset(rsp, 0, sizeof(struct rsp_box)); - - rsp->rsp = rqt->rqt; - rsp->rsp_data = rqt->rqt_data; - - switch (rqt->rqt_data) { - case RQT_INFO_VER_PROTOCOL: - rsp->int_data[0] = VER_PROTOCOL_MAJOR; - rsp->int_data[1] = VER_PROTOCOL_MINOR; - break; - case RQT_INIT_VER_HW: - snprintf(rsp->str_data[0], sizeof(rsp->str_data[0]), - "%x", checkboard()); - break; - case RQT_INIT_VER_BOOT: - sprintf(rsp->str_data[0], "%s", U_BOOT_VERSION); - break; - case RQT_INIT_VER_KERNEL: - sprintf(rsp->str_data[0], "%s", "k unknown"); - break; - case RQT_INIT_VER_PLATFORM: - sprintf(rsp->str_data[0], "%s", "p unknown"); - break; - case RQT_INIT_VER_CSC: - sprintf(rsp->str_data[0], "%s", "c unknown"); - break; - default: - return -EINVAL; - } - - send_rsp(rsp); - return true; -} - -static int process_rqt_cmd(const struct rqt_box *rqt) -{ - ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box)); - memset(rsp, 0, sizeof(struct rsp_box)); - - rsp->rsp = rqt->rqt; - rsp->rsp_data = rqt->rqt_data; - - switch (rqt->rqt_data) { - case RQT_CMD_REBOOT: - debug("TARGET RESET\n"); - send_rsp(rsp); - g_dnl_unregister(); - dfu_free_entities(); - run_command("reset", 0); - break; - case RQT_CMD_POWEROFF: - case RQT_CMD_EFSCLEAR: - send_rsp(rsp); - default: - printf("Command not supported -> cmd: %d\n", rqt->rqt_data); - return -EINVAL; - } - - return true; -} - -static long long int download_head(unsigned long long total, - unsigned int packet_size, - long long int *left, - int *cnt) -{ - long long int rcv_cnt = 0, left_to_rcv, ret_rcv; - void *transfer_buffer = dfu_get_buf(); - void *buf = transfer_buffer; - int usb_pkt_cnt = 0, ret; - - /* - * Files smaller than THOR_STORE_UNIT_SIZE (now 32 MiB) are stored on - * the medium. - * The packet response is sent on the purpose after successful data - * chunk write. There is a room for improvement when asynchronous write - * is performed. - */ - while (total - rcv_cnt >= packet_size) { - thor_set_dma(buf, packet_size); - buf += packet_size; - ret_rcv = thor_rx_data(); - if (ret_rcv < 0) - return ret_rcv; - rcv_cnt += ret_rcv; - debug("%d: RCV data count: %llu cnt: %d\n", usb_pkt_cnt, - rcv_cnt, *cnt); - - if ((rcv_cnt % THOR_STORE_UNIT_SIZE) == 0) { - ret = dfu_write(dfu_get_entity(alt_setting_num), - transfer_buffer, THOR_STORE_UNIT_SIZE, - (*cnt)++); - if (ret) { - error("DFU write failed [%d] cnt: %d", - ret, *cnt); - return ret; - } - buf = transfer_buffer; - } - send_data_rsp(0, ++usb_pkt_cnt); - } - - /* Calculate the amount of data to arrive from PC (in bytes) */ - left_to_rcv = total - rcv_cnt; - - /* - * Calculate number of data already received. but not yet stored - * on the medium (they are smaller than THOR_STORE_UNIT_SIZE) - */ - *left = left_to_rcv + buf - transfer_buffer; - debug("%s: left: %llu left_to_rcv: %llu buf: 0x%p\n", __func__, - *left, left_to_rcv, buf); - - if (left_to_rcv) { - thor_set_dma(buf, packet_size); - ret_rcv = thor_rx_data(); - if (ret_rcv < 0) - return ret_rcv; - rcv_cnt += ret_rcv; - send_data_rsp(0, ++usb_pkt_cnt); - } - - debug("%s: %llu total: %llu cnt: %d\n", __func__, rcv_cnt, total, *cnt); - - return rcv_cnt; -} - -static int download_tail(long long int left, int cnt) -{ - struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num); - void *transfer_buffer = dfu_get_buf(); - int ret; - - debug("%s: left: %llu cnt: %d\n", __func__, left, cnt); - - if (left) { - ret = dfu_write(dfu_entity, transfer_buffer, left, cnt++); - if (ret) { - error("DFU write failed [%d]: left: %llu", ret, left); - return ret; - } - } - - /* - * To store last "packet" DFU storage backend requires dfu_write with - * size parameter equal to 0 - * - * This also frees memory malloc'ed by dfu_get_buf(), so no explicit - * need fo call dfu_free_buf() is needed. - */ - ret = dfu_write(dfu_entity, transfer_buffer, 0, cnt); - if (ret) - error("DFU write failed [%d] cnt: %d", ret, cnt); - - ret = dfu_flush(dfu_entity, transfer_buffer, 0, cnt); - if (ret) { - error("DFU flush failed!"); - return ret; - } - - return ret; -} - -static long long int process_rqt_download(const struct rqt_box *rqt) -{ - ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box)); - static long long int left, ret_head; - int file_type, ret = 0; - static int cnt; - - memset(rsp, 0, sizeof(struct rsp_box)); - rsp->rsp = rqt->rqt; - rsp->rsp_data = rqt->rqt_data; - - switch (rqt->rqt_data) { - case RQT_DL_INIT: - thor_file_size = rqt->int_data[0]; - debug("INIT: total %d bytes\n", rqt->int_data[0]); - break; - case RQT_DL_FILE_INFO: - file_type = rqt->int_data[0]; - if (file_type == FILE_TYPE_PIT) { - puts("PIT table file - not supported\n"); - rsp->ack = -ENOTSUPP; - ret = rsp->ack; - break; - } - - thor_file_size = rqt->int_data[1]; - memcpy(f_name, rqt->str_data[0], F_NAME_BUF_SIZE); - - debug("INFO: name(%s, %d), size(%llu), type(%d)\n", - f_name, 0, thor_file_size, file_type); - - rsp->int_data[0] = THOR_PACKET_SIZE; - - alt_setting_num = dfu_get_alt(f_name); - if (alt_setting_num < 0) { - error("Alt setting [%d] to write not found!", - alt_setting_num); - rsp->ack = -ENODEV; - ret = rsp->ack; - } - break; - case RQT_DL_FILE_START: - send_rsp(rsp); - ret_head = download_head(thor_file_size, THOR_PACKET_SIZE, - &left, &cnt); - if (ret_head < 0) { - left = 0; - cnt = 0; - } - return ret_head; - case RQT_DL_FILE_END: - debug("DL FILE_END\n"); - rsp->ack = download_tail(left, cnt); - ret = rsp->ack; - left = 0; - cnt = 0; - break; - case RQT_DL_EXIT: - debug("DL EXIT\n"); - break; - default: - error("Operation not supported: %d", rqt->rqt_data); - ret = -ENOTSUPP; - } - - send_rsp(rsp); - return ret; -} - -static int process_data(void) -{ - ALLOC_CACHE_ALIGN_BUFFER(struct rqt_box, rqt, sizeof(struct rqt_box)); - int ret = -EINVAL; - - memset(rqt, 0, sizeof(rqt)); - memcpy(rqt, thor_rx_data_buf, sizeof(struct rqt_box)); - - debug("+RQT: %d, %d\n", rqt->rqt, rqt->rqt_data); - - switch (rqt->rqt) { - case RQT_INFO: - ret = process_rqt_info(rqt); - break; - case RQT_CMD: - ret = process_rqt_cmd(rqt); - break; - case RQT_DL: - ret = (int) process_rqt_download(rqt); - break; - case RQT_UL: - puts("RQT: UPLOAD not supported!\n"); - break; - default: - error("unknown request (%d)", rqt->rqt); - } - - return ret; -} - -/* ********************************************************** */ -/* THOR USB Function */ -/* ********************************************************** */ - -static inline struct usb_endpoint_descriptor * -ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, - struct usb_endpoint_descriptor *fs) -{ - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) - return hs; - return fs; -} - -static struct usb_interface_descriptor thor_downloader_intf_data = { - .bLength = sizeof(thor_downloader_intf_data), - .bDescriptorType = USB_DT_INTERFACE, - - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_CDC_DATA, -}; - -static struct usb_endpoint_descriptor fs_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, -}; - -static struct usb_endpoint_descriptor fs_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, -}; - -/* CDC configuration */ -static struct usb_interface_descriptor thor_downloader_intf_int = { - .bLength = sizeof(thor_downloader_intf_int), - .bDescriptorType = USB_DT_INTERFACE, - - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_COMM, - /* 0x02 Abstract Line Control Model */ - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - /* 0x01 Common AT commands */ - .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER, -}; - -static struct usb_cdc_header_desc thor_downloader_cdc_header = { - .bLength = sizeof(thor_downloader_cdc_header), - .bDescriptorType = 0x24, /* CS_INTERFACE */ - .bDescriptorSubType = 0x00, - .bcdCDC = 0x0110, -}; - -static struct usb_cdc_call_mgmt_descriptor thor_downloader_cdc_call = { - .bLength = sizeof(thor_downloader_cdc_call), - .bDescriptorType = 0x24, /* CS_INTERFACE */ - .bDescriptorSubType = 0x01, - .bmCapabilities = 0x00, - .bDataInterface = 0x01, -}; - -static struct usb_cdc_acm_descriptor thor_downloader_cdc_abstract = { - .bLength = sizeof(thor_downloader_cdc_abstract), - .bDescriptorType = 0x24, /* CS_INTERFACE */ - .bDescriptorSubType = 0x02, - .bmCapabilities = 0x00, -}; - -static struct usb_cdc_union_desc thor_downloader_cdc_union = { - .bLength = sizeof(thor_downloader_cdc_union), - .bDescriptorType = 0x24, /* CS_INTERFACE */ - .bDescriptorSubType = USB_CDC_UNION_TYPE, -}; - -static struct usb_endpoint_descriptor fs_int_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = 3 | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(16), - - .bInterval = 0x9, -}; - -static struct usb_interface_assoc_descriptor -thor_iad_descriptor = { - .bLength = sizeof(thor_iad_descriptor), - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - - .bFirstInterface = 0, - .bInterfaceCount = 2, /* control + data */ - .bFunctionClass = USB_CLASS_COMM, - .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_CDC_PROTO_NONE, -}; - -static struct usb_endpoint_descriptor hs_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), -}; - -static struct usb_endpoint_descriptor hs_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), -}; - -static struct usb_endpoint_descriptor hs_int_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(16), - - .bInterval = 0x9, -}; - -static struct usb_qualifier_descriptor dev_qualifier = { - .bLength = sizeof(dev_qualifier), - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - - .bcdUSB = __constant_cpu_to_le16(0x0200), - .bDeviceClass = USB_CLASS_VENDOR_SPEC, - - .bNumConfigurations = 2, -}; - -/* - * This attribute vendor descriptor is necessary for correct operation with - * Windows version of THOR download program - * - * It prevents windows driver from sending zero lenght packet (ZLP) after - * each THOR_PACKET_SIZE. This assures consistent behaviour with libusb - */ -static struct usb_cdc_attribute_vendor_descriptor thor_downloader_cdc_av = { - .bLength = sizeof(thor_downloader_cdc_av), - .bDescriptorType = 0x24, - .bDescriptorSubType = 0x80, - .DAUType = 0x0002, - .DAULength = 0x0001, - .DAUValue = 0x00, -}; - -static const struct usb_descriptor_header *hs_thor_downloader_function[] = { - (struct usb_descriptor_header *)&thor_iad_descriptor, - - (struct usb_descriptor_header *)&thor_downloader_intf_int, - (struct usb_descriptor_header *)&thor_downloader_cdc_header, - (struct usb_descriptor_header *)&thor_downloader_cdc_call, - (struct usb_descriptor_header *)&thor_downloader_cdc_abstract, - (struct usb_descriptor_header *)&thor_downloader_cdc_union, - (struct usb_descriptor_header *)&hs_int_desc, - - (struct usb_descriptor_header *)&thor_downloader_intf_data, - (struct usb_descriptor_header *)&thor_downloader_cdc_av, - (struct usb_descriptor_header *)&hs_in_desc, - (struct usb_descriptor_header *)&hs_out_desc, - NULL, -}; - -/*-------------------------------------------------------------------------*/ -static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) -{ - struct usb_request *req; - - req = usb_ep_alloc_request(ep, 0); - if (!req) - return req; - - req->length = length; - req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length); - if (!req->buf) { - usb_ep_free_request(ep, req); - req = NULL; - } - - return req; -} - -static int thor_rx_data(void) -{ - struct thor_dev *dev = thor_func->dev; - int data_to_rx, tmp, status; - - data_to_rx = dev->out_req->length; - tmp = data_to_rx; - do { - dev->out_req->length = data_to_rx; - debug("dev->out_req->length:%d dev->rxdata:%d\n", - dev->out_req->length, dev->rxdata); - - status = usb_ep_queue(dev->out_ep, dev->out_req, 0); - if (status) { - error("kill %s: resubmit %d bytes --> %d", - dev->out_ep->name, dev->out_req->length, status); - usb_ep_set_halt(dev->out_ep); - return -EAGAIN; - } - - while (!dev->rxdata) { - usb_gadget_handle_interrupts(); - if (ctrlc()) - return -1; - } - dev->rxdata = 0; - data_to_rx -= dev->out_req->actual; - } while (data_to_rx); - - return tmp; -} - -static void thor_tx_data(unsigned char *data, int len) -{ - struct thor_dev *dev = thor_func->dev; - unsigned char *ptr = dev->in_req->buf; - int status; - - memset(ptr, 0, len); - memcpy(ptr, data, len); - - dev->in_req->length = len; - - debug("%s: dev->in_req->length:%d to_cpy:%d\n", __func__, - dev->in_req->length, sizeof(data)); - - status = usb_ep_queue(dev->in_ep, dev->in_req, 0); - if (status) { - error("kill %s: resubmit %d bytes --> %d", - dev->in_ep->name, dev->in_req->length, status); - usb_ep_set_halt(dev->in_ep); - } - - /* Wait until tx interrupt received */ - while (!dev->txdata) - usb_gadget_handle_interrupts(); - - dev->txdata = 0; -} - -static void thor_rx_tx_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct thor_dev *dev = thor_func->dev; - int status = req->status; - - debug("%s: ep_ptr:%p, req_ptr:%p\n", __func__, ep, req); - switch (status) { - case 0: - if (ep == dev->out_ep) - dev->rxdata = 1; - else - dev->txdata = 1; - - break; - - /* this endpoint is normally active while we're configured */ - case -ECONNABORTED: /* hardware forced ep reset */ - case -ECONNRESET: /* request dequeued */ - case -ESHUTDOWN: /* disconnect from host */ - case -EREMOTEIO: /* short read */ - case -EOVERFLOW: - error("ERROR:%d", status); - break; - } - - debug("%s complete --> %d, %d/%d\n", ep->name, - status, req->actual, req->length); -} - -static struct usb_request *thor_start_ep(struct usb_ep *ep) -{ - struct usb_request *req; - - req = alloc_ep_req(ep, THOR_PACKET_SIZE); - debug("%s: ep:%p req:%p\n", __func__, ep, req); - - if (!req) - return NULL; - - memset(req->buf, 0, req->length); - req->complete = thor_rx_tx_complete; - - return req; -} - -static void thor_setup_complete(struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) - debug("setup complete --> %d, %d/%d\n", - req->status, req->actual, req->length); -} - -static int -thor_func_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) -{ - struct thor_dev *dev = thor_func->dev; - struct usb_request *req = dev->req; - struct usb_gadget *gadget = dev->gadget; - int value = 0; - - u16 len = le16_to_cpu(ctrl->wLength); - - debug("Req_Type: 0x%x Req: 0x%x wValue: 0x%x wIndex: 0x%x wLen: 0x%x\n", - ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex, - ctrl->wLength); - - switch (ctrl->bRequest) { - case USB_CDC_REQ_SET_CONTROL_LINE_STATE: - value = 0; - break; - case USB_CDC_REQ_SET_LINE_CODING: - value = len; - /* Line Coding set done = configuration done */ - thor_func->dev->configuration_done = 1; - break; - - default: - error("thor_setup: unknown request: %d", ctrl->bRequest); - } - - if (value >= 0) { - req->length = value; - req->zero = value < len; - value = usb_ep_queue(gadget->ep0, req, 0); - if (value < 0) { - debug("%s: ep_queue: %d\n", __func__, value); - req->status = 0; - } - } - - return value; -} - -/* Specific to the THOR protocol */ -static void thor_set_dma(void *addr, int len) -{ - struct thor_dev *dev = thor_func->dev; - - debug("in_req:%p, out_req:%p\n", dev->in_req, dev->out_req); - debug("addr:%p, len:%d\n", addr, len); - - dev->out_req->buf = addr; - dev->out_req->length = len; -} - -int thor_init(void) -{ - struct thor_dev *dev = thor_func->dev; - - /* Wait for a device enumeration and configuration settings */ - debug("THOR enumeration/configuration setting....\n"); - while (!dev->configuration_done) - usb_gadget_handle_interrupts(); - - thor_set_dma(thor_rx_data_buf, strlen("THOR")); - /* detect the download request from Host PC */ - if (thor_rx_data() < 0) { - printf("%s: Data not received!\n", __func__); - return -1; - } - - if (!strncmp((char *)thor_rx_data_buf, "THOR", strlen("THOR"))) { - puts("Download request from the Host PC\n"); - udelay(30 * 1000); /* 30 ms */ - - strcpy((char *)thor_tx_data_buf, "ROHT"); - thor_tx_data(thor_tx_data_buf, strlen("ROHT")); - } else { - puts("Wrong reply information\n"); - return -1; - } - - return 0; -} - -int thor_handle(void) -{ - int ret; - - /* receive the data from Host PC */ - while (1) { - thor_set_dma(thor_rx_data_buf, sizeof(struct rqt_box)); - ret = thor_rx_data(); - - if (ret > 0) { - ret = process_data(); - if (ret < 0) - return ret; - } else { - printf("%s: No data received!\n", __func__); - break; - } - } - - return 0; -} - -static int thor_func_bind(struct usb_configuration *c, struct usb_function *f) -{ - struct usb_gadget *gadget = c->cdev->gadget; - struct f_thor *f_thor = func_to_thor(f); - struct thor_dev *dev; - struct usb_ep *ep; - int status; - - thor_func = f_thor; - dev = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*dev)); - if (!dev) - return -ENOMEM; - - memset(dev, 0, sizeof(*dev)); - dev->gadget = gadget; - f_thor->dev = dev; - - debug("%s: usb_configuration: 0x%p usb_function: 0x%p\n", - __func__, c, f); - debug("f_thor: 0x%p thor: 0x%p\n", f_thor, dev); - - /* EP0 */ - /* preallocate control response and buffer */ - dev->req = usb_ep_alloc_request(gadget->ep0, 0); - if (!dev->req) { - status = -ENOMEM; - goto fail; - } - dev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, - gadget->ep0->maxpacket); - if (!dev->req->buf) { - status = -ENOMEM; - goto fail; - } - - dev->req->complete = thor_setup_complete; - - /* DYNAMIC interface numbers assignments */ - status = usb_interface_id(c, f); - - if (status < 0) - goto fail; - - thor_downloader_intf_int.bInterfaceNumber = status; - thor_downloader_cdc_union.bMasterInterface0 = status; - - status = usb_interface_id(c, f); - - if (status < 0) - goto fail; - - thor_downloader_intf_data.bInterfaceNumber = status; - thor_downloader_cdc_union.bSlaveInterface0 = status; - - /* allocate instance-specific endpoints */ - ep = usb_ep_autoconfig(gadget, &fs_in_desc); - if (!ep) { - status = -ENODEV; - goto fail; - } - - if (gadget_is_dualspeed(gadget)) { - hs_in_desc.bEndpointAddress = - fs_in_desc.bEndpointAddress; - } - - dev->in_ep = ep; /* Store IN EP for enabling @ setup */ - - ep = usb_ep_autoconfig(gadget, &fs_out_desc); - if (!ep) { - status = -ENODEV; - goto fail; - } - - if (gadget_is_dualspeed(gadget)) - hs_out_desc.bEndpointAddress = - fs_out_desc.bEndpointAddress; - - dev->out_ep = ep; /* Store OUT EP for enabling @ setup */ - - ep = usb_ep_autoconfig(gadget, &fs_int_desc); - if (!ep) { - status = -ENODEV; - goto fail; - } - - dev->int_ep = ep; - - if (gadget_is_dualspeed(gadget)) { - hs_int_desc.bEndpointAddress = - fs_int_desc.bEndpointAddress; - - f->hs_descriptors = (struct usb_descriptor_header **) - &hs_thor_downloader_function; - - if (!f->hs_descriptors) - goto fail; - } - - debug("%s: out_ep:%p out_req:%p\n", __func__, - dev->out_ep, dev->out_req); - - return 0; - - fail: - free(dev); - return status; -} - -static void free_ep_req(struct usb_ep *ep, struct usb_request *req) -{ - free(req->buf); - usb_ep_free_request(ep, req); -} - -static void thor_unbind(struct usb_configuration *c, struct usb_function *f) -{ - struct f_thor *f_thor = func_to_thor(f); - struct thor_dev *dev = f_thor->dev; - - free(dev); - memset(thor_func, 0, sizeof(*thor_func)); - thor_func = NULL; -} - -static void thor_func_disable(struct usb_function *f) -{ - struct f_thor *f_thor = func_to_thor(f); - struct thor_dev *dev = f_thor->dev; - - debug("%s:\n", __func__); - - /* Avoid freeing memory when ep is still claimed */ - if (dev->in_ep->driver_data) { - free_ep_req(dev->in_ep, dev->in_req); - usb_ep_disable(dev->in_ep); - dev->in_ep->driver_data = NULL; - } - - if (dev->out_ep->driver_data) { - dev->out_req->buf = NULL; - usb_ep_free_request(dev->out_ep, dev->out_req); - usb_ep_disable(dev->out_ep); - dev->out_ep->driver_data = NULL; - } - - if (dev->int_ep->driver_data) { - usb_ep_disable(dev->int_ep); - dev->int_ep->driver_data = NULL; - } -} - -static int thor_eps_setup(struct usb_function *f) -{ - struct usb_composite_dev *cdev = f->config->cdev; - struct usb_gadget *gadget = cdev->gadget; - struct thor_dev *dev = thor_func->dev; - struct usb_endpoint_descriptor *d; - struct usb_request *req; - struct usb_ep *ep; - int result; - - ep = dev->in_ep; - d = ep_desc(gadget, &hs_in_desc, &fs_in_desc); - debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress); - - result = usb_ep_enable(ep, d); - if (result) - goto exit; - - ep->driver_data = cdev; /* claim */ - req = thor_start_ep(ep); - if (!req) { - usb_ep_disable(ep); - result = -EIO; - goto exit; - } - - dev->in_req = req; - ep = dev->out_ep; - d = ep_desc(gadget, &hs_out_desc, &fs_out_desc); - debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress); - - result = usb_ep_enable(ep, d); - if (result) - goto exit; - - ep->driver_data = cdev; /* claim */ - req = thor_start_ep(ep); - if (!req) { - usb_ep_disable(ep); - result = -EIO; - goto exit; - } - - dev->out_req = req; - /* ACM control EP */ - ep = dev->int_ep; - ep->driver_data = cdev; /* claim */ - - exit: - return result; -} - -static int thor_func_set_alt(struct usb_function *f, - unsigned intf, unsigned alt) -{ - struct thor_dev *dev = thor_func->dev; - int result; - - debug("%s: func: %s intf: %d alt: %d\n", - __func__, f->name, intf, alt); - - switch (intf) { - case 0: - debug("ACM INTR interface\n"); - break; - case 1: - debug("Communication Data interface\n"); - result = thor_eps_setup(f); - if (result) - error("%s: EPs setup failed!", __func__); - dev->configuration_done = 1; - break; - } - - return 0; -} - -static int thor_func_init(struct usb_configuration *c) -{ - struct f_thor *f_thor; - int status; - - debug("%s: cdev: 0x%p\n", __func__, c->cdev); - - f_thor = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_thor)); - if (!f_thor) - return -ENOMEM; - - memset(f_thor, 0, sizeof(*f_thor)); - - f_thor->usb_function.name = "f_thor"; - f_thor->usb_function.bind = thor_func_bind; - f_thor->usb_function.unbind = thor_unbind; - f_thor->usb_function.setup = thor_func_setup; - f_thor->usb_function.set_alt = thor_func_set_alt; - f_thor->usb_function.disable = thor_func_disable; - - status = usb_add_function(c, &f_thor->usb_function); - if (status) - free(f_thor); - - return status; -} - -int thor_add(struct usb_configuration *c) -{ - debug("%s:\n", __func__); - return thor_func_init(c); -} - -DECLARE_GADGET_BIND_CALLBACK(usb_dnl_thor, thor_add); diff --git a/qemu/roms/u-boot/drivers/usb/gadget/f_thor.h b/qemu/roms/u-boot/drivers/usb/gadget/f_thor.h deleted file mode 100644 index 833a9d24a..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/f_thor.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * f_thor.h - USB TIZEN THOR - internal gadget definitions - * - * Copyright (C) 2013 Samsung Electronics - * Lukasz Majewski <l.majewski@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _USB_THOR_H_ -#define _USB_THOR_H_ - -#include <linux/compiler.h> -#include <linux/sizes.h> - -/* THOR Composite Gadget */ -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 -#define STRING_SERIAL_IDX 2 - -/* ********************************************************** */ -/* THOR protocol definitions */ -/* ********************************************************** */ - -/* - * Attribute Vendor descriptor - necessary to prevent ZLP transmission - * from Windows XP HOST PC - */ -struct usb_cdc_attribute_vendor_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u16 DAUType; - __u16 DAULength; - __u8 DAUValue; -} __packed; - -#define VER_PROTOCOL_MAJOR 4 -#define VER_PROTOCOL_MINOR 0 - -enum rqt { - RQT_INFO = 200, - RQT_CMD, - RQT_DL, - RQT_UL, -}; - -enum rqt_data { - /* RQT_INFO */ - RQT_INFO_VER_PROTOCOL = 1, - RQT_INIT_VER_HW, - RQT_INIT_VER_BOOT, - RQT_INIT_VER_KERNEL, - RQT_INIT_VER_PLATFORM, - RQT_INIT_VER_CSC, - - /* RQT_CMD */ - RQT_CMD_REBOOT = 1, - RQT_CMD_POWEROFF, - RQT_CMD_EFSCLEAR, - - /* RQT_DL */ - RQT_DL_INIT = 1, - RQT_DL_FILE_INFO, - RQT_DL_FILE_START, - RQT_DL_FILE_END, - RQT_DL_EXIT, - - /* RQT_UL */ - RQT_UL_INIT = 1, - RQT_UL_START, - RQT_UL_END, - RQT_UL_EXIT, -}; - -struct rqt_box { /* total: 256B */ - s32 rqt; /* request id */ - s32 rqt_data; /* request data id */ - s32 int_data[14]; /* int data */ - char str_data[5][32]; /* string data */ - char md5[32]; /* md5 checksum */ -} __packed; - -struct rsp_box { /* total: 128B */ - s32 rsp; /* response id (= request id) */ - s32 rsp_data; /* response data id */ - s32 ack; /* ack */ - s32 int_data[5]; /* int data */ - char str_data[3][32]; /* string data */ -} __packed; - -struct data_rsp_box { /* total: 8B */ - s32 ack; /* response id (= request id) */ - s32 count; /* response data id */ -} __packed; - -enum { - FILE_TYPE_NORMAL, - FILE_TYPE_PIT, -}; - -struct thor_dev { - struct usb_gadget *gadget; - struct usb_request *req; /* EP0 -> control responses */ - - /* IN/OUT EP's and correspoinding requests */ - struct usb_ep *in_ep, *out_ep, *int_ep; - struct usb_request *in_req, *out_req; - - /* Control flow variables */ - unsigned char configuration_done; - unsigned char rxdata; - unsigned char txdata; -}; - -struct f_thor { - struct usb_function usb_function; - struct thor_dev *dev; -}; - -#define F_NAME_BUF_SIZE 32 -#define THOR_PACKET_SIZE SZ_1M /* 1 MiB */ -#define THOR_STORE_UNIT_SIZE SZ_32M /* 32 MiB */ -#endif /* _USB_THOR_H_ */ diff --git a/qemu/roms/u-boot/drivers/usb/gadget/fotg210.c b/qemu/roms/u-boot/drivers/usb/gadget/fotg210.c deleted file mode 100644 index 3acf6a1f4..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/fotg210.c +++ /dev/null @@ -1,962 +0,0 @@ -/* - * Faraday USB 2.0 OTG Controller - * - * (C) Copyright 2010 Faraday Technology - * Dante Su <dantesu@faraday-tech.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <command.h> -#include <config.h> -#include <net.h> -#include <malloc.h> -#include <asm/io.h> -#include <asm/errno.h> -#include <linux/types.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> - -#include <usb/fotg210.h> - -#define CFG_NUM_ENDPOINTS 4 -#define CFG_EP0_MAX_PACKET_SIZE 64 -#define CFG_EPX_MAX_PACKET_SIZE 512 - -#define CFG_CMD_TIMEOUT (CONFIG_SYS_HZ >> 2) /* 250 ms */ - -struct fotg210_chip; - -struct fotg210_ep { - struct usb_ep ep; - - uint maxpacket; - uint id; - uint stopped; - - struct list_head queue; - struct fotg210_chip *chip; - const struct usb_endpoint_descriptor *desc; -}; - -struct fotg210_request { - struct usb_request req; - struct list_head queue; - struct fotg210_ep *ep; -}; - -struct fotg210_chip { - struct usb_gadget gadget; - struct usb_gadget_driver *driver; - struct fotg210_regs *regs; - uint8_t irq; - uint16_t addr; - int pullup; - enum usb_device_state state; - struct fotg210_ep ep[1 + CFG_NUM_ENDPOINTS]; -}; - -static struct usb_endpoint_descriptor ep0_desc = { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_CONTROL, -}; - -static inline int fifo_to_ep(struct fotg210_chip *chip, int id, int in) -{ - return (id < 0) ? 0 : ((id & 0x03) + 1); -} - -static inline int ep_to_fifo(struct fotg210_chip *chip, int id) -{ - return (id <= 0) ? -1 : ((id - 1) & 0x03); -} - -static inline int ep_reset(struct fotg210_chip *chip, uint8_t ep_addr) -{ - int ep = ep_addr & USB_ENDPOINT_NUMBER_MASK; - struct fotg210_regs *regs = chip->regs; - - if (ep_addr & USB_DIR_IN) { - /* reset endpoint */ - setbits_le32(®s->iep[ep - 1], IEP_RESET); - mdelay(1); - clrbits_le32(®s->iep[ep - 1], IEP_RESET); - /* clear endpoint stall */ - clrbits_le32(®s->iep[ep - 1], IEP_STALL); - } else { - /* reset endpoint */ - setbits_le32(®s->oep[ep - 1], OEP_RESET); - mdelay(1); - clrbits_le32(®s->oep[ep - 1], OEP_RESET); - /* clear endpoint stall */ - clrbits_le32(®s->oep[ep - 1], OEP_STALL); - } - - return 0; -} - -static int fotg210_reset(struct fotg210_chip *chip) -{ - struct fotg210_regs *regs = chip->regs; - uint32_t i; - - chip->state = USB_STATE_POWERED; - - /* chip enable */ - writel(DEVCTRL_EN, ®s->dev_ctrl); - - /* device address reset */ - chip->addr = 0; - writel(0, ®s->dev_addr); - - /* set idle counter to 7ms */ - writel(7, ®s->idle); - - /* disable all interrupts */ - writel(IMR_MASK, ®s->imr); - writel(GIMR_MASK, ®s->gimr); - writel(GIMR0_MASK, ®s->gimr0); - writel(GIMR1_MASK, ®s->gimr1); - writel(GIMR2_MASK, ®s->gimr2); - - /* clear interrupts */ - writel(ISR_MASK, ®s->isr); - writel(0, ®s->gisr); - writel(0, ®s->gisr0); - writel(0, ®s->gisr1); - writel(0, ®s->gisr2); - - /* chip reset */ - setbits_le32(®s->dev_ctrl, DEVCTRL_RESET); - mdelay(10); - if (readl(®s->dev_ctrl) & DEVCTRL_RESET) { - printf("fotg210: chip reset failed\n"); - return -1; - } - - /* CX FIFO reset */ - setbits_le32(®s->cxfifo, CXFIFO_CXFIFOCLR); - mdelay(10); - if (readl(®s->cxfifo) & CXFIFO_CXFIFOCLR) { - printf("fotg210: ep0 fifo reset failed\n"); - return -1; - } - - /* create static ep-fifo map (EP1 <-> FIFO0, EP2 <-> FIFO1 ...) */ - writel(EPMAP14_DEFAULT, ®s->epmap14); - writel(EPMAP58_DEFAULT, ®s->epmap58); - writel(FIFOMAP_DEFAULT, ®s->fifomap); - writel(0, ®s->fifocfg); - for (i = 0; i < 8; ++i) { - writel(CFG_EPX_MAX_PACKET_SIZE, ®s->iep[i]); - writel(CFG_EPX_MAX_PACKET_SIZE, ®s->oep[i]); - } - - /* FIFO reset */ - for (i = 0; i < 4; ++i) { - writel(FIFOCSR_RESET, ®s->fifocsr[i]); - mdelay(10); - if (readl(®s->fifocsr[i]) & FIFOCSR_RESET) { - printf("fotg210: fifo%d reset failed\n", i); - return -1; - } - } - - /* enable only device interrupt and triggered at level-high */ - writel(IMR_IRQLH | IMR_HOST | IMR_OTG, ®s->imr); - writel(ISR_MASK, ®s->isr); - /* disable EP0 IN/OUT interrupt */ - writel(GIMR0_CXOUT | GIMR0_CXIN, ®s->gimr0); - /* disable EPX IN+SPK+OUT interrupts */ - writel(GIMR1_MASK, ®s->gimr1); - /* disable wakeup+idle+dma+zlp interrupts */ - writel(GIMR2_WAKEUP | GIMR2_IDLE | GIMR2_DMAERR | GIMR2_DMAFIN - | GIMR2_ZLPRX | GIMR2_ZLPTX, ®s->gimr2); - /* enable all group interrupt */ - writel(0, ®s->gimr); - - /* suspend delay = 3 ms */ - writel(3, ®s->idle); - - /* turn-on device interrupts */ - setbits_le32(®s->dev_ctrl, DEVCTRL_GIRQ_EN); - - return 0; -} - -static inline int fotg210_cxwait(struct fotg210_chip *chip, uint32_t mask) -{ - struct fotg210_regs *regs = chip->regs; - int ret = -1; - ulong ts; - - for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) { - if ((readl(®s->cxfifo) & mask) != mask) - continue; - ret = 0; - break; - } - - if (ret) - printf("fotg210: cx/ep0 timeout\n"); - - return ret; -} - -static int fotg210_dma(struct fotg210_ep *ep, struct fotg210_request *req) -{ - struct fotg210_chip *chip = ep->chip; - struct fotg210_regs *regs = chip->regs; - uint32_t tmp, ts; - uint8_t *buf = req->req.buf + req->req.actual; - uint32_t len = req->req.length - req->req.actual; - int fifo = ep_to_fifo(chip, ep->id); - int ret = -EBUSY; - - /* 1. init dma buffer */ - if (len > ep->maxpacket) - len = ep->maxpacket; - - /* 2. wait for dma ready (hardware) */ - for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) { - if (!(readl(®s->dma_ctrl) & DMACTRL_START)) { - ret = 0; - break; - } - } - if (ret) { - printf("fotg210: dma busy\n"); - req->req.status = ret; - return ret; - } - - /* 3. DMA target setup */ - if (ep->desc->bEndpointAddress & USB_DIR_IN) - flush_dcache_range((ulong)buf, (ulong)buf + len); - else - invalidate_dcache_range((ulong)buf, (ulong)buf + len); - - writel(virt_to_phys(buf), ®s->dma_addr); - - if (ep->desc->bEndpointAddress & USB_DIR_IN) { - if (ep->id == 0) { - /* Wait until cx/ep0 fifo empty */ - fotg210_cxwait(chip, CXFIFO_CXFIFOE); - udelay(1); - writel(DMAFIFO_CX, ®s->dma_fifo); - } else { - /* Wait until epx fifo empty */ - fotg210_cxwait(chip, CXFIFO_FIFOE(fifo)); - writel(DMAFIFO_FIFO(fifo), ®s->dma_fifo); - } - writel(DMACTRL_LEN(len) | DMACTRL_MEM2FIFO, ®s->dma_ctrl); - } else { - uint32_t blen; - - if (ep->id == 0) { - writel(DMAFIFO_CX, ®s->dma_fifo); - do { - blen = CXFIFO_BYTES(readl(®s->cxfifo)); - } while (blen < len); - } else { - writel(DMAFIFO_FIFO(fifo), ®s->dma_fifo); - blen = FIFOCSR_BYTES(readl(®s->fifocsr[fifo])); - } - len = (len < blen) ? len : blen; - writel(DMACTRL_LEN(len) | DMACTRL_FIFO2MEM, ®s->dma_ctrl); - } - - /* 4. DMA start */ - setbits_le32(®s->dma_ctrl, DMACTRL_START); - - /* 5. DMA wait */ - ret = -EBUSY; - for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) { - tmp = readl(®s->gisr2); - /* DMA complete */ - if (tmp & GISR2_DMAFIN) { - ret = 0; - break; - } - /* DMA error */ - if (tmp & GISR2_DMAERR) { - printf("fotg210: dma error\n"); - break; - } - /* resume, suspend, reset */ - if (tmp & (GISR2_RESUME | GISR2_SUSPEND | GISR2_RESET)) { - printf("fotg210: dma reset by host\n"); - break; - } - } - - /* 7. DMA target reset */ - if (ret) - writel(DMACTRL_ABORT | DMACTRL_CLRFF, ®s->dma_ctrl); - - writel(0, ®s->gisr2); - writel(0, ®s->dma_fifo); - - req->req.status = ret; - if (!ret) - req->req.actual += len; - else - printf("fotg210: ep%d dma error(code=%d)\n", ep->id, ret); - - return len; -} - -/* - * result of setup packet - */ -#define CX_IDLE 0 -#define CX_FINISH 1 -#define CX_STALL 2 - -static void fotg210_setup(struct fotg210_chip *chip) -{ - int id, ret = CX_IDLE; - uint32_t tmp[2]; - struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)tmp; - struct fotg210_regs *regs = chip->regs; - - /* - * If this is the first Cx 8 byte command, - * we can now query USB mode (high/full speed; USB 2.0/USB 1.0) - */ - if (chip->state == USB_STATE_POWERED) { - chip->state = USB_STATE_DEFAULT; - if (readl(®s->otgcsr) & OTGCSR_DEV_B) { - /* Mini-B */ - if (readl(®s->dev_ctrl) & DEVCTRL_HS) { - puts("fotg210: HS\n"); - chip->gadget.speed = USB_SPEED_HIGH; - /* SOF mask timer = 1100 ticks */ - writel(SOFMTR_TMR(1100), ®s->sof_mtr); - } else { - puts("fotg210: FS\n"); - chip->gadget.speed = USB_SPEED_FULL; - /* SOF mask timer = 10000 ticks */ - writel(SOFMTR_TMR(10000), ®s->sof_mtr); - } - } else { - printf("fotg210: mini-A?\n"); - } - } - - /* switch data port to ep0 */ - writel(DMAFIFO_CX, ®s->dma_fifo); - /* fetch 8 bytes setup packet */ - tmp[0] = readl(®s->ep0_data); - tmp[1] = readl(®s->ep0_data); - /* release data port */ - writel(0, ®s->dma_fifo); - - if (req->bRequestType & USB_DIR_IN) - ep0_desc.bEndpointAddress = USB_DIR_IN; - else - ep0_desc.bEndpointAddress = USB_DIR_OUT; - - ret = CX_IDLE; - - if ((req->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { - switch (req->bRequest) { - case USB_REQ_SET_CONFIGURATION: - debug("fotg210: set_cfg(%d)\n", req->wValue & 0x00FF); - if (!(req->wValue & 0x00FF)) { - chip->state = USB_STATE_ADDRESS; - writel(chip->addr, ®s->dev_addr); - } else { - chip->state = USB_STATE_CONFIGURED; - writel(chip->addr | DEVADDR_CONF, - ®s->dev_addr); - } - ret = CX_IDLE; - break; - - case USB_REQ_SET_ADDRESS: - debug("fotg210: set_addr(0x%04X)\n", req->wValue); - chip->state = USB_STATE_ADDRESS; - chip->addr = req->wValue & DEVADDR_ADDR_MASK; - ret = CX_FINISH; - writel(chip->addr, ®s->dev_addr); - break; - - case USB_REQ_CLEAR_FEATURE: - debug("fotg210: clr_feature(%d, %d)\n", - req->bRequestType & 0x03, req->wValue); - switch (req->wValue) { - case 0: /* [Endpoint] halt */ - ep_reset(chip, req->wIndex); - ret = CX_FINISH; - break; - case 1: /* [Device] remote wake-up */ - case 2: /* [Device] test mode */ - default: - ret = CX_STALL; - break; - } - break; - - case USB_REQ_SET_FEATURE: - debug("fotg210: set_feature(%d, %d)\n", - req->wValue, req->wIndex & 0xf); - switch (req->wValue) { - case 0: /* Endpoint Halt */ - id = req->wIndex & 0xf; - setbits_le32(®s->iep[id - 1], IEP_STALL); - setbits_le32(®s->oep[id - 1], OEP_STALL); - ret = CX_FINISH; - break; - case 1: /* Remote Wakeup */ - case 2: /* Test Mode */ - default: - ret = CX_STALL; - break; - } - break; - - case USB_REQ_GET_STATUS: - debug("fotg210: get_status\n"); - ret = CX_STALL; - break; - - case USB_REQ_SET_DESCRIPTOR: - debug("fotg210: set_descriptor\n"); - ret = CX_STALL; - break; - - case USB_REQ_SYNCH_FRAME: - debug("fotg210: sync frame\n"); - ret = CX_STALL; - break; - } - } /* if ((req->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) */ - - if (ret == CX_IDLE && chip->driver->setup) { - if (chip->driver->setup(&chip->gadget, req) < 0) - ret = CX_STALL; - else - ret = CX_FINISH; - } - - switch (ret) { - case CX_FINISH: - setbits_le32(®s->cxfifo, CXFIFO_CXFIN); - break; - - case CX_STALL: - setbits_le32(®s->cxfifo, CXFIFO_CXSTALL | CXFIFO_CXFIN); - printf("fotg210: cx_stall!\n"); - break; - - case CX_IDLE: - debug("fotg210: cx_idle?\n"); - default: - break; - } -} - -/* - * fifo - FIFO id - * zlp - zero length packet - */ -static void fotg210_recv(struct fotg210_chip *chip, int ep_id) -{ - struct fotg210_regs *regs = chip->regs; - struct fotg210_ep *ep = chip->ep + ep_id; - struct fotg210_request *req; - int len; - - if (ep->stopped || (ep->desc->bEndpointAddress & USB_DIR_IN)) { - printf("fotg210: ep%d recv, invalid!\n", ep->id); - return; - } - - if (list_empty(&ep->queue)) { - printf("fotg210: ep%d recv, drop!\n", ep->id); - return; - } - - req = list_first_entry(&ep->queue, struct fotg210_request, queue); - len = fotg210_dma(ep, req); - if (len < ep->ep.maxpacket || req->req.length <= req->req.actual) { - list_del_init(&req->queue); - if (req->req.complete) - req->req.complete(&ep->ep, &req->req); - } - - if (ep->id > 0 && list_empty(&ep->queue)) { - setbits_le32(®s->gimr1, - GIMR1_FIFO_RX(ep_to_fifo(chip, ep->id))); - } -} - -/* - * USB Gadget Layer - */ -static int fotg210_ep_enable( - struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) -{ - struct fotg210_ep *ep = container_of(_ep, struct fotg210_ep, ep); - struct fotg210_chip *chip = ep->chip; - struct fotg210_regs *regs = chip->regs; - int id = ep_to_fifo(chip, ep->id); - int in = (desc->bEndpointAddress & USB_DIR_IN) ? 1 : 0; - - if (!_ep || !desc - || desc->bDescriptorType != USB_DT_ENDPOINT - || le16_to_cpu(desc->wMaxPacketSize) == 0) { - printf("fotg210: bad ep or descriptor\n"); - return -EINVAL; - } - - ep->desc = desc; - ep->stopped = 0; - - if (in) - setbits_le32(®s->fifomap, FIFOMAP(id, FIFOMAP_IN)); - - switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_CONTROL: - return -EINVAL; - - case USB_ENDPOINT_XFER_ISOC: - setbits_le32(®s->fifocfg, - FIFOCFG(id, FIFOCFG_EN | FIFOCFG_ISOC)); - break; - - case USB_ENDPOINT_XFER_BULK: - setbits_le32(®s->fifocfg, - FIFOCFG(id, FIFOCFG_EN | FIFOCFG_BULK)); - break; - - case USB_ENDPOINT_XFER_INT: - setbits_le32(®s->fifocfg, - FIFOCFG(id, FIFOCFG_EN | FIFOCFG_INTR)); - break; - } - - return 0; -} - -static int fotg210_ep_disable(struct usb_ep *_ep) -{ - struct fotg210_ep *ep = container_of(_ep, struct fotg210_ep, ep); - struct fotg210_chip *chip = ep->chip; - struct fotg210_regs *regs = chip->regs; - int id = ep_to_fifo(chip, ep->id); - - ep->desc = NULL; - ep->stopped = 1; - - clrbits_le32(®s->fifocfg, FIFOCFG(id, FIFOCFG_CFG_MASK)); - clrbits_le32(®s->fifomap, FIFOMAP(id, FIFOMAP_DIR_MASK)); - - return 0; -} - -static struct usb_request *fotg210_ep_alloc_request( - struct usb_ep *_ep, gfp_t gfp_flags) -{ - struct fotg210_request *req = malloc(sizeof(*req)); - - if (req) { - memset(req, 0, sizeof(*req)); - INIT_LIST_HEAD(&req->queue); - } - return &req->req; -} - -static void fotg210_ep_free_request( - struct usb_ep *_ep, struct usb_request *_req) -{ - struct fotg210_request *req; - - req = container_of(_req, struct fotg210_request, req); - free(req); -} - -static int fotg210_ep_queue( - struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) -{ - struct fotg210_ep *ep = container_of(_ep, struct fotg210_ep, ep); - struct fotg210_chip *chip = ep->chip; - struct fotg210_regs *regs = chip->regs; - struct fotg210_request *req; - - req = container_of(_req, struct fotg210_request, req); - if (!_req || !_req->complete || !_req->buf - || !list_empty(&req->queue)) { - printf("fotg210: invalid request to ep%d\n", ep->id); - return -EINVAL; - } - - if (!chip || chip->state == USB_STATE_SUSPENDED) { - printf("fotg210: request while chip suspended\n"); - return -EINVAL; - } - - req->req.actual = 0; - req->req.status = -EINPROGRESS; - - if (req->req.length == 0) { - req->req.status = 0; - if (req->req.complete) - req->req.complete(&ep->ep, &req->req); - return 0; - } - - if (ep->id == 0) { - do { - int len = fotg210_dma(ep, req); - if (len < ep->ep.maxpacket) - break; - if (ep->desc->bEndpointAddress & USB_DIR_IN) - udelay(100); - } while (req->req.length > req->req.actual); - } else { - if (ep->desc->bEndpointAddress & USB_DIR_IN) { - do { - int len = fotg210_dma(ep, req); - if (len < ep->ep.maxpacket) - break; - } while (req->req.length > req->req.actual); - } else { - list_add_tail(&req->queue, &ep->queue); - clrbits_le32(®s->gimr1, - GIMR1_FIFO_RX(ep_to_fifo(chip, ep->id))); - } - } - - if (ep->id == 0 || (ep->desc->bEndpointAddress & USB_DIR_IN)) { - if (req->req.complete) - req->req.complete(&ep->ep, &req->req); - } - - return 0; -} - -static int fotg210_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) -{ - struct fotg210_ep *ep = container_of(_ep, struct fotg210_ep, ep); - struct fotg210_request *req; - - /* make sure it's actually queued on this endpoint */ - list_for_each_entry(req, &ep->queue, queue) { - if (&req->req == _req) - break; - } - if (&req->req != _req) - return -EINVAL; - - /* remove the request */ - list_del_init(&req->queue); - - /* update status & invoke complete callback */ - if (req->req.status == -EINPROGRESS) { - req->req.status = -ECONNRESET; - if (req->req.complete) - req->req.complete(_ep, &req->req); - } - - return 0; -} - -static int fotg210_ep_halt(struct usb_ep *_ep, int halt) -{ - struct fotg210_ep *ep = container_of(_ep, struct fotg210_ep, ep); - struct fotg210_chip *chip = ep->chip; - struct fotg210_regs *regs = chip->regs; - int ret = -1; - - debug("fotg210: ep%d halt=%d\n", ep->id, halt); - - /* Endpoint STALL */ - if (ep->id > 0 && ep->id <= CFG_NUM_ENDPOINTS) { - if (halt) { - /* wait until all ep fifo empty */ - fotg210_cxwait(chip, 0xf00); - /* stall */ - if (ep->desc->bEndpointAddress & USB_DIR_IN) { - setbits_le32(®s->iep[ep->id - 1], - IEP_STALL); - } else { - setbits_le32(®s->oep[ep->id - 1], - OEP_STALL); - } - } else { - if (ep->desc->bEndpointAddress & USB_DIR_IN) { - clrbits_le32(®s->iep[ep->id - 1], - IEP_STALL); - } else { - clrbits_le32(®s->oep[ep->id - 1], - OEP_STALL); - } - } - ret = 0; - } - - return ret; -} - -/* - * activate/deactivate link with host. - */ -static void pullup(struct fotg210_chip *chip, int is_on) -{ - struct fotg210_regs *regs = chip->regs; - - if (is_on) { - if (!chip->pullup) { - chip->state = USB_STATE_POWERED; - chip->pullup = 1; - /* enable the chip */ - setbits_le32(®s->dev_ctrl, DEVCTRL_EN); - /* clear unplug bit (BIT0) */ - clrbits_le32(®s->phy_tmsr, PHYTMSR_UNPLUG); - } - } else { - chip->state = USB_STATE_NOTATTACHED; - chip->pullup = 0; - chip->addr = 0; - writel(chip->addr, ®s->dev_addr); - /* set unplug bit (BIT0) */ - setbits_le32(®s->phy_tmsr, PHYTMSR_UNPLUG); - /* disable the chip */ - clrbits_le32(®s->dev_ctrl, DEVCTRL_EN); - } -} - -static int fotg210_pullup(struct usb_gadget *_gadget, int is_on) -{ - struct fotg210_chip *chip; - - chip = container_of(_gadget, struct fotg210_chip, gadget); - - debug("fotg210: pullup=%d\n", is_on); - - pullup(chip, is_on); - - return 0; -} - -static int fotg210_get_frame(struct usb_gadget *_gadget) -{ - struct fotg210_chip *chip; - struct fotg210_regs *regs; - - chip = container_of(_gadget, struct fotg210_chip, gadget); - regs = chip->regs; - - return SOFFNR_FNR(readl(®s->sof_fnr)); -} - -static struct usb_gadget_ops fotg210_gadget_ops = { - .get_frame = fotg210_get_frame, - .pullup = fotg210_pullup, -}; - -static struct usb_ep_ops fotg210_ep_ops = { - .enable = fotg210_ep_enable, - .disable = fotg210_ep_disable, - .queue = fotg210_ep_queue, - .dequeue = fotg210_ep_dequeue, - .set_halt = fotg210_ep_halt, - .alloc_request = fotg210_ep_alloc_request, - .free_request = fotg210_ep_free_request, -}; - -static struct fotg210_chip controller = { - .regs = (void __iomem *)CONFIG_FOTG210_BASE, - .gadget = { - .name = "fotg210_udc", - .ops = &fotg210_gadget_ops, - .ep0 = &controller.ep[0].ep, - .speed = USB_SPEED_UNKNOWN, - .is_dualspeed = 1, - .is_otg = 0, - .is_a_peripheral = 0, - .b_hnp_enable = 0, - .a_hnp_support = 0, - .a_alt_hnp_support = 0, - }, - .ep[0] = { - .id = 0, - .ep = { - .name = "ep0", - .ops = &fotg210_ep_ops, - }, - .desc = &ep0_desc, - .chip = &controller, - .maxpacket = CFG_EP0_MAX_PACKET_SIZE, - }, - .ep[1] = { - .id = 1, - .ep = { - .name = "ep1", - .ops = &fotg210_ep_ops, - }, - .chip = &controller, - .maxpacket = CFG_EPX_MAX_PACKET_SIZE, - }, - .ep[2] = { - .id = 2, - .ep = { - .name = "ep2", - .ops = &fotg210_ep_ops, - }, - .chip = &controller, - .maxpacket = CFG_EPX_MAX_PACKET_SIZE, - }, - .ep[3] = { - .id = 3, - .ep = { - .name = "ep3", - .ops = &fotg210_ep_ops, - }, - .chip = &controller, - .maxpacket = CFG_EPX_MAX_PACKET_SIZE, - }, - .ep[4] = { - .id = 4, - .ep = { - .name = "ep4", - .ops = &fotg210_ep_ops, - }, - .chip = &controller, - .maxpacket = CFG_EPX_MAX_PACKET_SIZE, - }, -}; - -int usb_gadget_handle_interrupts(void) -{ - struct fotg210_chip *chip = &controller; - struct fotg210_regs *regs = chip->regs; - uint32_t id, st, isr, gisr; - - isr = readl(®s->isr) & (~readl(®s->imr)); - gisr = readl(®s->gisr) & (~readl(®s->gimr)); - if (!(isr & ISR_DEV) || !gisr) - return 0; - - writel(ISR_DEV, ®s->isr); - - /* CX interrupts */ - if (gisr & GISR_GRP0) { - st = readl(®s->gisr0); - /* - * Write 1 and then 0 works for both W1C & RW. - * - * HW v1.11.0+: It's a W1C register (write 1 clear) - * HW v1.10.0-: It's a R/W register (write 0 clear) - */ - writel(st & GISR0_CXABORT, ®s->gisr0); - writel(0, ®s->gisr0); - - if (st & GISR0_CXERR) - printf("fotg210: cmd error\n"); - - if (st & GISR0_CXABORT) - printf("fotg210: cmd abort\n"); - - if (st & GISR0_CXSETUP) /* setup */ - fotg210_setup(chip); - else if (st & GISR0_CXEND) /* command finish */ - setbits_le32(®s->cxfifo, CXFIFO_CXFIN); - } - - /* FIFO interrupts */ - if (gisr & GISR_GRP1) { - st = readl(®s->gisr1); - for (id = 0; id < 4; ++id) { - if (st & GISR1_RX_FIFO(id)) - fotg210_recv(chip, fifo_to_ep(chip, id, 0)); - } - } - - /* Device Status Interrupts */ - if (gisr & GISR_GRP2) { - st = readl(®s->gisr2); - /* - * Write 1 and then 0 works for both W1C & RW. - * - * HW v1.11.0+: It's a W1C register (write 1 clear) - * HW v1.10.0-: It's a R/W register (write 0 clear) - */ - writel(st, ®s->gisr2); - writel(0, ®s->gisr2); - - if (st & GISR2_RESET) - printf("fotg210: reset by host\n"); - else if (st & GISR2_SUSPEND) - printf("fotg210: suspend/removed\n"); - else if (st & GISR2_RESUME) - printf("fotg210: resume\n"); - - /* Errors */ - if (st & GISR2_ISOCERR) - printf("fotg210: iso error\n"); - if (st & GISR2_ISOCABT) - printf("fotg210: iso abort\n"); - if (st & GISR2_DMAERR) - printf("fotg210: dma error\n"); - } - - return 0; -} - -int usb_gadget_register_driver(struct usb_gadget_driver *driver) -{ - int i, ret = 0; - struct fotg210_chip *chip = &controller; - - if (!driver || !driver->bind || !driver->setup) { - puts("fotg210: bad parameter.\n"); - return -EINVAL; - } - - INIT_LIST_HEAD(&chip->gadget.ep_list); - for (i = 0; i < CFG_NUM_ENDPOINTS + 1; ++i) { - struct fotg210_ep *ep = chip->ep + i; - - ep->ep.maxpacket = ep->maxpacket; - INIT_LIST_HEAD(&ep->queue); - - if (ep->id == 0) { - ep->stopped = 0; - } else { - ep->stopped = 1; - list_add_tail(&ep->ep.ep_list, &chip->gadget.ep_list); - } - } - - if (fotg210_reset(chip)) { - puts("fotg210: reset failed.\n"); - return -EINVAL; - } - - ret = driver->bind(&chip->gadget); - if (ret) { - debug("fotg210: driver->bind() returned %d\n", ret); - return ret; - } - chip->driver = driver; - - return ret; -} - -int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -{ - struct fotg210_chip *chip = &controller; - - driver->unbind(&chip->gadget); - chip->driver = NULL; - - pullup(chip, 0); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/g_dnl.c b/qemu/roms/u-boot/drivers/usb/gadget/g_dnl.c deleted file mode 100644 index 25611acd6..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/g_dnl.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * g_dnl.c -- USB Downloader Gadget - * - * Copyright (C) 2012 Samsung Electronics - * Lukasz Majewski <l.majewski@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <malloc.h> - -#include <mmc.h> -#include <part.h> - -#include <g_dnl.h> -#include <usb_mass_storage.h> -#include <dfu.h> -#include <thor.h> - -#include "gadget_chips.h" -#include "composite.c" - -/* - * One needs to define the following: - * CONFIG_G_DNL_VENDOR_NUM - * CONFIG_G_DNL_PRODUCT_NUM - * CONFIG_G_DNL_MANUFACTURER - * at e.g. ./include/configs/<board>.h - */ - -#define STRING_MANUFACTURER 25 -#define STRING_PRODUCT 2 -/* Index of String Descriptor describing this configuration */ -#define STRING_USBDOWN 2 -/* Index of String serial */ -#define STRING_SERIAL 3 -#define MAX_STRING_SERIAL 32 -/* Number of supported configurations */ -#define CONFIGURATION_NUMBER 1 - -#define DRIVER_VERSION "usb_dnl 2.0" - -static const char product[] = "USB download gadget"; -static char g_dnl_serial[MAX_STRING_SERIAL]; -static const char manufacturer[] = CONFIG_G_DNL_MANUFACTURER; - -void g_dnl_set_serialnumber(char *s) -{ - memset(g_dnl_serial, 0, MAX_STRING_SERIAL); - if (strlen(s) < MAX_STRING_SERIAL) - strncpy(g_dnl_serial, s, strlen(s)); -} - -static struct usb_device_descriptor device_desc = { - .bLength = sizeof device_desc, - .bDescriptorType = USB_DT_DEVICE, - - .bcdUSB = __constant_cpu_to_le16(0x0200), - .bDeviceClass = USB_CLASS_COMM, - .bDeviceSubClass = 0x02, /*0x02:CDC-modem , 0x00:CDC-serial*/ - - .idVendor = __constant_cpu_to_le16(CONFIG_G_DNL_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(CONFIG_G_DNL_PRODUCT_NUM), - .iProduct = STRING_PRODUCT, - .iSerialNumber = STRING_SERIAL, - .bNumConfigurations = 1, -}; - -/* - * static strings, in UTF-8 - * IDs for those strings are assigned dynamically at g_dnl_bind() - */ -static struct usb_string g_dnl_string_defs[] = { - {.s = manufacturer}, - {.s = product}, - {.s = g_dnl_serial}, - { } /* end of list */ -}; - -static struct usb_gadget_strings g_dnl_string_tab = { - .language = 0x0409, /* en-us */ - .strings = g_dnl_string_defs, -}; - -static struct usb_gadget_strings *g_dnl_composite_strings[] = { - &g_dnl_string_tab, - NULL, -}; - -static int g_dnl_unbind(struct usb_composite_dev *cdev) -{ - struct usb_gadget *gadget = cdev->gadget; - - free(cdev->config); - cdev->config = NULL; - debug("%s: calling usb_gadget_disconnect for " - "controller '%s'\n", __func__, gadget->name); - usb_gadget_disconnect(gadget); - - return 0; -} - -static inline struct g_dnl_bind_callback *g_dnl_bind_callback_first(void) -{ - return ll_entry_start(struct g_dnl_bind_callback, - g_dnl_bind_callbacks); -} - -static inline struct g_dnl_bind_callback *g_dnl_bind_callback_end(void) -{ - return ll_entry_end(struct g_dnl_bind_callback, - g_dnl_bind_callbacks); -} - -static int g_dnl_do_config(struct usb_configuration *c) -{ - const char *s = c->cdev->driver->name; - struct g_dnl_bind_callback *callback = g_dnl_bind_callback_first(); - - debug("%s: configuration: 0x%p composite dev: 0x%p\n", - __func__, c, c->cdev); - - for (; callback != g_dnl_bind_callback_end(); callback++) - if (!strcmp(s, callback->usb_function_name)) - return callback->fptr(c); - return -ENODEV; -} - -static int g_dnl_config_register(struct usb_composite_dev *cdev) -{ - struct usb_configuration *config; - const char *name = "usb_dnload"; - - config = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*config)); - if (!config) - return -ENOMEM; - - memset(config, 0, sizeof(*config)); - - config->label = name; - config->bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER; - config->bConfigurationValue = CONFIGURATION_NUMBER; - config->iConfiguration = STRING_USBDOWN; - config->bind = g_dnl_do_config; - - return usb_add_config(cdev, config); -} - -__weak -int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) -{ - return 0; -} - -__weak int g_dnl_get_board_bcd_device_number(int gcnum) -{ - return gcnum; -} - -__weak int g_dnl_board_usb_cable_connected(void) -{ - return -EOPNOTSUPP; -} - -static int g_dnl_get_bcd_device_number(struct usb_composite_dev *cdev) -{ - struct usb_gadget *gadget = cdev->gadget; - int gcnum; - - gcnum = usb_gadget_controller_number(gadget); - if (gcnum > 0) - gcnum += 0x200; - - return g_dnl_get_board_bcd_device_number(gcnum); -} - -static int g_dnl_bind(struct usb_composite_dev *cdev) -{ - struct usb_gadget *gadget = cdev->gadget; - int id, ret; - int gcnum; - - debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__, gadget, cdev); - - id = usb_string_id(cdev); - - if (id < 0) - return id; - g_dnl_string_defs[0].id = id; - device_desc.iManufacturer = id; - - id = usb_string_id(cdev); - if (id < 0) - return id; - - g_dnl_string_defs[1].id = id; - device_desc.iProduct = id; - - id = usb_string_id(cdev); - if (id < 0) - return id; - - g_dnl_string_defs[2].id = id; - device_desc.iSerialNumber = id; - - g_dnl_bind_fixup(&device_desc, cdev->driver->name); - ret = g_dnl_config_register(cdev); - if (ret) - goto error; - - gcnum = g_dnl_get_bcd_device_number(cdev); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(gcnum); - else { - debug("%s: controller '%s' not recognized\n", - __func__, gadget->name); - device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); - } - - debug("%s: calling usb_gadget_connect for " - "controller '%s'\n", __func__, gadget->name); - usb_gadget_connect(gadget); - - return 0; - - error: - g_dnl_unbind(cdev); - return -ENOMEM; -} - -static struct usb_composite_driver g_dnl_driver = { - .name = NULL, - .dev = &device_desc, - .strings = g_dnl_composite_strings, - - .bind = g_dnl_bind, - .unbind = g_dnl_unbind, -}; - -/* - * NOTICE: - * Registering via USB function name won't be necessary after rewriting - * g_dnl to support multiple USB functions. - */ -int g_dnl_register(const char *name) -{ - int ret; - - debug("%s: g_dnl_driver.name = %s\n", __func__, name); - g_dnl_driver.name = name; - - ret = usb_composite_register(&g_dnl_driver); - if (ret) { - printf("%s: failed!, error: %d\n", __func__, ret); - return ret; - } - return 0; -} - -void g_dnl_unregister(void) -{ - usb_composite_unregister(&g_dnl_driver); -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/gadget_chips.h b/qemu/roms/u-boot/drivers/usb/gadget/gadget_chips.h deleted file mode 100644 index cc94771e3..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/gadget_chips.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - * USB device controllers have lots of quirks. Use these macros in - * gadget drivers or other code that needs to deal with them, and which - * autoconfigures instead of using early binding to the hardware. - * - * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by - * some config file that gets updated as new hardware is supported. - * (And avoiding all runtime comparisons in typical one-choice configs!) - * - * NOTE: some of these controller drivers may not be available yet. - * Some are available on 2.4 kernels; several are available, but not - * yet pushed in the 2.6 mainline tree. - * - * Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and - * Remy Bohmer <linux@bohmer.net> - */ -#ifdef CONFIG_USB_GADGET_NET2280 -#define gadget_is_net2280(g) (!strcmp("net2280", (g)->name)) -#else -#define gadget_is_net2280(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_AMD5536UDC -#define gadget_is_amd5536udc(g) (!strcmp("amd5536udc", (g)->name)) -#else -#define gadget_is_amd5536udc(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_DUMMY_HCD -#define gadget_is_dummy(g) (!strcmp("dummy_udc", (g)->name)) -#else -#define gadget_is_dummy(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_PXA2XX -#define gadget_is_pxa(g) (!strcmp("pxa2xx_udc", (g)->name)) -#else -#define gadget_is_pxa(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_GOKU -#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name)) -#else -#define gadget_is_goku(g) 0 -#endif - -/* SH3 UDC -- not yet ported 2.4 --> 2.6 */ -#ifdef CONFIG_USB_GADGET_SUPERH -#define gadget_is_sh(g) (!strcmp("sh_udc", (g)->name)) -#else -#define gadget_is_sh(g) 0 -#endif - -/* not yet stable on 2.6 (would help "original Zaurus") */ -#ifdef CONFIG_USB_GADGET_SA1100 -#define gadget_is_sa1100(g) (!strcmp("sa1100_udc", (g)->name)) -#else -#define gadget_is_sa1100(g) 0 -#endif - -/* handhelds.org tree (?) */ -#ifdef CONFIG_USB_GADGET_MQ11XX -#define gadget_is_mq11xx(g) (!strcmp("mq11xx_udc", (g)->name)) -#else -#define gadget_is_mq11xx(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_OMAP -#define gadget_is_omap(g) (!strcmp("omap_udc", (g)->name)) -#else -#define gadget_is_omap(g) 0 -#endif - -/* not yet ported 2.4 --> 2.6 */ -#ifdef CONFIG_USB_GADGET_N9604 -#define gadget_is_n9604(g) (!strcmp("n9604_udc", (g)->name)) -#else -#define gadget_is_n9604(g) 0 -#endif - -/* various unstable versions available */ -#ifdef CONFIG_USB_GADGET_PXA27X -#define gadget_is_pxa27x(g) (!strcmp("pxa27x_udc", (g)->name)) -#else -#define gadget_is_pxa27x(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_ATMEL_USBA -#define gadget_is_atmel_usba(g) (!strcmp("atmel_usba_udc", (g)->name)) -#else -#define gadget_is_atmel_usba(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_S3C2410 -#define gadget_is_s3c2410(g) (!strcmp("s3c2410_udc", (g)->name)) -#else -#define gadget_is_s3c2410(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_AT91 -#define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name)) -#else -#define gadget_is_at91(g) 0 -#endif - -/* status unclear */ -#ifdef CONFIG_USB_GADGET_IMX -#define gadget_is_imx(g) (!strcmp("imx_udc", (g)->name)) -#else -#define gadget_is_imx(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_FSL_USB2 -#define gadget_is_fsl_usb2(g) (!strcmp("fsl-usb2-udc", (g)->name)) -#else -#define gadget_is_fsl_usb2(g) 0 -#endif - -/* Mentor high speed function controller */ -/* from Montavista kernel (?) */ -#ifdef CONFIG_USB_GADGET_MUSBHSFC -#define gadget_is_musbhsfc(g) (!strcmp("musbhsfc_udc", (g)->name)) -#else -#define gadget_is_musbhsfc(g) 0 -#endif - -/* Mentor high speed "dual role" controller, in peripheral role */ -#ifdef CONFIG_MUSB_GADGET -#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name)) -#else -#define gadget_is_musbhdrc(g) 0 -#endif - -/* from Montavista kernel (?) */ -#ifdef CONFIG_USB_GADGET_MPC8272 -#define gadget_is_mpc8272(g) (!strcmp("mpc8272_udc", (g)->name)) -#else -#define gadget_is_mpc8272(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_M66592 -#define gadget_is_m66592(g) (!strcmp("m66592_udc", (g)->name)) -#else -#define gadget_is_m66592(g) 0 -#endif - -#ifdef CONFIG_CI_UDC -#define gadget_is_ci(g) (!strcmp("ci_udc", (g)->name)) -#else -#define gadget_is_ci(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_FOTG210 -#define gadget_is_fotg210(g) (!strcmp("fotg210_udc", (g)->name)) -#else -#define gadget_is_fotg210(g) 0 -#endif - -/* - * CONFIG_USB_GADGET_SX2 - * CONFIG_USB_GADGET_AU1X00 - * ... - */ - -/** - * usb_gadget_controller_number - support bcdDevice id convention - * @gadget: the controller being driven - * - * Return a 2-digit BCD value associated with the peripheral controller, - * suitable for use as part of a bcdDevice value, or a negative error code. - * - * NOTE: this convention is purely optional, and has no meaning in terms of - * any USB specification. If you want to use a different convention in your - * gadget driver firmware -- maybe a more formal revision ID -- feel free. - * - * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!) - * to change their behavior accordingly. For example it might help avoiding - * some chip bug. - */ -static inline int usb_gadget_controller_number(struct usb_gadget *gadget) -{ - if (gadget_is_net2280(gadget)) - return 0x01; - else if (gadget_is_dummy(gadget)) - return 0x02; - else if (gadget_is_pxa(gadget)) - return 0x03; - else if (gadget_is_sh(gadget)) - return 0x04; - else if (gadget_is_sa1100(gadget)) - return 0x05; - else if (gadget_is_goku(gadget)) - return 0x06; - else if (gadget_is_mq11xx(gadget)) - return 0x07; - else if (gadget_is_omap(gadget)) - return 0x08; - else if (gadget_is_n9604(gadget)) - return 0x09; - else if (gadget_is_pxa27x(gadget)) - return 0x10; - else if (gadget_is_s3c2410(gadget)) - return 0x11; - else if (gadget_is_at91(gadget)) - return 0x12; - else if (gadget_is_imx(gadget)) - return 0x13; - else if (gadget_is_musbhsfc(gadget)) - return 0x14; - else if (gadget_is_musbhdrc(gadget)) - return 0x15; - else if (gadget_is_mpc8272(gadget)) - return 0x16; - else if (gadget_is_atmel_usba(gadget)) - return 0x17; - else if (gadget_is_fsl_usb2(gadget)) - return 0x18; - else if (gadget_is_amd5536udc(gadget)) - return 0x19; - else if (gadget_is_m66592(gadget)) - return 0x20; - else if (gadget_is_ci(gadget)) - return 0x21; - else if (gadget_is_fotg210(gadget)) - return 0x22; - return -ENOENT; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/mpc8xx_udc.c b/qemu/roms/u-boot/drivers/usb/gadget/mpc8xx_udc.c deleted file mode 100644 index 7f72972dc..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/mpc8xx_udc.c +++ /dev/null @@ -1,1386 +0,0 @@ -/* - * Copyright (C) 2006 by Bryan O'Donoghue, CodeHermit - * bodonoghue@CodeHermit.ie - * - * References - * DasUBoot/drivers/usb/gadget/omap1510_udc.c, for design and implementation - * ideas. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Notes : - * 1. #define __SIMULATE_ERROR__ to inject a CRC error into every 2nd TX - * packet to force the USB re-transmit protocol. - * - * 2. #define __DEBUG_UDC__ to switch on debug tracing to serial console - * be careful that tracing doesn't create Hiesen-bugs with respect to - * response timeouts to control requests. - * - * 3. This driver should be able to support any higher level driver that - * that wants to do either of the two standard UDC implementations - * Control-Bulk-Interrupt or Bulk-IN/Bulk-Out standards. Hence - * gserial and cdc_acm should work with this code. - * - * 4. NAK events never actually get raised at all, the documentation - * is just wrong ! - * - * 5. For some reason, cbd_datlen is *always* +2 the value it should be. - * this means that having an RX cbd of 16 bytes is not possible, since - * the same size is reported for 14 bytes received as 16 bytes received - * until we can find out why this happens, RX cbds must be limited to 8 - * bytes. TODO: check errata for this behaviour. - * - * 6. Right now this code doesn't support properly powering up with the USB - * cable attached to the USB host my development board the Adder87x doesn't - * have a pull-up fitted to allow this, so it is necessary to power the - * board and *then* attached the USB cable to the host. However somebody - * with a different design in their board may be able to keep the cable - * constantly connected and simply enable/disable a pull-up re - * figure 31.1 in MPC885RM.pdf instead of having to power up the board and - * then attach the cable ! - * - */ -#include <common.h> -#include <config.h> -#include <commproc.h> -#include <usbdevice.h> -#include <usb/mpc8xx_udc.h> -#include <usb/udc.h> - -#include "ep0.h" - -DECLARE_GLOBAL_DATA_PTR; - -#define ERR(fmt, args...)\ - serial_printf("ERROR : [%s] %s:%d: "fmt,\ - __FILE__,__FUNCTION__,__LINE__, ##args) -#ifdef __DEBUG_UDC__ -#define DBG(fmt,args...)\ - serial_printf("[%s] %s:%d: "fmt,\ - __FILE__,__FUNCTION__,__LINE__, ##args) -#else -#define DBG(fmt,args...) -#endif - -/* Static Data */ -#ifdef __SIMULATE_ERROR__ -static char err_poison_test = 0; -#endif -static struct mpc8xx_ep ep_ref[MAX_ENDPOINTS]; -static u32 address_base = STATE_NOT_READY; -static mpc8xx_udc_state_t udc_state = 0; -static struct usb_device_instance *udc_device = 0; -static volatile usb_epb_t *endpoints[MAX_ENDPOINTS]; -static volatile cbd_t *tx_cbd[TX_RING_SIZE]; -static volatile cbd_t *rx_cbd[RX_RING_SIZE]; -static volatile immap_t *immr = 0; -static volatile cpm8xx_t *cp = 0; -static volatile usb_pram_t *usb_paramp = 0; -static volatile usb_t *usbp = 0; -static int rx_ct = 0; -static int tx_ct = 0; - -/* Static Function Declarations */ -static void mpc8xx_udc_state_transition_up (usb_device_state_t initial, - usb_device_state_t final); -static void mpc8xx_udc_state_transition_down (usb_device_state_t initial, - usb_device_state_t final); -static void mpc8xx_udc_stall (unsigned int ep); -static void mpc8xx_udc_flush_tx_fifo (int epid); -static void mpc8xx_udc_flush_rx_fifo (void); -static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp); -static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi, - struct urb *tx_urb); -static void mpc8xx_udc_dump_request (struct usb_device_request *request); -static void mpc8xx_udc_clock_init (volatile immap_t * immr, - volatile cpm8xx_t * cp); -static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi); -static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp); -static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp); -static void mpc8xx_udc_cbd_init (void); -static void mpc8xx_udc_endpoint_init (void); -static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size); -static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment); -static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp); -static void mpc8xx_udc_set_nak (unsigned int ep); -static short mpc8xx_udc_handle_txerr (void); -static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid); - -/****************************************************************************** - Global Linkage - *****************************************************************************/ - -/* udc_init - * - * Do initial bus gluing - */ -int udc_init (void) -{ - /* Init various pointers */ - immr = (immap_t *) CONFIG_SYS_IMMR; - cp = (cpm8xx_t *) & (immr->im_cpm); - usb_paramp = (usb_pram_t *) & (cp->cp_dparam[PROFF_USB]); - usbp = (usb_t *) & (cp->cp_scc[0]); - - memset (ep_ref, 0x00, (sizeof (struct mpc8xx_ep) * MAX_ENDPOINTS)); - - udc_device = 0; - udc_state = STATE_NOT_READY; - - usbp->usmod = 0x00; - usbp->uscom = 0; - - /* Set USB Frame #0, Respond at Address & Get a clock source */ - usbp->usaddr = 0x00; - mpc8xx_udc_clock_init (immr, cp); - - /* PA15, PA14 as perhiperal USBRXD and USBOE */ - immr->im_ioport.iop_padir &= ~0x0003; - immr->im_ioport.iop_papar |= 0x0003; - - /* PC11/PC10 as peripheral USBRXP USBRXN */ - immr->im_ioport.iop_pcso |= 0x0030; - - /* PC7/PC6 as perhiperal USBTXP and USBTXN */ - immr->im_ioport.iop_pcdir |= 0x0300; - immr->im_ioport.iop_pcpar |= 0x0300; - - /* Set the base address */ - address_base = (u32) (cp->cp_dpmem + CPM_USB_BASE); - - /* Initialise endpoints and circular buffers */ - mpc8xx_udc_endpoint_init (); - mpc8xx_udc_cbd_init (); - - /* Assign allocated Dual Port Endpoint descriptors */ - usb_paramp->ep0ptr = (u32) endpoints[0]; - usb_paramp->ep1ptr = (u32) endpoints[1]; - usb_paramp->ep2ptr = (u32) endpoints[2]; - usb_paramp->ep3ptr = (u32) endpoints[3]; - usb_paramp->frame_n = 0; - - DBG ("ep0ptr=0x%08x ep1ptr=0x%08x ep2ptr=0x%08x ep3ptr=0x%08x\n", - usb_paramp->ep0ptr, usb_paramp->ep1ptr, usb_paramp->ep2ptr, - usb_paramp->ep3ptr); - - return 0; -} - -/* udc_irq - * - * Poll for whatever events may have occured - */ -void udc_irq (void) -{ - int epid = 0; - volatile cbd_t *rx_cbdp = 0; - volatile cbd_t *rx_cbdp_base = 0; - - if (udc_state != STATE_READY) { - return; - } - - if (usbp->usber & USB_E_BSY) { - /* This shouldn't happen. If it does then it's a bug ! */ - usbp->usber |= USB_E_BSY; - mpc8xx_udc_flush_rx_fifo (); - } - - /* Scan all RX/Bidirectional Endpoints for RX data. */ - for (epid = 0; epid < MAX_ENDPOINTS; epid++) { - if (!ep_ref[epid].prx) { - continue; - } - rx_cbdp = rx_cbdp_base = ep_ref[epid].prx; - - do { - if (!(rx_cbdp->cbd_sc & RX_BD_E)) { - - if (rx_cbdp->cbd_sc & 0x1F) { - /* Corrupt data discard it. - * Controller has NAK'd this packet. - */ - mpc8xx_udc_clear_rxbd (rx_cbdp); - - } else { - if (!epid) { - mpc8xx_udc_ep0_rx (rx_cbdp); - - } else { - /* Process data */ - mpc8xx_udc_set_nak (epid); - mpc8xx_udc_epn_rx (epid, rx_cbdp); - mpc8xx_udc_clear_rxbd (rx_cbdp); - } - } - - /* Advance RX CBD pointer */ - mpc8xx_udc_advance_rx (&rx_cbdp, epid); - ep_ref[epid].prx = rx_cbdp; - } else { - /* Advance RX CBD pointer */ - mpc8xx_udc_advance_rx (&rx_cbdp, epid); - } - - } while (rx_cbdp != rx_cbdp_base); - } - - /* Handle TX events as appropiate, the correct place to do this is - * in a tx routine. Perhaps TX on epn was pre-empted by ep0 - */ - - if (usbp->usber & USB_E_TXB) { - usbp->usber |= USB_E_TXB; - } - - if (usbp->usber & (USB_TX_ERRMASK)) { - mpc8xx_udc_handle_txerr (); - } - - /* Switch to the default state, respond at the default address */ - if (usbp->usber & USB_E_RESET) { - usbp->usber |= USB_E_RESET; - usbp->usaddr = 0x00; - udc_device->device_state = STATE_DEFAULT; - } - - /* if(usbp->usber&USB_E_IDLE){ - We could suspend here ! - usbp->usber|=USB_E_IDLE; - DBG("idle state change\n"); - } - if(usbp->usbs){ - We could resume here when IDLE is deasserted ! - Not worth doing, so long as we are self powered though. - } - */ - - return; -} - -/* udc_endpoint_write - * - * Write some data to an endpoint - */ -int udc_endpoint_write (struct usb_endpoint_instance *epi) -{ - int ep = 0; - short epid = 1, unnak = 0, ret = 0; - - if (udc_state != STATE_READY) { - ERR ("invalid udc_state != STATE_READY!\n"); - return -1; - } - - if (!udc_device || !epi) { - return -1; - } - - if (udc_device->device_state != STATE_CONFIGURED) { - return -1; - } - - ep = epi->endpoint_address & 0x03; - if (ep >= MAX_ENDPOINTS) { - return -1; - } - - /* Set NAK for all RX endpoints during TX */ - for (epid = 1; epid < MAX_ENDPOINTS; epid++) { - - /* Don't set NAK on DATA IN/CONTROL endpoints */ - if (ep_ref[epid].sc & USB_DIR_IN) { - continue; - } - - if (!(usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK))) { - unnak |= 1 << epid; - } - - mpc8xx_udc_set_nak (epid); - } - - mpc8xx_udc_init_tx (&udc_device->bus->endpoint_array[ep], - epi->tx_urb); - ret = mpc8xx_udc_ep_tx (&udc_device->bus->endpoint_array[ep]); - - /* Remove temporary NAK */ - for (epid = 1; epid < MAX_ENDPOINTS; epid++) { - if (unnak & (1 << epid)) { - udc_unset_nak (epid); - } - } - - return ret; -} - -/* mpc8xx_udc_assign_urb - * - * Associate a given urb to an endpoint TX or RX transmit/receive buffers - */ -static int mpc8xx_udc_assign_urb (int ep, char direction) -{ - struct usb_endpoint_instance *epi = 0; - - if (ep >= MAX_ENDPOINTS) { - goto err; - } - epi = &udc_device->bus->endpoint_array[ep]; - if (!epi) { - goto err; - } - - if (!ep_ref[ep].urb) { - ep_ref[ep].urb = usbd_alloc_urb (udc_device, udc_device->bus->endpoint_array); - if (!ep_ref[ep].urb) { - goto err; - } - } else { - ep_ref[ep].urb->actual_length = 0; - } - - switch (direction) { - case USB_DIR_IN: - epi->tx_urb = ep_ref[ep].urb; - break; - case USB_DIR_OUT: - epi->rcv_urb = ep_ref[ep].urb; - break; - default: - goto err; - } - return 0; - - err: - udc_state = STATE_ERROR; - return -1; -} - -/* udc_setup_ep - * - * Associate U-Boot software endpoints to mpc8xx endpoint parameter ram - * Isochronous endpoints aren't yet supported! - */ -void udc_setup_ep (struct usb_device_instance *device, unsigned int ep, - struct usb_endpoint_instance *epi) -{ - uchar direction = 0; - int ep_attrib = 0; - - if (epi && (ep < MAX_ENDPOINTS)) { - - if (ep == 0) { - if (epi->rcv_attributes != USB_ENDPOINT_XFER_CONTROL - || epi->tx_attributes != - USB_ENDPOINT_XFER_CONTROL) { - - /* ep0 must be a control endpoint */ - udc_state = STATE_ERROR; - return; - - } - if (!(ep_ref[ep].sc & EP_ATTACHED)) { - mpc8xx_udc_cbd_attach (ep, epi->tx_packetSize, - epi->rcv_packetSize); - } - usbp->usep[ep] = 0x0000; - return; - } - - if ((epi->endpoint_address & USB_ENDPOINT_DIR_MASK) - == USB_DIR_IN) { - - direction = 1; - ep_attrib = epi->tx_attributes; - epi->rcv_packetSize = 0; - ep_ref[ep].sc |= USB_DIR_IN; - } else { - - direction = 0; - ep_attrib = epi->rcv_attributes; - epi->tx_packetSize = 0; - ep_ref[ep].sc &= ~USB_DIR_IN; - } - - if (mpc8xx_udc_assign_urb (ep, epi->endpoint_address - & USB_ENDPOINT_DIR_MASK)) { - return; - } - - switch (ep_attrib) { - case USB_ENDPOINT_XFER_CONTROL: - if (!(ep_ref[ep].sc & EP_ATTACHED)) { - mpc8xx_udc_cbd_attach (ep, - epi->tx_packetSize, - epi->rcv_packetSize); - } - usbp->usep[ep] = ep << 12; - epi->rcv_urb = epi->tx_urb = ep_ref[ep].urb; - - break; - case USB_ENDPOINT_XFER_BULK: - case USB_ENDPOINT_XFER_INT: - if (!(ep_ref[ep].sc & EP_ATTACHED)) { - if (direction) { - mpc8xx_udc_cbd_attach (ep, - epi->tx_packetSize, - 0); - } else { - mpc8xx_udc_cbd_attach (ep, - 0, - epi->rcv_packetSize); - } - } - usbp->usep[ep] = (ep << 12) | ((ep_attrib) << 8); - - break; - case USB_ENDPOINT_XFER_ISOC: - default: - serial_printf ("Error endpoint attrib %d>3\n", ep_attrib); - udc_state = STATE_ERROR; - break; - } - } - -} - -/* udc_connect - * - * Move state, switch on the USB - */ -void udc_connect (void) -{ - /* Enable pull-up resistor on D+ - * TODO: fit a pull-up resistor to drive SE0 for > 2.5us - */ - - if (udc_state != STATE_ERROR) { - udc_state = STATE_READY; - usbp->usmod |= USMOD_EN; - } -} - -/* udc_disconnect - * - * Disconnect is not used but, is included for completeness - */ -void udc_disconnect (void) -{ - /* Disable pull-up resistor on D- - * TODO: fix a pullup resistor to control this - */ - - if (udc_state != STATE_ERROR) { - udc_state = STATE_NOT_READY; - } - usbp->usmod &= ~USMOD_EN; -} - -/* udc_enable - * - * Grab an EP0 URB, register interest in a subset of USB events - */ -void udc_enable (struct usb_device_instance *device) -{ - if (udc_state == STATE_ERROR) { - return; - } - - udc_device = device; - - if (!ep_ref[0].urb) { - ep_ref[0].urb = usbd_alloc_urb (device, device->bus->endpoint_array); - } - - /* Register interest in all events except SOF, enable transceiver */ - usbp->usber = 0x03FF; - usbp->usbmr = 0x02F7; - - return; -} - -/* udc_disable - * - * disable the currently hooked device - */ -void udc_disable (void) -{ - int i = 0; - - if (udc_state == STATE_ERROR) { - DBG ("Won't disable UDC. udc_state==STATE_ERROR !\n"); - return; - } - - udc_device = 0; - - for (; i < MAX_ENDPOINTS; i++) { - if (ep_ref[i].urb) { - usbd_dealloc_urb (ep_ref[i].urb); - ep_ref[i].urb = 0; - } - } - - usbp->usbmr = 0x00; - usbp->usmod = ~USMOD_EN; - udc_state = STATE_NOT_READY; -} - -/* udc_startup_events - * - * Enable the specified device - */ -void udc_startup_events (struct usb_device_instance *device) -{ - udc_enable (device); - if (udc_state == STATE_READY) { - usbd_device_event_irq (device, DEVICE_CREATE, 0); - } -} - -/* udc_set_nak - * - * Allow upper layers to signal lower layers should not accept more RX data - * - */ -void udc_set_nak (int epid) -{ - if (epid) { - mpc8xx_udc_set_nak (epid); - } -} - -/* udc_unset_nak - * - * Suspend sending of NAK tokens for DATA OUT tokens on a given endpoint. - * Switch off NAKing on this endpoint to accept more data output from host. - * - */ -void udc_unset_nak (int epid) -{ - if (epid > MAX_ENDPOINTS) { - return; - } - - if (usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK)) { - usbp->usep[epid] &= ~(USEP_THS_NAK | USEP_RHS_NAK); - __asm__ ("eieio"); - } -} - -/****************************************************************************** - Static Linkage -******************************************************************************/ - -/* udc_state_transition_up - * udc_state_transition_down - * - * Helper functions to implement device state changes. The device states and - * the events that transition between them are: - * - * STATE_ATTACHED - * || /\ - * \/ || - * DEVICE_HUB_CONFIGURED DEVICE_HUB_RESET - * || /\ - * \/ || - * STATE_POWERED - * || /\ - * \/ || - * DEVICE_RESET DEVICE_POWER_INTERRUPTION - * || /\ - * \/ || - * STATE_DEFAULT - * || /\ - * \/ || - * DEVICE_ADDRESS_ASSIGNED DEVICE_RESET - * || /\ - * \/ || - * STATE_ADDRESSED - * || /\ - * \/ || - * DEVICE_CONFIGURED DEVICE_DE_CONFIGURED - * || /\ - * \/ || - * STATE_CONFIGURED - * - * udc_state_transition_up transitions up (in the direction from STATE_ATTACHED - * to STATE_CONFIGURED) from the specified initial state to the specified final - * state, passing through each intermediate state on the way. If the initial - * state is at or above (i.e. nearer to STATE_CONFIGURED) the final state, then - * no state transitions will take place. - * - * udc_state_transition_down transitions down (in the direction from - * STATE_CONFIGURED to STATE_ATTACHED) from the specified initial state to the - * specified final state, passing through each intermediate state on the way. - * If the initial state is at or below (i.e. nearer to STATE_ATTACHED) the final - * state, then no state transitions will take place. - * - */ - -static void mpc8xx_udc_state_transition_up (usb_device_state_t initial, - usb_device_state_t final) -{ - if (initial < final) { - switch (initial) { - case STATE_ATTACHED: - usbd_device_event_irq (udc_device, - DEVICE_HUB_CONFIGURED, 0); - if (final == STATE_POWERED) - break; - case STATE_POWERED: - usbd_device_event_irq (udc_device, DEVICE_RESET, 0); - if (final == STATE_DEFAULT) - break; - case STATE_DEFAULT: - usbd_device_event_irq (udc_device, - DEVICE_ADDRESS_ASSIGNED, 0); - if (final == STATE_ADDRESSED) - break; - case STATE_ADDRESSED: - usbd_device_event_irq (udc_device, DEVICE_CONFIGURED, - 0); - case STATE_CONFIGURED: - break; - default: - break; - } - } -} - -static void mpc8xx_udc_state_transition_down (usb_device_state_t initial, - usb_device_state_t final) -{ - if (initial > final) { - switch (initial) { - case STATE_CONFIGURED: - usbd_device_event_irq (udc_device, - DEVICE_DE_CONFIGURED, 0); - if (final == STATE_ADDRESSED) - break; - case STATE_ADDRESSED: - usbd_device_event_irq (udc_device, DEVICE_RESET, 0); - if (final == STATE_DEFAULT) - break; - case STATE_DEFAULT: - usbd_device_event_irq (udc_device, - DEVICE_POWER_INTERRUPTION, 0); - if (final == STATE_POWERED) - break; - case STATE_POWERED: - usbd_device_event_irq (udc_device, DEVICE_HUB_RESET, - 0); - case STATE_ATTACHED: - break; - default: - break; - } - } -} - -/* mpc8xx_udc_stall - * - * Force returning of STALL tokens on the given endpoint. Protocol or function - * STALL conditions are permissable here - */ -static void mpc8xx_udc_stall (unsigned int ep) -{ - usbp->usep[ep] |= STALL_BITMASK; -} - -/* mpc8xx_udc_set_nak - * - * Force returning of NAK responses for the given endpoint as a kind of very - * simple flow control - */ -static void mpc8xx_udc_set_nak (unsigned int ep) -{ - usbp->usep[ep] |= NAK_BITMASK; - __asm__ ("eieio"); -} - -/* mpc8xx_udc_handle_txerr - * - * Handle errors relevant to TX. Return a status code to allow calling - * indicative of what if anything happened - */ -static short mpc8xx_udc_handle_txerr () -{ - short ep = 0, ret = 0; - - for (; ep < TX_RING_SIZE; ep++) { - if (usbp->usber & (0x10 << ep)) { - - /* Timeout or underrun */ - if (tx_cbd[ep]->cbd_sc & 0x06) { - ret = 1; - mpc8xx_udc_flush_tx_fifo (ep); - - } else { - if (usbp->usep[ep] & STALL_BITMASK) { - if (!ep) { - usbp->usep[ep] &= ~STALL_BITMASK; - } - } /* else NAK */ - } - usbp->usber |= (0x10 << ep); - } - } - return ret; -} - -/* mpc8xx_udc_advance_rx - * - * Advance cbd rx - */ -static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid) -{ - if ((*rx_cbdp)->cbd_sc & RX_BD_W) { - *rx_cbdp = (volatile cbd_t *) (endpoints[epid]->rbase + CONFIG_SYS_IMMR); - - } else { - (*rx_cbdp)++; - } -} - - -/* mpc8xx_udc_flush_tx_fifo - * - * Flush a given TX fifo. Assumes one tx cbd per endpoint - */ -static void mpc8xx_udc_flush_tx_fifo (int epid) -{ - volatile cbd_t *tx_cbdp = 0; - - if (epid > MAX_ENDPOINTS) { - return; - } - - /* TX stop */ - immr->im_cpm.cp_cpcr = ((epid << 2) | 0x1D01); - __asm__ ("eieio"); - while (immr->im_cpm.cp_cpcr & 0x01); - - usbp->uscom = 0x40 | 0; - - /* reset ring */ - tx_cbdp = (cbd_t *) (endpoints[epid]->tbptr + CONFIG_SYS_IMMR); - tx_cbdp->cbd_sc = (TX_BD_I | TX_BD_W); - - - endpoints[epid]->tptr = endpoints[epid]->tbase; - endpoints[epid]->tstate = 0x00; - endpoints[epid]->tbcnt = 0x00; - - /* TX start */ - immr->im_cpm.cp_cpcr = ((epid << 2) | 0x2D01); - __asm__ ("eieio"); - while (immr->im_cpm.cp_cpcr & 0x01); - - return; -} - -/* mpc8xx_udc_flush_rx_fifo - * - * For the sake of completeness of the namespace, it seems like - * a good-design-decision (tm) to include mpc8xx_udc_flush_rx_fifo(); - * If RX_BD_E is true => a driver bug either here or in an upper layer - * not polling frequently enough. If RX_BD_E is true we have told the host - * we have accepted data but, the CPM found it had no-where to put that data - * which needless to say would be a bad thing. - */ -static void mpc8xx_udc_flush_rx_fifo () -{ - int i = 0; - - for (i = 0; i < RX_RING_SIZE; i++) { - if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) { - ERR ("buf %p used rx data len = 0x%x sc=0x%x!\n", - rx_cbd[i], rx_cbd[i]->cbd_datlen, - rx_cbd[i]->cbd_sc); - - } - } - ERR ("BUG : Input over-run\n"); -} - -/* mpc8xx_udc_clear_rxbd - * - * Release control of RX CBD to CP. - */ -static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp) -{ - rx_cbdp->cbd_datlen = 0x0000; - rx_cbdp->cbd_sc = ((rx_cbdp->cbd_sc & RX_BD_W) | (RX_BD_E | RX_BD_I)); - __asm__ ("eieio"); -} - -/* mpc8xx_udc_tx_irq - * - * Parse for tx timeout, control RX or USB reset/busy conditions - * Return -1 on timeout, -2 on fatal error, else return zero - */ -static int mpc8xx_udc_tx_irq (int ep) -{ - int i = 0; - - if (usbp->usber & (USB_TX_ERRMASK)) { - if (mpc8xx_udc_handle_txerr ()) { - /* Timeout, controlling function must retry send */ - return -1; - } - } - - if (usbp->usber & (USB_E_RESET | USB_E_BSY)) { - /* Fatal, abandon TX transaction */ - return -2; - } - - if (usbp->usber & USB_E_RXB) { - for (i = 0; i < RX_RING_SIZE; i++) { - if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) { - if ((rx_cbd[i] == ep_ref[0].prx) || ep) { - return -2; - } - } - } - } - - return 0; -} - -/* mpc8xx_udc_ep_tx - * - * Transmit in a re-entrant fashion outbound USB packets. - * Implement retry/timeout mechanism described in USB specification - * Toggle DATA0/DATA1 pids as necessary - * Introduces non-standard tx_retry. The USB standard has no scope for slave - * devices to give up TX, however tx_retry stops us getting stuck in an endless - * TX loop. - */ -static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi) -{ - struct urb *urb = epi->tx_urb; - volatile cbd_t *tx_cbdp = 0; - unsigned int ep = 0, pkt_len = 0, x = 0, tx_retry = 0; - int ret = 0; - - if (!epi || (epi->endpoint_address & 0x03) >= MAX_ENDPOINTS || !urb) { - return -1; - } - - ep = epi->endpoint_address & 0x03; - tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CONFIG_SYS_IMMR); - - if (tx_cbdp->cbd_sc & TX_BD_R || usbp->usber & USB_E_TXB) { - mpc8xx_udc_flush_tx_fifo (ep); - usbp->usber |= USB_E_TXB; - }; - - while (tx_retry++ < 100) { - ret = mpc8xx_udc_tx_irq (ep); - if (ret == -1) { - /* ignore timeout here */ - } else if (ret == -2) { - /* Abandon TX */ - mpc8xx_udc_flush_tx_fifo (ep); - return -1; - } - - tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CONFIG_SYS_IMMR); - while (tx_cbdp->cbd_sc & TX_BD_R) { - }; - tx_cbdp->cbd_sc = (tx_cbdp->cbd_sc & TX_BD_W); - - pkt_len = urb->actual_length - epi->sent; - - if (pkt_len > epi->tx_packetSize || pkt_len > EP_MAX_PKT) { - pkt_len = MIN (epi->tx_packetSize, EP_MAX_PKT); - } - - for (x = 0; x < pkt_len; x++) { - *((unsigned char *) (tx_cbdp->cbd_bufaddr + x)) = - urb->buffer[epi->sent + x]; - } - tx_cbdp->cbd_datlen = pkt_len; - tx_cbdp->cbd_sc |= (CBD_TX_BITMASK | ep_ref[ep].pid); - __asm__ ("eieio"); - -#ifdef __SIMULATE_ERROR__ - if (++err_poison_test == 2) { - err_poison_test = 0; - tx_cbdp->cbd_sc &= ~TX_BD_TC; - } -#endif - - usbp->uscom = (USCOM_STR | ep); - - while (!(usbp->usber & USB_E_TXB)) { - ret = mpc8xx_udc_tx_irq (ep); - if (ret == -1) { - /* TX timeout */ - break; - } else if (ret == -2) { - if (usbp->usber & USB_E_TXB) { - usbp->usber |= USB_E_TXB; - } - mpc8xx_udc_flush_tx_fifo (ep); - return -1; - } - }; - - if (usbp->usber & USB_E_TXB) { - usbp->usber |= USB_E_TXB; - } - - /* ACK must be present <= 18bit times from TX */ - if (ret == -1) { - continue; - } - - /* TX ACK : USB 2.0 8.7.2, Toggle PID, Advance TX */ - epi->sent += pkt_len; - epi->last = MIN (urb->actual_length - epi->sent, epi->tx_packetSize); - TOGGLE_TX_PID (ep_ref[ep].pid); - - if (epi->sent >= epi->tx_urb->actual_length) { - - epi->tx_urb->actual_length = 0; - epi->sent = 0; - - if (ep_ref[ep].sc & EP_SEND_ZLP) { - ep_ref[ep].sc &= ~EP_SEND_ZLP; - } else { - return 0; - } - } - } - - ERR ("TX fail, endpoint 0x%x tx bytes 0x%x/0x%x\n", ep, epi->sent, - epi->tx_urb->actual_length); - - return -1; -} - -/* mpc8xx_udc_dump_request - * - * Dump a control request to console - */ -static void mpc8xx_udc_dump_request (struct usb_device_request *request) -{ - DBG ("bmRequestType:%02x bRequest:%02x wValue:%04x " - "wIndex:%04x wLength:%04x ?\n", - request->bmRequestType, - request->bRequest, - request->wValue, request->wIndex, request->wLength); - - return; -} - -/* mpc8xx_udc_ep0_rx_setup - * - * Decode received ep0 SETUP packet. return non-zero on error - */ -static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp) -{ - unsigned int x = 0; - struct urb *purb = ep_ref[0].urb; - struct usb_endpoint_instance *epi = - &udc_device->bus->endpoint_array[0]; - - for (; x < rx_cbdp->cbd_datlen; x++) { - *(((unsigned char *) &ep_ref[0].urb->device_request) + x) = - *((unsigned char *) (rx_cbdp->cbd_bufaddr + x)); - } - - mpc8xx_udc_clear_rxbd (rx_cbdp); - - if (ep0_recv_setup (purb)) { - mpc8xx_udc_dump_request (&purb->device_request); - return -1; - } - - if ((purb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK) - == USB_REQ_HOST2DEVICE) { - - switch (purb->device_request.bRequest) { - case USB_REQ_SET_ADDRESS: - /* Send the Status OUT ZLP */ - ep_ref[0].pid = TX_BD_PID_DATA1; - purb->actual_length = 0; - mpc8xx_udc_init_tx (epi, purb); - mpc8xx_udc_ep_tx (epi); - - /* Move to the addressed state */ - usbp->usaddr = udc_device->address; - mpc8xx_udc_state_transition_up (udc_device->device_state, - STATE_ADDRESSED); - return 0; - - case USB_REQ_SET_CONFIGURATION: - if (!purb->device_request.wValue) { - /* Respond at default address */ - usbp->usaddr = 0x00; - mpc8xx_udc_state_transition_down (udc_device->device_state, - STATE_ADDRESSED); - } else { - /* TODO: Support multiple configurations */ - mpc8xx_udc_state_transition_up (udc_device->device_state, - STATE_CONFIGURED); - for (x = 1; x < MAX_ENDPOINTS; x++) { - if ((udc_device->bus->endpoint_array[x].endpoint_address & USB_ENDPOINT_DIR_MASK) - == USB_DIR_IN) { - ep_ref[x].pid = TX_BD_PID_DATA0; - } else { - ep_ref[x].pid = RX_BD_PID_DATA0; - } - /* Set configuration must unstall endpoints */ - usbp->usep[x] &= ~STALL_BITMASK; - } - } - break; - default: - /* CDC/Vendor specific */ - break; - } - - /* Send ZLP as ACK in Status OUT phase */ - ep_ref[0].pid = TX_BD_PID_DATA1; - purb->actual_length = 0; - mpc8xx_udc_init_tx (epi, purb); - mpc8xx_udc_ep_tx (epi); - - } else { - - if (purb->actual_length) { - ep_ref[0].pid = TX_BD_PID_DATA1; - mpc8xx_udc_init_tx (epi, purb); - - if (!(purb->actual_length % EP0_MAX_PACKET_SIZE)) { - ep_ref[0].sc |= EP_SEND_ZLP; - } - - if (purb->device_request.wValue == - USB_DESCRIPTOR_TYPE_DEVICE) { - if (le16_to_cpu (purb->device_request.wLength) - > purb->actual_length) { - /* Send EP0_MAX_PACKET_SIZE bytes - * unless correct size requested. - */ - if (purb->actual_length > epi->tx_packetSize) { - purb->actual_length = epi->tx_packetSize; - } - } - } - mpc8xx_udc_ep_tx (epi); - - } else { - /* Corrupt SETUP packet? */ - ERR ("Zero length data or SETUP with DATA-IN phase ?\n"); - return 1; - } - } - return 0; -} - -/* mpc8xx_udc_init_tx - * - * Setup some basic parameters for a TX transaction - */ -static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi, - struct urb *tx_urb) -{ - epi->sent = 0; - epi->last = 0; - epi->tx_urb = tx_urb; -} - -/* mpc8xx_udc_ep0_rx - * - * Receive ep0/control USB data. Parse and possibly send a response. - */ -static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp) -{ - if (rx_cbdp->cbd_sc & RX_BD_PID_SETUP) { - - /* Unconditionally accept SETUP packets */ - if (mpc8xx_udc_ep0_rx_setup (rx_cbdp)) { - mpc8xx_udc_stall (0); - } - - } else { - - mpc8xx_udc_clear_rxbd (rx_cbdp); - - if ((rx_cbdp->cbd_datlen - 2)) { - /* SETUP with a DATA phase - * outside of SETUP packet. - * Reply with STALL. - */ - mpc8xx_udc_stall (0); - } - } -} - -/* mpc8xx_udc_epn_rx - * - * Receive some data from cbd into USB system urb data abstraction - * Upper layers should NAK if there is insufficient RX data space - */ -static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp) -{ - struct usb_endpoint_instance *epi = 0; - struct urb *urb = 0; - unsigned int x = 0; - - if (epid >= MAX_ENDPOINTS || !rx_cbdp->cbd_datlen) { - return 0; - } - - /* USB 2.0 PDF section 8.6.4 - * Discard data with invalid PID it is a resend. - */ - if (ep_ref[epid].pid != (rx_cbdp->cbd_sc & 0xC0)) { - return 1; - } - TOGGLE_RX_PID (ep_ref[epid].pid); - - epi = &udc_device->bus->endpoint_array[epid]; - urb = epi->rcv_urb; - - for (; x < (rx_cbdp->cbd_datlen - 2); x++) { - *((unsigned char *) (urb->buffer + urb->actual_length + x)) = - *((unsigned char *) (rx_cbdp->cbd_bufaddr + x)); - } - - if (x) { - usbd_rcv_complete (epi, x, 0); - if (ep_ref[epid].urb->status == RECV_ERROR) { - DBG ("RX error unset NAK\n"); - udc_unset_nak (epid); - } - } - return x; -} - -/* mpc8xx_udc_clock_init - * - * Obtain a clock reference for Full Speed Signaling - */ -static void mpc8xx_udc_clock_init (volatile immap_t * immr, - volatile cpm8xx_t * cp) -{ - -#if defined(CONFIG_SYS_USB_EXTC_CLK) - - /* This has been tested with a 48MHz crystal on CLK6 */ - switch (CONFIG_SYS_USB_EXTC_CLK) { - case 1: - immr->im_ioport.iop_papar |= 0x0100; - immr->im_ioport.iop_padir &= ~0x0100; - cp->cp_sicr |= 0x24; - break; - case 2: - immr->im_ioport.iop_papar |= 0x0200; - immr->im_ioport.iop_padir &= ~0x0200; - cp->cp_sicr |= 0x2D; - break; - case 3: - immr->im_ioport.iop_papar |= 0x0400; - immr->im_ioport.iop_padir &= ~0x0400; - cp->cp_sicr |= 0x36; - break; - case 4: - immr->im_ioport.iop_papar |= 0x0800; - immr->im_ioport.iop_padir &= ~0x0800; - cp->cp_sicr |= 0x3F; - break; - default: - udc_state = STATE_ERROR; - break; - } - -#elif defined(CONFIG_SYS_USB_BRGCLK) - - /* This has been tested with brgclk == 50MHz */ - int divisor = 0; - - if (gd->cpu_clk < 48000000L) { - ERR ("brgclk is too slow for full-speed USB!\n"); - udc_state = STATE_ERROR; - return; - } - - /* Assume the brgclk is 'good enough', we want !(gd->cpu_clk%48MHz) - * but, can /probably/ live with close-ish alternative rates. - */ - divisor = (gd->cpu_clk / 48000000L) - 1; - cp->cp_sicr &= ~0x0000003F; - - switch (CONFIG_SYS_USB_BRGCLK) { - case 1: - cp->cp_brgc1 |= (divisor | CPM_BRG_EN); - cp->cp_sicr &= ~0x2F; - break; - case 2: - cp->cp_brgc2 |= (divisor | CPM_BRG_EN); - cp->cp_sicr |= 0x00000009; - break; - case 3: - cp->cp_brgc3 |= (divisor | CPM_BRG_EN); - cp->cp_sicr |= 0x00000012; - break; - case 4: - cp->cp_brgc4 = (divisor | CPM_BRG_EN); - cp->cp_sicr |= 0x0000001B; - break; - default: - udc_state = STATE_ERROR; - break; - } - -#else -#error "CONFIG_SYS_USB_EXTC_CLK or CONFIG_SYS_USB_BRGCLK must be defined" -#endif - -} - -/* mpc8xx_udc_cbd_attach - * - * attach a cbd to and endpoint - */ -static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size) -{ - - if (!tx_cbd[ep] || !rx_cbd[ep] || ep >= MAX_ENDPOINTS) { - udc_state = STATE_ERROR; - return; - } - - if (tx_size > USB_MAX_PKT || rx_size > USB_MAX_PKT || - (!tx_size && !rx_size)) { - udc_state = STATE_ERROR; - return; - } - - /* Attach CBD to appropiate Parameter RAM Endpoint data structure */ - if (rx_size) { - endpoints[ep]->rbase = (u32) rx_cbd[rx_ct]; - endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct]; - rx_ct++; - - if (!ep) { - - endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct]; - rx_cbd[rx_ct]->cbd_sc |= RX_BD_W; - rx_ct++; - - } else { - rx_ct += 2; - endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct]; - rx_cbd[rx_ct]->cbd_sc |= RX_BD_W; - rx_ct++; - } - - /* Where we expect to RX data on this endpoint */ - ep_ref[ep].prx = rx_cbd[rx_ct - 1]; - } else { - - ep_ref[ep].prx = 0; - endpoints[ep]->rbase = 0; - endpoints[ep]->rbptr = 0; - } - - if (tx_size) { - endpoints[ep]->tbase = (u32) tx_cbd[tx_ct]; - endpoints[ep]->tbptr = (u32) tx_cbd[tx_ct]; - tx_ct++; - } else { - endpoints[ep]->tbase = 0; - endpoints[ep]->tbptr = 0; - } - - endpoints[ep]->tstate = 0; - endpoints[ep]->tbcnt = 0; - endpoints[ep]->mrblr = EP_MAX_PKT; - endpoints[ep]->rfcr = 0x18; - endpoints[ep]->tfcr = 0x18; - ep_ref[ep].sc |= EP_ATTACHED; - - DBG ("ep %d rbase 0x%08x rbptr 0x%08x tbase 0x%08x tbptr 0x%08x prx = %p\n", - ep, endpoints[ep]->rbase, endpoints[ep]->rbptr, - endpoints[ep]->tbase, endpoints[ep]->tbptr, - ep_ref[ep].prx); - - return; -} - -/* mpc8xx_udc_cbd_init - * - * Allocate space for a cbd and allocate TX/RX data space - */ -static void mpc8xx_udc_cbd_init (void) -{ - int i = 0; - - for (; i < TX_RING_SIZE; i++) { - tx_cbd[i] = (cbd_t *) - mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int)); - } - - for (i = 0; i < RX_RING_SIZE; i++) { - rx_cbd[i] = (cbd_t *) - mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int)); - } - - for (i = 0; i < TX_RING_SIZE; i++) { - tx_cbd[i]->cbd_bufaddr = - mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int)); - - tx_cbd[i]->cbd_sc = (TX_BD_I | TX_BD_W); - tx_cbd[i]->cbd_datlen = 0x0000; - } - - - for (i = 0; i < RX_RING_SIZE; i++) { - rx_cbd[i]->cbd_bufaddr = - mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int)); - rx_cbd[i]->cbd_sc = (RX_BD_I | RX_BD_E); - rx_cbd[i]->cbd_datlen = 0x0000; - - } - - return; -} - -/* mpc8xx_udc_endpoint_init - * - * Attach an endpoint to some dpram - */ -static void mpc8xx_udc_endpoint_init (void) -{ - int i = 0; - - for (; i < MAX_ENDPOINTS; i++) { - endpoints[i] = (usb_epb_t *) - mpc8xx_udc_alloc (sizeof (usb_epb_t), 32); - } -} - -/* mpc8xx_udc_alloc - * - * Grab the address of some dpram - */ -static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment) -{ - u32 retaddr = address_base; - - while (retaddr % alignment) { - retaddr++; - } - address_base += data_size; - - return retaddr; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/ndis.h b/qemu/roms/u-boot/drivers/usb/gadget/ndis.h deleted file mode 100644 index 753838f79..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/ndis.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * ndis.h - * - * ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de> - * - * Thanks to the cygwin development team, - * espacially to Casper S. Hornstrup <chorns@users.sourceforge.net> - * - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#ifndef _USBGADGET_NDIS_H -#define _USBGADGET_NDIS_H - - -#define NDIS_STATUS_MULTICAST_FULL 0xC0010009 -#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A -#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B - -enum NDIS_DEVICE_POWER_STATE { - NdisDeviceStateUnspecified = 0, - NdisDeviceStateD0, - NdisDeviceStateD1, - NdisDeviceStateD2, - NdisDeviceStateD3, - NdisDeviceStateMaximum -}; - -struct NDIS_PM_WAKE_UP_CAPABILITIES { - enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp; - enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp; - enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp; -}; - -/* NDIS_PNP_CAPABILITIES.Flags constants */ -#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001 -#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 -#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 - -struct NDIS_PNP_CAPABILITIES { - __le32 Flags; - struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; -}; - -struct NDIS_PM_PACKET_PATTERN { - __le32 Priority; - __le32 Reserved; - __le32 MaskSize; - __le32 PatternOffset; - __le32 PatternSize; - __le32 PatternFlags; -}; - - -/* Required Object IDs (OIDs) */ -#define OID_GEN_SUPPORTED_LIST 0x00010101 -#define OID_GEN_HARDWARE_STATUS 0x00010102 -#define OID_GEN_MEDIA_SUPPORTED 0x00010103 -#define OID_GEN_MEDIA_IN_USE 0x00010104 -#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 -#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 -#define OID_GEN_LINK_SPEED 0x00010107 -#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 -#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 -#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A -#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B -#define OID_GEN_VENDOR_ID 0x0001010C -#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D -#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E -#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F -#define OID_GEN_DRIVER_VERSION 0x00010110 -#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 -#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 -#define OID_GEN_MAC_OPTIONS 0x00010113 -#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 -#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 -#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 -#define OID_GEN_SUPPORTED_GUIDS 0x00010117 -#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 -#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 -#define OID_GEN_MACHINE_NAME 0x0001021A -#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B -#define OID_GEN_VLAN_ID 0x0001021C - -/* Optional OIDs */ -#define OID_GEN_MEDIA_CAPABILITIES 0x00010201 -#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 - -/* Required statistics OIDs */ -#define OID_GEN_XMIT_OK 0x00020101 -#define OID_GEN_RCV_OK 0x00020102 -#define OID_GEN_XMIT_ERROR 0x00020103 -#define OID_GEN_RCV_ERROR 0x00020104 -#define OID_GEN_RCV_NO_BUFFER 0x00020105 - -/* Optional statistics OIDs */ -#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 -#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 -#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 -#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 -#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 -#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 -#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 -#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 -#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 -#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A -#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B -#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C -#define OID_GEN_RCV_CRC_ERROR 0x0002020D -#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E -#define OID_GEN_GET_TIME_CAPS 0x0002020F -#define OID_GEN_GET_NETCARD_TIME 0x00020210 -#define OID_GEN_NETCARD_LOAD 0x00020211 -#define OID_GEN_DEVICE_PROFILE 0x00020212 -#define OID_GEN_INIT_TIME_MS 0x00020213 -#define OID_GEN_RESET_COUNTS 0x00020214 -#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215 -#define OID_GEN_FRIENDLY_NAME 0x00020216 -#define OID_GEN_MINIPORT_INFO 0x00020217 -#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218 - -/* IEEE 802.3 (Ethernet) OIDs */ -#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 - -#define OID_802_3_PERMANENT_ADDRESS 0x01010101 -#define OID_802_3_CURRENT_ADDRESS 0x01010102 -#define OID_802_3_MULTICAST_LIST 0x01010103 -#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 -#define OID_802_3_MAC_OPTIONS 0x01010105 -#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 -#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 -#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 -#define OID_802_3_XMIT_DEFERRED 0x01020201 -#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 -#define OID_802_3_RCV_OVERRUN 0x01020203 -#define OID_802_3_XMIT_UNDERRUN 0x01020204 -#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 -#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 -#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 - -/* OID_GEN_MINIPORT_INFO constants */ -#define NDIS_MINIPORT_BUS_MASTER 0x00000001 -#define NDIS_MINIPORT_WDM_DRIVER 0x00000002 -#define NDIS_MINIPORT_SG_LIST 0x00000004 -#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008 -#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010 -#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020 -#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040 -#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080 -#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100 -#define NDIS_MINIPORT_IS_NDIS_5 0x00000200 -#define NDIS_MINIPORT_IS_CO 0x00000400 -#define NDIS_MINIPORT_DESERIALIZE 0x00000800 -#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000 -#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000 -#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000 -#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000 -#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000 -#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000 -#define NDIS_MINIPORT_HIDDEN 0x00040000 -#define NDIS_MINIPORT_SWENUM 0x00080000 -#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000 -#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000 -#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000 -#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000 -#define NDIS_MINIPORT_64BITS_DMA 0x01000000 - -#define NDIS_MEDIUM_802_3 0x00000000 -#define NDIS_MEDIUM_802_5 0x00000001 -#define NDIS_MEDIUM_FDDI 0x00000002 -#define NDIS_MEDIUM_WAN 0x00000003 -#define NDIS_MEDIUM_LOCAL_TALK 0x00000004 -#define NDIS_MEDIUM_DIX 0x00000005 -#define NDIS_MEDIUM_ARCENT_RAW 0x00000006 -#define NDIS_MEDIUM_ARCENT_878_2 0x00000007 -#define NDIS_MEDIUM_ATM 0x00000008 -#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009 -#define NDIS_MEDIUM_IRDA 0x0000000A -#define NDIS_MEDIUM_BPC 0x0000000B -#define NDIS_MEDIUM_CO_WAN 0x0000000C -#define NDIS_MEDIUM_1394 0x0000000D - -#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 -#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 -#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 -#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 -#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 -#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 -#define NDIS_PACKET_TYPE_SMT 0x00000040 -#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 -#define NDIS_PACKET_TYPE_GROUP 0x00000100 -#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200 -#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 -#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 - -#define NDIS_MEDIA_STATE_CONNECTED 0x00000000 -#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001 - -#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 -#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 -#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 -#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 -#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 -#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 -#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 -#define NDIS_MAC_OPTION_RESERVED 0x80000000 - -#endif /* _USBGADGET_NDIS_H */ diff --git a/qemu/roms/u-boot/drivers/usb/gadget/omap1510_udc.c b/qemu/roms/u-boot/drivers/usb/gadget/omap1510_udc.c deleted file mode 100644 index bdc1b886f..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/omap1510_udc.c +++ /dev/null @@ -1,1555 +0,0 @@ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * Based on - * linux/drivers/usb/device/bi/omap.c - * TI OMAP1510 USB bus interface driver - * - * Author: MontaVista Software, Inc. - * source@mvista.com - * (C) Copyright 2002 - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#ifdef CONFIG_OMAP_SX1 -#include <i2c.h> -#endif -#include <usbdevice.h> -#include <usb/omap1510_udc.h> -#include <usb/udc.h> - -#include "ep0.h" - - -#define UDC_INIT_MDELAY 80 /* Device settle delay */ -#define UDC_MAX_ENDPOINTS 31 /* Number of endpoints on this UDC */ - -/* Some kind of debugging output... */ -#if 1 -#define UDCDBG(str) -#define UDCDBGA(fmt,args...) -#else /* The bugs still exists... */ -#define UDCDBG(str) serial_printf("[%s] %s:%d: " str "\n", __FILE__,__FUNCTION__,__LINE__) -#define UDCDBGA(fmt,args...) serial_printf("[%s] %s:%d: " fmt "\n", __FILE__,__FUNCTION__,__LINE__, ##args) -#endif - -#if 1 -#define UDCREG(name) -#define UDCREGL(name) -#else /* The bugs still exists... */ -#define UDCREG(name) serial_printf("%s():%d: %s[%08x]=%.4x\n",__FUNCTION__,__LINE__, (#name), name, inw(name)) /* For 16-bit regs */ -#define UDCREGL(name) serial_printf("%s():%d: %s[%08x]=%.8x\n",__FUNCTION__,__LINE__, (#name), name, inl(name)) /* For 32-bit regs */ -#endif - - -static struct urb *ep0_urb = NULL; - -static struct usb_device_instance *udc_device; /* Used in interrupt handler */ -static u16 udc_devstat = 0; /* UDC status (DEVSTAT) */ -static u32 udc_interrupts = 0; - -static void udc_stall_ep (unsigned int ep_addr); - - -static struct usb_endpoint_instance *omap1510_find_ep (int ep) -{ - int i; - - for (i = 0; i < udc_device->bus->max_endpoints; i++) { - if (udc_device->bus->endpoint_array[i].endpoint_address == ep) - return &udc_device->bus->endpoint_array[i]; - } - return NULL; -} - -/* ************************************************************************** */ -/* IO - */ - -/* - * omap1510_prepare_endpoint_for_rx - * - * This function implements TRM Figure 14-11. - * - * The endpoint to prepare for transfer is specified as a physical endpoint - * number. For OUT (rx) endpoints 1 through 15, the corresponding endpoint - * configuration register is checked to see if the endpoint is ISO or not. - * If the OUT endpoint is valid and is non-ISO then its FIFO is enabled. - * No action is taken for endpoint 0 or for IN (tx) endpoints 16 through 30. - */ -static void omap1510_prepare_endpoint_for_rx (int ep_addr) -{ - int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; - - UDCDBGA ("omap1510_prepare_endpoint %x", ep_addr); - if (((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)) { - if ((inw (UDC_EP_RX (ep_num)) & - (UDC_EPn_RX_Valid | UDC_EPn_RX_Iso)) == - UDC_EPn_RX_Valid) { - /* rx endpoint is valid, non-ISO, so enable its FIFO */ - outw (UDC_EP_Sel | ep_num, UDC_EP_NUM); - outw (UDC_Set_FIFO_En, UDC_CTRL); - outw (0, UDC_EP_NUM); - } - } -} - -/* omap1510_configure_endpoints - * - * This function implements TRM Figure 14-10. - */ -static void omap1510_configure_endpoints (struct usb_device_instance *device) -{ - int ep; - struct usb_bus_instance *bus; - struct usb_endpoint_instance *endpoint; - unsigned short ep_ptr; - unsigned short ep_size; - unsigned short ep_isoc; - unsigned short ep_doublebuffer; - int ep_addr; - int packet_size; - int buffer_size; - int attributes; - - bus = device->bus; - - /* There is a dedicated 2048 byte buffer for USB packets that may be - * arbitrarily partitioned among the endpoints on 8-byte boundaries. - * The first 8 bytes are reserved for receiving setup packets on - * endpoint 0. - */ - ep_ptr = 8; /* reserve the first 8 bytes for the setup fifo */ - - for (ep = 0; ep < bus->max_endpoints; ep++) { - endpoint = bus->endpoint_array + ep; - ep_addr = endpoint->endpoint_address; - if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { - /* IN endpoint */ - packet_size = endpoint->tx_packetSize; - attributes = endpoint->tx_attributes; - } else { - /* OUT endpoint */ - packet_size = endpoint->rcv_packetSize; - attributes = endpoint->rcv_attributes; - } - - switch (packet_size) { - case 0: - ep_size = 0; - break; - case 8: - ep_size = 0; - break; - case 16: - ep_size = 1; - break; - case 32: - ep_size = 2; - break; - case 64: - ep_size = 3; - break; - case 128: - ep_size = 4; - break; - case 256: - ep_size = 5; - break; - case 512: - ep_size = 6; - break; - default: - UDCDBGA ("ep 0x%02x has bad packet size %d", - ep_addr, packet_size); - packet_size = 0; - ep_size = 0; - break; - } - - switch (attributes & USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_CONTROL: - case USB_ENDPOINT_XFER_BULK: - case USB_ENDPOINT_XFER_INT: - default: - /* A non-isochronous endpoint may optionally be - * double-buffered. For now we disable - * double-buffering. - */ - ep_doublebuffer = 0; - ep_isoc = 0; - if (packet_size > 64) - packet_size = 0; - if (!ep || !ep_doublebuffer) - buffer_size = packet_size; - else - buffer_size = packet_size * 2; - break; - case USB_ENDPOINT_XFER_ISOC: - /* Isochronous endpoints are always double- - * buffered, but the double-buffering bit - * in the endpoint configuration register - * becomes the msb of the endpoint size so we - * set the double-buffering flag to zero. - */ - ep_doublebuffer = 0; - ep_isoc = 1; - buffer_size = packet_size * 2; - break; - } - - /* check to see if our packet buffer RAM is exhausted */ - if ((ep_ptr + buffer_size) > 2048) { - UDCDBGA ("out of packet RAM for ep 0x%02x buf size %d", ep_addr, buffer_size); - buffer_size = packet_size = 0; - } - - /* force a default configuration for endpoint 0 since it is - * always enabled - */ - if (!ep && ((packet_size < 8) || (packet_size > 64))) { - buffer_size = packet_size = 64; - ep_size = 3; - } - - if (!ep) { - /* configure endpoint 0 */ - outw ((ep_size << 12) | (ep_ptr >> 3), UDC_EP0); - /*UDCDBGA("ep 0 buffer offset 0x%03x packet size 0x%03x", */ - /* ep_ptr, packet_size); */ - } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { - /* IN endpoint */ - if (packet_size) { - outw ((1 << 15) | (ep_doublebuffer << 14) | - (ep_size << 12) | (ep_isoc << 11) | - (ep_ptr >> 3), - UDC_EP_TX (ep_addr & - USB_ENDPOINT_NUMBER_MASK)); - UDCDBGA ("IN ep %d buffer offset 0x%03x" - " packet size 0x%03x", - ep_addr & USB_ENDPOINT_NUMBER_MASK, - ep_ptr, packet_size); - } else { - outw (0, - UDC_EP_TX (ep_addr & - USB_ENDPOINT_NUMBER_MASK)); - } - } else { - /* OUT endpoint */ - if (packet_size) { - outw ((1 << 15) | (ep_doublebuffer << 14) | - (ep_size << 12) | (ep_isoc << 11) | - (ep_ptr >> 3), - UDC_EP_RX (ep_addr & - USB_ENDPOINT_NUMBER_MASK)); - UDCDBGA ("OUT ep %d buffer offset 0x%03x" - " packet size 0x%03x", - ep_addr & USB_ENDPOINT_NUMBER_MASK, - ep_ptr, packet_size); - } else { - outw (0, - UDC_EP_RX (ep_addr & - USB_ENDPOINT_NUMBER_MASK)); - } - } - ep_ptr += buffer_size; - } -} - -/* omap1510_deconfigure_device - * - * This function balances omap1510_configure_device. - */ -static void omap1510_deconfigure_device (void) -{ - int epnum; - - UDCDBG ("clear Cfg_Lock"); - outw (inw (UDC_SYSCON1) & ~UDC_Cfg_Lock, UDC_SYSCON1); - UDCREG (UDC_SYSCON1); - - /* deconfigure all endpoints */ - for (epnum = 1; epnum <= 15; epnum++) { - outw (0, UDC_EP_RX (epnum)); - outw (0, UDC_EP_TX (epnum)); - } -} - -/* omap1510_configure_device - * - * This function implements TRM Figure 14-9. - */ -static void omap1510_configure_device (struct usb_device_instance *device) -{ - omap1510_configure_endpoints (device); - - - /* Figure 14-9 indicates we should enable interrupts here, but we have - * other routines (udc_all_interrupts, udc_suspended_interrupts) to - * do that. - */ - - UDCDBG ("set Cfg_Lock"); - outw (inw (UDC_SYSCON1) | UDC_Cfg_Lock, UDC_SYSCON1); - UDCREG (UDC_SYSCON1); -} - -/* omap1510_write_noniso_tx_fifo - * - * This function implements TRM Figure 14-30. - * - * If the endpoint has an active tx_urb, then the next packet of data from the - * URB is written to the tx FIFO. The total amount of data in the urb is given - * by urb->actual_length. The maximum amount of data that can be sent in any - * one packet is given by endpoint->tx_packetSize. The number of data bytes - * from this URB that have already been transmitted is given by endpoint->sent. - * endpoint->last is updated by this routine with the number of data bytes - * transmitted in this packet. - * - * In accordance with Figure 14-30, the EP_NUM register must already have been - * written with the value to select the appropriate tx FIFO before this routine - * is called. - */ -static void omap1510_write_noniso_tx_fifo (struct usb_endpoint_instance - *endpoint) -{ - struct urb *urb = endpoint->tx_urb; - - if (urb) { - unsigned int last, i; - - UDCDBGA ("urb->buffer %p, buffer_length %d, actual_length %d", - urb->buffer, urb->buffer_length, urb->actual_length); - if ((last = - MIN (urb->actual_length - endpoint->sent, - endpoint->tx_packetSize))) { - u8 *cp = urb->buffer + endpoint->sent; - - UDCDBGA ("endpoint->sent %d, tx_packetSize %d, last %d", endpoint->sent, endpoint->tx_packetSize, last); - - if (((u32) cp & 1) == 0) { /* word aligned? */ - outsw (UDC_DATA, cp, last >> 1); - } else { /* byte aligned. */ - for (i = 0; i < (last >> 1); i++) { - u16 w = ((u16) cp[2 * i + 1] << 8) | - (u16) cp[2 * i]; - outw (w, UDC_DATA); - } - } - if (last & 1) { - outb (*(cp + last - 1), UDC_DATA); - } - } - endpoint->last = last; - } -} - -/* omap1510_read_noniso_rx_fifo - * - * This function implements TRM Figure 14-28. - * - * If the endpoint has an active rcv_urb, then the next packet of data is read - * from the rcv FIFO and written to rcv_urb->buffer at offset - * rcv_urb->actual_length to append the packet data to the data from any - * previous packets for this transfer. We assume that there is sufficient room - * left in the buffer to hold an entire packet of data. - * - * The return value is the number of bytes read from the FIFO for this packet. - * - * In accordance with Figure 14-28, the EP_NUM register must already have been - * written with the value to select the appropriate rcv FIFO before this routine - * is called. - */ -static int omap1510_read_noniso_rx_fifo (struct usb_endpoint_instance - *endpoint) -{ - struct urb *urb = endpoint->rcv_urb; - int len = 0; - - if (urb) { - len = inw (UDC_RXFSTAT); - - if (len) { - unsigned char *cp = urb->buffer + urb->actual_length; - - insw (UDC_DATA, cp, len >> 1); - if (len & 1) - *(cp + len - 1) = inb (UDC_DATA); - } - } - return len; -} - -/* omap1510_prepare_for_control_write_status - * - * This function implements TRM Figure 14-17. - * - * We have to deal here with non-autodecoded control writes that haven't already - * been dealt with by ep0_recv_setup. The non-autodecoded standard control - * write requests are: set/clear endpoint feature, set configuration, set - * interface, and set descriptor. ep0_recv_setup handles set/clear requests for - * ENDPOINT_HALT by halting the endpoint for a set request and resetting the - * endpoint for a clear request. ep0_recv_setup returns an error for - * SET_DESCRIPTOR requests which causes them to be terminated with a stall by - * the setup handler. A SET_INTERFACE request is handled by ep0_recv_setup by - * generating a DEVICE_SET_INTERFACE event. This leaves only the - * SET_CONFIGURATION event for us to deal with here. - * - */ -static void omap1510_prepare_for_control_write_status (struct urb *urb) -{ - struct usb_device_request *request = &urb->device_request;; - - /* check for a SET_CONFIGURATION request */ - if (request->bRequest == USB_REQ_SET_CONFIGURATION) { - int configuration = le16_to_cpu (request->wValue) & 0xff; - unsigned short devstat = inw (UDC_DEVSTAT); - - if ((devstat & (UDC_ADD | UDC_CFG)) == UDC_ADD) { - /* device is currently in ADDRESSED state */ - if (configuration) { - /* Assume the specified non-zero configuration - * value is valid and switch to the CONFIGURED - * state. - */ - outw (UDC_Dev_Cfg, UDC_SYSCON2); - } - } else if ((devstat & UDC_CFG) == UDC_CFG) { - /* device is currently in CONFIGURED state */ - if (!configuration) { - /* Switch to ADDRESSED state. */ - outw (UDC_Clr_Cfg, UDC_SYSCON2); - } - } - } - - /* select EP0 tx FIFO */ - outw (UDC_EP_Dir | UDC_EP_Sel, UDC_EP_NUM); - /* clear endpoint (no data bytes in status stage) */ - outw (UDC_Clr_EP, UDC_CTRL); - /* enable the EP0 tx FIFO */ - outw (UDC_Set_FIFO_En, UDC_CTRL); - /* deselect the endpoint */ - outw (UDC_EP_Dir, UDC_EP_NUM); -} - -/* udc_state_transition_up - * udc_state_transition_down - * - * Helper functions to implement device state changes. The device states and - * the events that transition between them are: - * - * STATE_ATTACHED - * || /\ - * \/ || - * DEVICE_HUB_CONFIGURED DEVICE_HUB_RESET - * || /\ - * \/ || - * STATE_POWERED - * || /\ - * \/ || - * DEVICE_RESET DEVICE_POWER_INTERRUPTION - * || /\ - * \/ || - * STATE_DEFAULT - * || /\ - * \/ || - * DEVICE_ADDRESS_ASSIGNED DEVICE_RESET - * || /\ - * \/ || - * STATE_ADDRESSED - * || /\ - * \/ || - * DEVICE_CONFIGURED DEVICE_DE_CONFIGURED - * || /\ - * \/ || - * STATE_CONFIGURED - * - * udc_state_transition_up transitions up (in the direction from STATE_ATTACHED - * to STATE_CONFIGURED) from the specified initial state to the specified final - * state, passing through each intermediate state on the way. If the initial - * state is at or above (i.e. nearer to STATE_CONFIGURED) the final state, then - * no state transitions will take place. - * - * udc_state_transition_down transitions down (in the direction from - * STATE_CONFIGURED to STATE_ATTACHED) from the specified initial state to the - * specified final state, passing through each intermediate state on the way. - * If the initial state is at or below (i.e. nearer to STATE_ATTACHED) the final - * state, then no state transitions will take place. - * - * These functions must only be called with interrupts disabled. - */ -static void udc_state_transition_up (usb_device_state_t initial, - usb_device_state_t final) -{ - if (initial < final) { - switch (initial) { - case STATE_ATTACHED: - usbd_device_event_irq (udc_device, - DEVICE_HUB_CONFIGURED, 0); - if (final == STATE_POWERED) - break; - case STATE_POWERED: - usbd_device_event_irq (udc_device, DEVICE_RESET, 0); - if (final == STATE_DEFAULT) - break; - case STATE_DEFAULT: - usbd_device_event_irq (udc_device, - DEVICE_ADDRESS_ASSIGNED, 0); - if (final == STATE_ADDRESSED) - break; - case STATE_ADDRESSED: - usbd_device_event_irq (udc_device, DEVICE_CONFIGURED, - 0); - case STATE_CONFIGURED: - break; - default: - break; - } - } -} - -static void udc_state_transition_down (usb_device_state_t initial, - usb_device_state_t final) -{ - if (initial > final) { - switch (initial) { - case STATE_CONFIGURED: - usbd_device_event_irq (udc_device, DEVICE_DE_CONFIGURED, 0); - if (final == STATE_ADDRESSED) - break; - case STATE_ADDRESSED: - usbd_device_event_irq (udc_device, DEVICE_RESET, 0); - if (final == STATE_DEFAULT) - break; - case STATE_DEFAULT: - usbd_device_event_irq (udc_device, DEVICE_POWER_INTERRUPTION, 0); - if (final == STATE_POWERED) - break; - case STATE_POWERED: - usbd_device_event_irq (udc_device, DEVICE_HUB_RESET, 0); - case STATE_ATTACHED: - break; - default: - break; - } - } -} - -/* Handle all device state changes. - * This function implements TRM Figure 14-21. - */ -static void omap1510_udc_state_changed (void) -{ - u16 bits; - u16 devstat = inw (UDC_DEVSTAT); - - UDCDBGA ("state changed, devstat %x, old %x", devstat, udc_devstat); - - bits = devstat ^ udc_devstat; - if (bits) { - if (bits & UDC_ATT) { - if (devstat & UDC_ATT) { - UDCDBG ("device attached and powered"); - udc_state_transition_up (udc_device->device_state, STATE_POWERED); - } else { - UDCDBG ("device detached or unpowered"); - udc_state_transition_down (udc_device->device_state, STATE_ATTACHED); - } - } - if (bits & UDC_USB_Reset) { - if (devstat & UDC_USB_Reset) { - UDCDBG ("device reset in progess"); - udc_state_transition_down (udc_device->device_state, STATE_POWERED); - } else { - UDCDBG ("device reset completed"); - } - } - if (bits & UDC_DEF) { - if (devstat & UDC_DEF) { - UDCDBG ("device entering default state"); - udc_state_transition_up (udc_device->device_state, STATE_DEFAULT); - } else { - UDCDBG ("device leaving default state"); - udc_state_transition_down (udc_device->device_state, STATE_POWERED); - } - } - if (bits & UDC_SUS) { - if (devstat & UDC_SUS) { - UDCDBG ("entering suspended state"); - usbd_device_event_irq (udc_device, DEVICE_BUS_INACTIVE, 0); - } else { - UDCDBG ("leaving suspended state"); - usbd_device_event_irq (udc_device, DEVICE_BUS_ACTIVITY, 0); - } - } - if (bits & UDC_R_WK_OK) { - UDCDBGA ("remote wakeup %s", (devstat & UDC_R_WK_OK) - ? "enabled" : "disabled"); - } - if (bits & UDC_ADD) { - if (devstat & UDC_ADD) { - UDCDBG ("default -> addressed"); - udc_state_transition_up (udc_device->device_state, STATE_ADDRESSED); - } else { - UDCDBG ("addressed -> default"); - udc_state_transition_down (udc_device->device_state, STATE_DEFAULT); - } - } - if (bits & UDC_CFG) { - if (devstat & UDC_CFG) { - UDCDBG ("device configured"); - /* The ep0_recv_setup function generates the - * DEVICE_CONFIGURED event when a - * USB_REQ_SET_CONFIGURATION setup packet is - * received, so we should already be in the - * state STATE_CONFIGURED. - */ - udc_state_transition_up (udc_device->device_state, STATE_CONFIGURED); - } else { - UDCDBG ("device deconfigured"); - udc_state_transition_down (udc_device->device_state, STATE_ADDRESSED); - } - } - } - - /* Clear interrupt source */ - outw (UDC_DS_Chg, UDC_IRQ_SRC); - - /* Save current DEVSTAT */ - udc_devstat = devstat; -} - -/* Handle SETUP USB interrupt. - * This function implements TRM Figure 14-14. - */ -static void omap1510_udc_setup (struct usb_endpoint_instance *endpoint) -{ - UDCDBG ("-> Entering device setup"); - - do { - const int setup_pktsize = 8; - unsigned char *datap = - (unsigned char *) &ep0_urb->device_request; - - /* Gain access to EP 0 setup FIFO */ - outw (UDC_Setup_Sel, UDC_EP_NUM); - - /* Read control request data */ - insb (UDC_DATA, datap, setup_pktsize); - - UDCDBGA ("EP0 setup read [%x %x %x %x %x %x %x %x]", - *(datap + 0), *(datap + 1), *(datap + 2), - *(datap + 3), *(datap + 4), *(datap + 5), - *(datap + 6), *(datap + 7)); - - /* Reset EP0 setup FIFO */ - outw (0, UDC_EP_NUM); - } while (inw (UDC_IRQ_SRC) & UDC_Setup); - - /* Try to process setup packet */ - if (ep0_recv_setup (ep0_urb)) { - /* Not a setup packet, stall next EP0 transaction */ - udc_stall_ep (0); - UDCDBG ("can't parse setup packet, still waiting for setup"); - return; - } - - /* Check direction */ - if ((ep0_urb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK) - == USB_REQ_HOST2DEVICE) { - UDCDBG ("control write on EP0"); - if (le16_to_cpu (ep0_urb->device_request.wLength)) { - /* We don't support control write data stages. - * The only standard control write request with a data - * stage is SET_DESCRIPTOR, and ep0_recv_setup doesn't - * support that so we just stall those requests. A - * function driver might support a non-standard - * write request with a data stage, but it isn't - * obvious what we would do with the data if we read it - * so we'll just stall it. It seems like the API isn't - * quite right here. - */ -#if 0 - /* Here is what we would do if we did support control - * write data stages. - */ - ep0_urb->actual_length = 0; - outw (0, UDC_EP_NUM); - /* enable the EP0 rx FIFO */ - outw (UDC_Set_FIFO_En, UDC_CTRL); -#else - /* Stall this request */ - UDCDBG ("Stalling unsupported EP0 control write data " - "stage."); - udc_stall_ep (0); -#endif - } else { - omap1510_prepare_for_control_write_status (ep0_urb); - } - } else { - UDCDBG ("control read on EP0"); - /* The ep0_recv_setup function has already placed our response - * packet data in ep0_urb->buffer and the packet length in - * ep0_urb->actual_length. - */ - endpoint->tx_urb = ep0_urb; - endpoint->sent = 0; - /* select the EP0 tx FIFO */ - outw (UDC_EP_Dir | UDC_EP_Sel, UDC_EP_NUM); - /* Write packet data to the FIFO. omap1510_write_noniso_tx_fifo - * will update endpoint->last with the number of bytes written - * to the FIFO. - */ - omap1510_write_noniso_tx_fifo (endpoint); - /* enable the FIFO to start the packet transmission */ - outw (UDC_Set_FIFO_En, UDC_CTRL); - /* deselect the EP0 tx FIFO */ - outw (UDC_EP_Dir, UDC_EP_NUM); - } - - UDCDBG ("<- Leaving device setup"); -} - -/* Handle endpoint 0 RX interrupt - * This routine implements TRM Figure 14-16. - */ -static void omap1510_udc_ep0_rx (struct usb_endpoint_instance *endpoint) -{ - unsigned short status; - - UDCDBG ("RX on EP0"); - /* select EP0 rx FIFO */ - outw (UDC_EP_Sel, UDC_EP_NUM); - - status = inw (UDC_STAT_FLG); - - if (status & UDC_ACK) { - /* Check direction */ - if ((ep0_urb->device_request.bmRequestType - & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) { - /* This rx interrupt must be for a control write data - * stage packet. - * - * We don't support control write data stages. - * We should never end up here. - */ - - /* clear the EP0 rx FIFO */ - outw (UDC_Clr_EP, UDC_CTRL); - - /* deselect the EP0 rx FIFO */ - outw (0, UDC_EP_NUM); - - UDCDBG ("Stalling unexpected EP0 control write " - "data stage packet"); - udc_stall_ep (0); - } else { - /* This rx interrupt must be for a control read status - * stage packet. - */ - UDCDBG ("ACK on EP0 control read status stage packet"); - /* deselect EP0 rx FIFO */ - outw (0, UDC_EP_NUM); - } - } else if (status & UDC_STALL) { - UDCDBG ("EP0 stall during RX"); - /* deselect EP0 rx FIFO */ - outw (0, UDC_EP_NUM); - } else { - /* deselect EP0 rx FIFO */ - outw (0, UDC_EP_NUM); - } -} - -/* Handle endpoint 0 TX interrupt - * This routine implements TRM Figure 14-18. - */ -static void omap1510_udc_ep0_tx (struct usb_endpoint_instance *endpoint) -{ - unsigned short status; - struct usb_device_request *request = &ep0_urb->device_request; - - UDCDBG ("TX on EP0"); - /* select EP0 TX FIFO */ - outw (UDC_EP_Dir | UDC_EP_Sel, UDC_EP_NUM); - - status = inw (UDC_STAT_FLG); - if (status & UDC_ACK) { - /* Check direction */ - if ((request->bmRequestType & USB_REQ_DIRECTION_MASK) == - USB_REQ_HOST2DEVICE) { - /* This tx interrupt must be for a control write status - * stage packet. - */ - UDCDBG ("ACK on EP0 control write status stage packet"); - /* deselect EP0 TX FIFO */ - outw (UDC_EP_Dir, UDC_EP_NUM); - } else { - /* This tx interrupt must be for a control read data - * stage packet. - */ - int wLength = le16_to_cpu (request->wLength); - - /* Update our count of bytes sent so far in this - * transfer. - */ - endpoint->sent += endpoint->last; - - /* We are finished with this transfer if we have sent - * all of the bytes in our tx urb (urb->actual_length) - * unless we need a zero-length terminating packet. We - * need a zero-length terminating packet if we returned - * fewer bytes than were requested (wLength) by the host, - * and the number of bytes we returned is an exact - * multiple of the packet size endpoint->tx_packetSize. - */ - if ((endpoint->sent == ep0_urb->actual_length) - && ((ep0_urb->actual_length == wLength) - || (endpoint->last != - endpoint->tx_packetSize))) { - /* Done with control read data stage. */ - UDCDBG ("control read data stage complete"); - /* deselect EP0 TX FIFO */ - outw (UDC_EP_Dir, UDC_EP_NUM); - /* select EP0 RX FIFO to prepare for control - * read status stage. - */ - outw (UDC_EP_Sel, UDC_EP_NUM); - /* clear the EP0 RX FIFO */ - outw (UDC_Clr_EP, UDC_CTRL); - /* enable the EP0 RX FIFO */ - outw (UDC_Set_FIFO_En, UDC_CTRL); - /* deselect the EP0 RX FIFO */ - outw (0, UDC_EP_NUM); - } else { - /* We still have another packet of data to send - * in this control read data stage or else we - * need a zero-length terminating packet. - */ - UDCDBG ("ACK control read data stage packet"); - omap1510_write_noniso_tx_fifo (endpoint); - /* enable the EP0 tx FIFO to start transmission */ - outw (UDC_Set_FIFO_En, UDC_CTRL); - /* deselect EP0 TX FIFO */ - outw (UDC_EP_Dir, UDC_EP_NUM); - } - } - } else if (status & UDC_STALL) { - UDCDBG ("EP0 stall during TX"); - /* deselect EP0 TX FIFO */ - outw (UDC_EP_Dir, UDC_EP_NUM); - } else { - /* deselect EP0 TX FIFO */ - outw (UDC_EP_Dir, UDC_EP_NUM); - } -} - -/* Handle RX transaction on non-ISO endpoint. - * This function implements TRM Figure 14-27. - * The ep argument is a physical endpoint number for a non-ISO OUT endpoint - * in the range 1 to 15. - */ -static void omap1510_udc_epn_rx (int ep) -{ - unsigned short status; - - /* Check endpoint status */ - status = inw (UDC_STAT_FLG); - - if (status & UDC_ACK) { - int nbytes; - struct usb_endpoint_instance *endpoint = - omap1510_find_ep (ep); - - nbytes = omap1510_read_noniso_rx_fifo (endpoint); - usbd_rcv_complete (endpoint, nbytes, 0); - - /* enable rx FIFO to prepare for next packet */ - outw (UDC_Set_FIFO_En, UDC_CTRL); - } else if (status & UDC_STALL) { - UDCDBGA ("STALL on RX endpoint %d", ep); - } else if (status & UDC_NAK) { - UDCDBGA ("NAK on RX ep %d", ep); - } else { - serial_printf ("omap-bi: RX on ep %d with status %x", ep, - status); - } -} - -/* Handle TX transaction on non-ISO endpoint. - * This function implements TRM Figure 14-29. - * The ep argument is a physical endpoint number for a non-ISO IN endpoint - * in the range 16 to 30. - */ -static void omap1510_udc_epn_tx (int ep) -{ - unsigned short status; - - /*serial_printf("omap1510_udc_epn_tx( %x )\n",ep); */ - - /* Check endpoint status */ - status = inw (UDC_STAT_FLG); - - if (status & UDC_ACK) { - struct usb_endpoint_instance *endpoint = - omap1510_find_ep (ep); - - /* We need to transmit a terminating zero-length packet now if - * we have sent all of the data in this URB and the transfer - * size was an exact multiple of the packet size. - */ - if (endpoint->tx_urb - && (endpoint->last == endpoint->tx_packetSize) - && (endpoint->tx_urb->actual_length - endpoint->sent - - endpoint->last == 0)) { - /* Prepare to transmit a zero-length packet. */ - endpoint->sent += endpoint->last; - /* write 0 bytes of data to FIFO */ - omap1510_write_noniso_tx_fifo (endpoint); - /* enable tx FIFO to start transmission */ - outw (UDC_Set_FIFO_En, UDC_CTRL); - } else if (endpoint->tx_urb - && endpoint->tx_urb->actual_length) { - /* retire the data that was just sent */ - usbd_tx_complete (endpoint); - /* Check to see if we have more data ready to transmit - * now. - */ - if (endpoint->tx_urb - && endpoint->tx_urb->actual_length) { - /* write data to FIFO */ - omap1510_write_noniso_tx_fifo (endpoint); - /* enable tx FIFO to start transmission */ - outw (UDC_Set_FIFO_En, UDC_CTRL); - } - } - } else if (status & UDC_STALL) { - UDCDBGA ("STALL on TX endpoint %d", ep); - } else if (status & UDC_NAK) { - UDCDBGA ("NAK on TX endpoint %d", ep); - } else { - /*serial_printf("omap-bi: TX on ep %d with status %x\n", ep, status); */ - } -} - - -/* -------------------------------------------------------------------------------- -*/ - -/* Handle general USB interrupts and dispatch according to type. - * This function implements TRM Figure 14-13. - */ -void omap1510_udc_irq (void) -{ - u16 irq_src = inw (UDC_IRQ_SRC); - int valid_irq = 0; - - if (!(irq_src & ~UDC_SOF_Flg)) /* ignore SOF interrupts ) */ - return; - - UDCDBGA ("< IRQ #%d start >- %x", udc_interrupts, irq_src); - /*serial_printf("< IRQ #%d start >- %x\n", udc_interrupts, irq_src); */ - - if (irq_src & UDC_DS_Chg) { - /* Device status changed */ - omap1510_udc_state_changed (); - valid_irq++; - } - if (irq_src & UDC_EP0_RX) { - /* Endpoint 0 receive */ - outw (UDC_EP0_RX, UDC_IRQ_SRC); /* ack interrupt */ - omap1510_udc_ep0_rx (udc_device->bus->endpoint_array + 0); - valid_irq++; - } - if (irq_src & UDC_EP0_TX) { - /* Endpoint 0 transmit */ - outw (UDC_EP0_TX, UDC_IRQ_SRC); /* ack interrupt */ - omap1510_udc_ep0_tx (udc_device->bus->endpoint_array + 0); - valid_irq++; - } - if (irq_src & UDC_Setup) { - /* Device setup */ - omap1510_udc_setup (udc_device->bus->endpoint_array + 0); - valid_irq++; - } - /*if (!valid_irq) */ - /* serial_printf("unknown interrupt, IRQ_SRC %.4x\n", irq_src); */ - UDCDBGA ("< IRQ #%d end >", udc_interrupts); - udc_interrupts++; -} - -/* This function implements TRM Figure 14-26. */ -void omap1510_udc_noniso_irq (void) -{ - unsigned short epnum; - unsigned short irq_src = inw (UDC_IRQ_SRC); - int valid_irq = 0; - - if (!(irq_src & (UDC_EPn_RX | UDC_EPn_TX))) - return; - - UDCDBGA ("non-ISO IRQ, IRQ_SRC %x", inw (UDC_IRQ_SRC)); - - if (irq_src & UDC_EPn_RX) { /* Endpoint N OUT transaction */ - /* Determine the endpoint number for this interrupt */ - epnum = (inw (UDC_EPN_STAT) & 0x0f00) >> 8; - UDCDBGA ("RX on ep %x", epnum); - - /* acknowledge interrupt */ - outw (UDC_EPn_RX, UDC_IRQ_SRC); - - if (epnum) { - /* select the endpoint FIFO */ - outw (UDC_EP_Sel | epnum, UDC_EP_NUM); - - omap1510_udc_epn_rx (epnum); - - /* deselect the endpoint FIFO */ - outw (epnum, UDC_EP_NUM); - } - valid_irq++; - } - if (irq_src & UDC_EPn_TX) { /* Endpoint N IN transaction */ - /* Determine the endpoint number for this interrupt */ - epnum = (inw (UDC_EPN_STAT) & 0x000f) | USB_DIR_IN; - UDCDBGA ("TX on ep %x", epnum); - - /* acknowledge interrupt */ - outw (UDC_EPn_TX, UDC_IRQ_SRC); - - if (epnum) { - /* select the endpoint FIFO */ - outw (UDC_EP_Sel | UDC_EP_Dir | epnum, UDC_EP_NUM); - - omap1510_udc_epn_tx (epnum); - - /* deselect the endpoint FIFO */ - outw (UDC_EP_Dir | epnum, UDC_EP_NUM); - } - valid_irq++; - } - if (!valid_irq) - serial_printf (": unknown non-ISO interrupt, IRQ_SRC %.4x\n", - irq_src); -} - -/* -------------------------------------------------------------------------------- -*/ - - -/* - * Start of public functions. - */ - -/* Called to start packet transmission. */ -int udc_endpoint_write (struct usb_endpoint_instance *endpoint) -{ - unsigned short epnum = - endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK; - - UDCDBGA ("Starting transmit on ep %x", epnum); - - if (endpoint->tx_urb) { - /* select the endpoint FIFO */ - outw (UDC_EP_Sel | UDC_EP_Dir | epnum, UDC_EP_NUM); - /* write data to FIFO */ - omap1510_write_noniso_tx_fifo (endpoint); - /* enable tx FIFO to start transmission */ - outw (UDC_Set_FIFO_En, UDC_CTRL); - /* deselect the endpoint FIFO */ - outw (UDC_EP_Dir | epnum, UDC_EP_NUM); - } - - return 0; -} - -/* Start to initialize h/w stuff */ -int udc_init (void) -{ - u16 udc_rev; - uchar value; - ulong gpio; - int i; - - /* Let the device settle down before we start */ - for (i = 0; i < UDC_INIT_MDELAY; i++) udelay(1000); - - udc_device = NULL; - - UDCDBG ("starting"); - - /* Check peripheral reset. Must be 1 to make sure - MPU TIPB peripheral reset is inactive */ - UDCREG (ARM_RSTCT2); - - /* Set and check clock control. - * We might ought to be using the clock control API to do - * this instead of fiddling with the clock registers directly - * here. - */ - outw ((1 << 4) | (1 << 5), CLOCK_CTRL); - UDCREG (CLOCK_CTRL); - -#ifdef CONFIG_OMAP1510 - /* This code was originally implemented for OMAP1510 and - * therefore is only applicable for OMAP1510 boards. For - * OMAP5912 or OMAP16xx the register APLL_CTRL does not - * exist and DPLL_CTRL is already configured. - */ - - /* Set and check APLL */ - outw (0x0008, APLL_CTRL); - UDCREG (APLL_CTRL); - /* Set and check DPLL */ - outw (0x2210, DPLL_CTRL); - UDCREG (DPLL_CTRL); -#endif - /* Set and check SOFT - * The below line of code has been changed to perform a - * read-modify-write instead of a simple write for - * configuring the SOFT_REQ register. This allows the code - * to be compatible with OMAP5912 and OMAP16xx devices - */ - outw ((1 << 4) | (1 << 3) | 1 | (inw(SOFT_REQ)), SOFT_REQ); - - /* Short delay to wait for DPLL */ - udelay (1000); - - /* Print banner with device revision */ - udc_rev = inw (UDC_REV) & 0xff; -#ifdef CONFIG_OMAP1510 - printf ("USB: TI OMAP1510 USB function module rev %d.%d\n", - udc_rev >> 4, udc_rev & 0xf); -#endif - -#ifdef CONFIG_OMAP1610 - printf ("USB: TI OMAP5912 USB function module rev %d.%d\n", - udc_rev >> 4, udc_rev & 0xf); -#endif - -#ifdef CONFIG_OMAP_SX1 - i2c_read (0x32, 0x04, 1, &value, 1); - value |= 0x04; - i2c_write (0x32, 0x04, 1, &value, 1); - - i2c_read (0x32, 0x03, 1, &value, 1); - value |= 0x01; - i2c_write (0x32, 0x03, 1, &value, 1); - - gpio = inl(GPIO_PIN_CONTROL_REG); - gpio |= 0x0002; /* A_IRDA_OFF */ - gpio |= 0x0800; /* A_SWITCH */ - gpio |= 0x8000; /* A_USB_ON */ - outl (gpio, GPIO_PIN_CONTROL_REG); - - gpio = inl(GPIO_DIR_CONTROL_REG); - gpio &= ~0x0002; /* A_IRDA_OFF */ - gpio &= ~0x0800; /* A_SWITCH */ - gpio &= ~0x8000; /* A_USB_ON */ - outl (gpio, GPIO_DIR_CONTROL_REG); - - gpio = inl(GPIO_DATA_OUTPUT_REG); - gpio |= 0x0002; /* A_IRDA_OFF */ - gpio &= ~0x0800; /* A_SWITCH */ - gpio &= ~0x8000; /* A_USB_ON */ - outl (gpio, GPIO_DATA_OUTPUT_REG); -#endif - - /* The VBUS_MODE bit selects whether VBUS detection is done via - * software (1) or hardware (0). When software detection is - * selected, VBUS_CTRL selects whether USB is not connected (0) - * or connected (1). - */ - outl (inl (FUNC_MUX_CTRL_0) | UDC_VBUS_MODE, FUNC_MUX_CTRL_0); - outl (inl (FUNC_MUX_CTRL_0) & ~UDC_VBUS_CTRL, FUNC_MUX_CTRL_0); - UDCREGL (FUNC_MUX_CTRL_0); - - /* - * At this point, device is ready for configuration... - */ - - UDCDBG ("disable USB interrupts"); - outw (0, UDC_IRQ_EN); - UDCREG (UDC_IRQ_EN); - - UDCDBG ("disable USB DMA"); - outw (0, UDC_DMA_IRQ_EN); - UDCREG (UDC_DMA_IRQ_EN); - - UDCDBG ("initialize SYSCON1"); - outw (UDC_Self_Pwr | UDC_Pullup_En, UDC_SYSCON1); - UDCREG (UDC_SYSCON1); - - return 0; -} - -/* Stall endpoint */ -static void udc_stall_ep (unsigned int ep_addr) -{ - /*int ep_addr = PHYS_EP_TO_EP_ADDR(ep); */ - int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; - - UDCDBGA ("stall ep_addr %d", ep_addr); - - /* REVISIT? - * The OMAP TRM section 14.2.4.2 says we must check that the FIFO - * is empty before halting the endpoint. The current implementation - * doesn't check that the FIFO is empty. - */ - - if (!ep_num) { - outw (UDC_Stall_Cmd, UDC_SYSCON2); - } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { - if (inw (UDC_EP_RX (ep_num)) & UDC_EPn_RX_Valid) { - /* we have a valid rx endpoint, so halt it */ - outw (UDC_EP_Sel | ep_num, UDC_EP_NUM); - outw (UDC_Set_Halt, UDC_CTRL); - outw (ep_num, UDC_EP_NUM); - } - } else { - if (inw (UDC_EP_TX (ep_num)) & UDC_EPn_TX_Valid) { - /* we have a valid tx endpoint, so halt it */ - outw (UDC_EP_Sel | UDC_EP_Dir | ep_num, UDC_EP_NUM); - outw (UDC_Set_Halt, UDC_CTRL); - outw (ep_num, UDC_EP_NUM); - } - } -} - -/* Reset endpoint */ -#if 0 -static void udc_reset_ep (unsigned int ep_addr) -{ - /*int ep_addr = PHYS_EP_TO_EP_ADDR(ep); */ - int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; - - UDCDBGA ("reset ep_addr %d", ep_addr); - - if (!ep_num) { - /* control endpoint 0 can't be reset */ - } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { - UDCDBGA ("UDC_EP_RX(%d) = 0x%04x", ep_num, - inw (UDC_EP_RX (ep_num))); - if (inw (UDC_EP_RX (ep_num)) & UDC_EPn_RX_Valid) { - /* we have a valid rx endpoint, so reset it */ - outw (ep_num | UDC_EP_Sel, UDC_EP_NUM); - outw (UDC_Reset_EP, UDC_CTRL); - outw (ep_num, UDC_EP_NUM); - UDCDBGA ("OUT endpoint %d reset", ep_num); - } - } else { - UDCDBGA ("UDC_EP_TX(%d) = 0x%04x", ep_num, - inw (UDC_EP_TX (ep_num))); - /* Resetting of tx endpoints seems to be causing the USB function - * module to fail, which causes problems when the driver is - * uninstalled. We'll skip resetting tx endpoints for now until - * we figure out what the problem is. - */ -#if 0 - if (inw (UDC_EP_TX (ep_num)) & UDC_EPn_TX_Valid) { - /* we have a valid tx endpoint, so reset it */ - outw (ep_num | UDC_EP_Dir | UDC_EP_Sel, UDC_EP_NUM); - outw (UDC_Reset_EP, UDC_CTRL); - outw (ep_num | UDC_EP_Dir, UDC_EP_NUM); - UDCDBGA ("IN endpoint %d reset", ep_num); - } -#endif - } -} -#endif - -/* ************************************************************************** */ - -/** - * udc_check_ep - check logical endpoint - * - * Return physical endpoint number to use for this logical endpoint or zero if not valid. - */ -#if 0 -int udc_check_ep (int logical_endpoint, int packetsize) -{ - if ((logical_endpoint == 0x80) || - ((logical_endpoint & 0x8f) != logical_endpoint)) { - return 0; - } - - switch (packetsize) { - case 8: - case 16: - case 32: - case 64: - case 128: - case 256: - case 512: - break; - default: - return 0; - } - - return EP_ADDR_TO_PHYS_EP (logical_endpoint); -} -#endif - -/* - * udc_setup_ep - setup endpoint - * - * Associate a physical endpoint with endpoint_instance - */ -void udc_setup_ep (struct usb_device_instance *device, - unsigned int ep, struct usb_endpoint_instance *endpoint) -{ - UDCDBGA ("setting up endpoint addr %x", endpoint->endpoint_address); - - /* This routine gets called by bi_modinit for endpoint 0 and from - * bi_config for all of the other endpoints. bi_config gets called - * during the DEVICE_CREATE, DEVICE_CONFIGURED, and - * DEVICE_SET_INTERFACE events. We need to reconfigure the OMAP packet - * RAM after bi_config scans the selected device configuration and - * initializes the endpoint structures, but before this routine enables - * the OUT endpoint FIFOs. Since bi_config calls this routine in a - * loop for endpoints 1 through UDC_MAX_ENDPOINTS, we reconfigure our - * packet RAM here when ep==1. - * I really hate to do this here, but it seems like the API exported - * by the USB bus interface controller driver to the usbd-bi module - * isn't quite right so there is no good place to do this. - */ - if (ep == 1) { - omap1510_deconfigure_device (); - omap1510_configure_device (device); - } - - if (endpoint && (ep < UDC_MAX_ENDPOINTS)) { - int ep_addr = endpoint->endpoint_address; - - if (!ep_addr) { - /* nothing to do for endpoint 0 */ - } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { - /* nothing to do for IN (tx) endpoints */ - } else { /* OUT (rx) endpoint */ - if (endpoint->rcv_packetSize) { - /*struct urb* urb = &(urb_out_array[ep&0xFF]); */ - /*urb->endpoint = endpoint; */ - /*urb->device = device; */ - /*urb->buffer_length = sizeof(urb->buffer); */ - - /*endpoint->rcv_urb = urb; */ - omap1510_prepare_endpoint_for_rx (ep_addr); - } - } - } -} - -/** - * udc_disable_ep - disable endpoint - * @ep: - * - * Disable specified endpoint - */ -#if 0 -void udc_disable_ep (unsigned int ep_addr) -{ - /*int ep_addr = PHYS_EP_TO_EP_ADDR(ep); */ - int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; - struct usb_endpoint_instance *endpoint = omap1510_find_ep (ep_addr); /*udc_device->bus->endpoint_array + ep; */ - - UDCDBGA ("disable ep_addr %d", ep_addr); - - if (!ep_num) { - /* nothing to do for endpoint 0 */ ; - } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { - if (endpoint->tx_packetSize) { - /* we have a valid tx endpoint */ - /*usbd_flush_tx(endpoint); */ - endpoint->tx_urb = NULL; - } - } else { - if (endpoint->rcv_packetSize) { - /* we have a valid rx endpoint */ - /*usbd_flush_rcv(endpoint); */ - endpoint->rcv_urb = NULL; - } - } -} -#endif - -/* ************************************************************************** */ - -/** - * udc_connected - is the USB cable connected - * - * Return non-zero if cable is connected. - */ -#if 0 -int udc_connected (void) -{ - return ((inw (UDC_DEVSTAT) & UDC_ATT) == UDC_ATT); -} -#endif - -/* Turn on the USB connection by enabling the pullup resistor */ -void udc_connect (void) -{ - UDCDBG ("connect, enable Pullup"); - outl (0x00000018, FUNC_MUX_CTRL_D); -} - -/* Turn off the USB connection by disabling the pullup resistor */ -void udc_disconnect (void) -{ - UDCDBG ("disconnect, disable Pullup"); - outl (0x00000000, FUNC_MUX_CTRL_D); -} - -/* ************************************************************************** */ - - -/* - * udc_disable_interrupts - disable interrupts - * switch off interrupts - */ -#if 0 -void udc_disable_interrupts (struct usb_device_instance *device) -{ - UDCDBG ("disabling all interrupts"); - outw (0, UDC_IRQ_EN); -} -#endif - -/* ************************************************************************** */ - -/** - * udc_ep0_packetsize - return ep0 packetsize - */ -#if 0 -int udc_ep0_packetsize (void) -{ - return EP0_PACKETSIZE; -} -#endif - -/* Switch on the UDC */ -void udc_enable (struct usb_device_instance *device) -{ - UDCDBGA ("enable device %p, status %d", device, device->status); - - /* initialize driver state variables */ - udc_devstat = 0; - - /* Save the device structure pointer */ - udc_device = device; - - /* Setup ep0 urb */ - if (!ep0_urb) { - ep0_urb = - usbd_alloc_urb (udc_device, - udc_device->bus->endpoint_array); - } else { - serial_printf ("udc_enable: ep0_urb already allocated %p\n", - ep0_urb); - } - - UDCDBG ("Check clock status"); - UDCREG (STATUS_REQ); - - /* The VBUS_MODE bit selects whether VBUS detection is done via - * software (1) or hardware (0). When software detection is - * selected, VBUS_CTRL selects whether USB is not connected (0) - * or connected (1). - */ - outl (inl (FUNC_MUX_CTRL_0) | UDC_VBUS_CTRL | UDC_VBUS_MODE, - FUNC_MUX_CTRL_0); - UDCREGL (FUNC_MUX_CTRL_0); - - omap1510_configure_device (device); -} - -/* Switch off the UDC */ -void udc_disable (void) -{ - UDCDBG ("disable UDC"); - - omap1510_deconfigure_device (); - - /* The VBUS_MODE bit selects whether VBUS detection is done via - * software (1) or hardware (0). When software detection is - * selected, VBUS_CTRL selects whether USB is not connected (0) - * or connected (1). - */ - outl (inl (FUNC_MUX_CTRL_0) | UDC_VBUS_MODE, FUNC_MUX_CTRL_0); - outl (inl (FUNC_MUX_CTRL_0) & ~UDC_VBUS_CTRL, FUNC_MUX_CTRL_0); - UDCREGL (FUNC_MUX_CTRL_0); - - /* Free ep0 URB */ - if (ep0_urb) { - /*usbd_dealloc_urb(ep0_urb); */ - ep0_urb = NULL; - } - - /* Reset device pointer. - * We ought to do this here to balance the initialization of udc_device - * in udc_enable, but some of our other exported functions get called - * by the bus interface driver after udc_disable, so we have to hang on - * to the device pointer to avoid a null pointer dereference. */ - /* udc_device = NULL; */ -} - -/** - * udc_startup - allow udc code to do any additional startup - */ -void udc_startup_events (struct usb_device_instance *device) -{ - /* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */ - usbd_device_event_irq (device, DEVICE_INIT, 0); - - /* The DEVICE_CREATE event puts the USB device in the state - * STATE_ATTACHED. - */ - usbd_device_event_irq (device, DEVICE_CREATE, 0); - - /* Some USB controller driver implementations signal - * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here. - * DEVICE_HUB_CONFIGURED causes a transition to the state STATE_POWERED, - * and DEVICE_RESET causes a transition to the state STATE_DEFAULT. - * The OMAP USB client controller has the capability to detect when the - * USB cable is connected to a powered USB bus via the ATT bit in the - * DEVSTAT register, so we will defer the DEVICE_HUB_CONFIGURED and - * DEVICE_RESET events until later. - */ - - udc_enable (device); -} - -/** - * udc_irq - do pseudo interrupts - */ -void udc_irq(void) -{ - /* Loop while we have interrupts. - * If we don't do this, the input chain - * polling delay is likely to miss - * host requests. - */ - while (inw (UDC_IRQ_SRC) & ~UDC_SOF_Flg) { - /* Handle any new IRQs */ - omap1510_udc_irq (); - omap1510_udc_noniso_irq (); - } -} - -/* Flow control */ -void udc_set_nak(int epid) -{ - /* TODO: implement this functionality in omap1510 */ -} - -void udc_unset_nak (int epid) -{ - /* TODO: implement this functionality in omap1510 */ -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/pxa25x_udc.c b/qemu/roms/u-boot/drivers/usb/gadget/pxa25x_udc.c deleted file mode 100644 index 8945c5b66..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/pxa25x_udc.c +++ /dev/null @@ -1,2047 +0,0 @@ -/* - * Intel PXA25x and IXP4xx on-chip full speed USB device controllers - * - * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker) - * Copyright (C) 2003 Robert Schwebel, Pengutronix - * Copyright (C) 2003 Benedikt Spranger, Pengutronix - * Copyright (C) 2003 David Brownell - * Copyright (C) 2003 Joshua Wise - * Copyright (C) 2012 Lukasz Dalek <luk0104@gmail.com> - * - * SPDX-License-Identifier: GPL-2.0+ - * - * MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell"); - */ - -#define CONFIG_USB_PXA25X_SMALL -#define DRIVER_NAME "pxa25x_udc_linux" -#define ARCH_HAS_PREFETCH - -#include <common.h> -#include <errno.h> -#include <asm/byteorder.h> -#include <asm/system.h> -#include <asm/mach-types.h> -#include <asm/unaligned.h> -#include <linux/compat.h> -#include <malloc.h> -#include <asm/io.h> -#include <asm/arch/pxa.h> - -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <usb/lin_gadget_compat.h> -#include <asm/arch/pxa-regs.h> - -#include "pxa25x_udc.h" - -/* - * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x - * series processors. The UDC for the IXP 4xx series is very similar. - * There are fifteen endpoints, in addition to ep0. - * - * Such controller drivers work with a gadget driver. The gadget driver - * returns descriptors, implements configuration and data protocols used - * by the host to interact with this device, and allocates endpoints to - * the different protocol interfaces. The controller driver virtualizes - * usb hardware so that the gadget drivers will be more portable. - * - * This UDC hardware wants to implement a bit too much USB protocol, so - * it constrains the sorts of USB configuration change events that work. - * The errata for these chips are misleading; some "fixed" bugs from - * pxa250 a0/a1 b0/b1/b2 sure act like they're still there. - * - * Note that the UDC hardware supports DMA (except on IXP) but that's - * not used here. IN-DMA (to host) is simple enough, when the data is - * suitably aligned (16 bytes) ... the network stack doesn't do that, - * other software can. OUT-DMA is buggy in most chip versions, as well - * as poorly designed (data toggle not automatic). So this driver won't - * bother using DMA. (Mostly-working IN-DMA support was available in - * kernels before 2.6.23, but was never enabled or well tested.) - */ - -#define DRIVER_VERSION "18-August-2012" -#define DRIVER_DESC "PXA 25x USB Device Controller driver" - -static const char driver_name[] = "pxa25x_udc"; -static const char ep0name[] = "ep0"; - -/* Watchdog */ -static inline void start_watchdog(struct pxa25x_udc *udc) -{ - debug("Started watchdog\n"); - udc->watchdog.base = get_timer(0); - udc->watchdog.running = 1; -} - -static inline void stop_watchdog(struct pxa25x_udc *udc) -{ - udc->watchdog.running = 0; - debug("Stopped watchdog\n"); -} - -static inline void test_watchdog(struct pxa25x_udc *udc) -{ - if (!udc->watchdog.running) - return; - - debug("watchdog %ld %ld\n", get_timer(udc->watchdog.base), - udc->watchdog.period); - - if (get_timer(udc->watchdog.base) >= udc->watchdog.period) { - stop_watchdog(udc); - udc->watchdog.function(udc); - } -} - -static void udc_watchdog(struct pxa25x_udc *dev) -{ - uint32_t udccs0 = readl(&dev->regs->udccs[0]); - - debug("Fired up udc_watchdog\n"); - - local_irq_disable(); - if (dev->ep0state == EP0_STALL - && (udccs0 & UDCCS0_FST) == 0 - && (udccs0 & UDCCS0_SST) == 0) { - writel(UDCCS0_FST|UDCCS0_FTF, &dev->regs->udccs[0]); - debug("ep0 re-stall\n"); - start_watchdog(dev); - } - local_irq_enable(); -} - -#ifdef DEBUG - -static const char * const state_name[] = { - "EP0_IDLE", - "EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE", - "EP0_END_XFER", "EP0_STALL" -}; - -static void -dump_udccr(const char *label) -{ - u32 udccr = readl(&UDC_REGS->udccr); - debug("%s %02X =%s%s%s%s%s%s%s%s\n", - label, udccr, - (udccr & UDCCR_REM) ? " rem" : "", - (udccr & UDCCR_RSTIR) ? " rstir" : "", - (udccr & UDCCR_SRM) ? " srm" : "", - (udccr & UDCCR_SUSIR) ? " susir" : "", - (udccr & UDCCR_RESIR) ? " resir" : "", - (udccr & UDCCR_RSM) ? " rsm" : "", - (udccr & UDCCR_UDA) ? " uda" : "", - (udccr & UDCCR_UDE) ? " ude" : ""); -} - -static void -dump_udccs0(const char *label) -{ - u32 udccs0 = readl(&UDC_REGS->udccs[0]); - - debug("%s %s %02X =%s%s%s%s%s%s%s%s\n", - label, state_name[the_controller->ep0state], udccs0, - (udccs0 & UDCCS0_SA) ? " sa" : "", - (udccs0 & UDCCS0_RNE) ? " rne" : "", - (udccs0 & UDCCS0_FST) ? " fst" : "", - (udccs0 & UDCCS0_SST) ? " sst" : "", - (udccs0 & UDCCS0_DRWF) ? " dwrf" : "", - (udccs0 & UDCCS0_FTF) ? " ftf" : "", - (udccs0 & UDCCS0_IPR) ? " ipr" : "", - (udccs0 & UDCCS0_OPR) ? " opr" : ""); -} - -static void -dump_state(struct pxa25x_udc *dev) -{ - u32 tmp; - unsigned i; - - debug("%s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n", - state_name[dev->ep0state], - readl(&UDC_REGS->uicr1), readl(&UDC_REGS->uicr0), - readl(&UDC_REGS->usir1), readl(&UDC_REGS->usir0), - readl(&UDC_REGS->ufnrh), readl(&UDC_REGS->ufnrl)); - dump_udccr("udccr"); - if (dev->has_cfr) { - tmp = readl(&UDC_REGS->udccfr); - debug("udccfr %02X =%s%s\n", tmp, - (tmp & UDCCFR_AREN) ? " aren" : "", - (tmp & UDCCFR_ACM) ? " acm" : ""); - } - - if (!dev->driver) { - debug("no gadget driver bound\n"); - return; - } else - debug("ep0 driver '%s'\n", "ether"); - - dump_udccs0("udccs0"); - debug("ep0 IN %lu/%lu, OUT %lu/%lu\n", - dev->stats.write.bytes, dev->stats.write.ops, - dev->stats.read.bytes, dev->stats.read.ops); - - for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) { - if (dev->ep[i].desc == NULL) - continue; - debug("udccs%d = %02x\n", i, *dev->ep->reg_udccs); - } -} - -#else /* DEBUG */ - -static inline void dump_udccr(const char *label) { } -static inline void dump_udccs0(const char *label) { } -static inline void dump_state(struct pxa25x_udc *dev) { } - -#endif /* DEBUG */ - -/* - * --------------------------------------------------------------------------- - * endpoint related parts of the api to the usb controller hardware, - * used by gadget driver; and the inner talker-to-hardware core. - * --------------------------------------------------------------------------- - */ - -static void pxa25x_ep_fifo_flush(struct usb_ep *ep); -static void nuke(struct pxa25x_ep *, int status); - -/* one GPIO should control a D+ pullup, so host sees this device (or not) */ -static void pullup_off(void) -{ - struct pxa2xx_udc_mach_info *mach = the_controller->mach; - - if (mach->udc_command) - mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); -} - -static void pullup_on(void) -{ - struct pxa2xx_udc_mach_info *mach = the_controller->mach; - - if (mach->udc_command) - mach->udc_command(PXA2XX_UDC_CMD_CONNECT); -} - -static void pio_irq_enable(int bEndpointAddress) -{ - bEndpointAddress &= 0xf; - if (bEndpointAddress < 8) { - clrbits_le32(&the_controller->regs->uicr0, - 1 << bEndpointAddress); - } else { - bEndpointAddress -= 8; - clrbits_le32(&the_controller->regs->uicr1, - 1 << bEndpointAddress); - } -} - -static void pio_irq_disable(int bEndpointAddress) -{ - bEndpointAddress &= 0xf; - if (bEndpointAddress < 8) { - setbits_le32(&the_controller->regs->uicr0, - 1 << bEndpointAddress); - } else { - bEndpointAddress -= 8; - setbits_le32(&the_controller->regs->uicr1, - 1 << bEndpointAddress); - } -} - -static inline void udc_set_mask_UDCCR(int mask) -{ - /* - * The UDCCR reg contains mask and interrupt status bits, - * so using '|=' isn't safe as it may ack an interrupt. - */ - const uint32_t mask_bits = UDCCR_REM | UDCCR_SRM | UDCCR_UDE; - - mask &= mask_bits; - clrsetbits_le32(&the_controller->regs->udccr, ~mask_bits, mask); -} - -static inline void udc_clear_mask_UDCCR(int mask) -{ - const uint32_t mask_bits = UDCCR_REM | UDCCR_SRM | UDCCR_UDE; - - mask = ~mask & mask_bits; - clrbits_le32(&the_controller->regs->udccr, ~mask); -} - -static inline void udc_ack_int_UDCCR(int mask) -{ - const uint32_t mask_bits = UDCCR_REM | UDCCR_SRM | UDCCR_UDE; - - mask &= ~mask_bits; - clrsetbits_le32(&the_controller->regs->udccr, ~mask_bits, mask); -} - -/* - * endpoint enable/disable - * - * we need to verify the descriptors used to enable endpoints. since pxa25x - * endpoint configurations are fixed, and are pretty much always enabled, - * there's not a lot to manage here. - * - * because pxa25x can't selectively initialize bulk (or interrupt) endpoints, - * (resetting endpoint halt and toggle), SET_INTERFACE is unusable except - * for a single interface (with only the default altsetting) and for gadget - * drivers that don't halt endpoints (not reset by set_interface). that also - * means that if you use ISO, you must violate the USB spec rule that all - * iso endpoints must be in non-default altsettings. - */ -static int pxa25x_ep_enable(struct usb_ep *_ep, - const struct usb_endpoint_descriptor *desc) -{ - struct pxa25x_ep *ep; - struct pxa25x_udc *dev; - - ep = container_of(_ep, struct pxa25x_ep, ep); - if (!_ep || !desc || ep->desc || _ep->name == ep0name - || desc->bDescriptorType != USB_DT_ENDPOINT - || ep->bEndpointAddress != desc->bEndpointAddress - || ep->fifo_size < - le16_to_cpu(get_unaligned(&desc->wMaxPacketSize))) { - printf("%s, bad ep or descriptor\n", __func__); - return -EINVAL; - } - - /* xfer types must match, except that interrupt ~= bulk */ - if (ep->bmAttributes != desc->bmAttributes - && ep->bmAttributes != USB_ENDPOINT_XFER_BULK - && desc->bmAttributes != USB_ENDPOINT_XFER_INT) { - printf("%s, %s type mismatch\n", __func__, _ep->name); - return -EINVAL; - } - - /* hardware _could_ do smaller, but driver doesn't */ - if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK - && le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)) - != BULK_FIFO_SIZE) - || !get_unaligned(&desc->wMaxPacketSize)) { - printf("%s, bad %s maxpacket\n", __func__, _ep->name); - return -ERANGE; - } - - dev = ep->dev; - if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { - printf("%s, bogus device state\n", __func__); - return -ESHUTDOWN; - } - - ep->desc = desc; - ep->stopped = 0; - ep->pio_irqs = 0; - ep->ep.maxpacket = le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)); - - /* flush fifo (mostly for OUT buffers) */ - pxa25x_ep_fifo_flush(_ep); - - /* ... reset halt state too, if we could ... */ - - debug("enabled %s\n", _ep->name); - return 0; -} - -static int pxa25x_ep_disable(struct usb_ep *_ep) -{ - struct pxa25x_ep *ep; - unsigned long flags; - - ep = container_of(_ep, struct pxa25x_ep, ep); - if (!_ep || !ep->desc) { - printf("%s, %s not enabled\n", __func__, - _ep ? ep->ep.name : NULL); - return -EINVAL; - } - local_irq_save(flags); - - nuke(ep, -ESHUTDOWN); - - /* flush fifo (mostly for IN buffers) */ - pxa25x_ep_fifo_flush(_ep); - - ep->desc = NULL; - ep->stopped = 1; - - local_irq_restore(flags); - debug("%s disabled\n", _ep->name); - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* - * for the pxa25x, these can just wrap kmalloc/kfree. gadget drivers - * must still pass correctly initialized endpoints, since other controller - * drivers may care about how it's currently set up (dma issues etc). - */ - -/* - * pxa25x_ep_alloc_request - allocate a request data structure - */ -static struct usb_request * -pxa25x_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) -{ - struct pxa25x_request *req; - - req = kzalloc(sizeof(*req), gfp_flags); - if (!req) - return NULL; - - INIT_LIST_HEAD(&req->queue); - return &req->req; -} - - -/* - * pxa25x_ep_free_request - deallocate a request data structure - */ -static void -pxa25x_ep_free_request(struct usb_ep *_ep, struct usb_request *_req) -{ - struct pxa25x_request *req; - - req = container_of(_req, struct pxa25x_request, req); - WARN_ON(!list_empty(&req->queue)); - kfree(req); -} - -/*-------------------------------------------------------------------------*/ - -/* - * done - retire a request; caller blocked irqs - */ -static void done(struct pxa25x_ep *ep, struct pxa25x_request *req, int status) -{ - unsigned stopped = ep->stopped; - - list_del_init(&req->queue); - - if (likely(req->req.status == -EINPROGRESS)) - req->req.status = status; - else - status = req->req.status; - - if (status && status != -ESHUTDOWN) - debug("complete %s req %p stat %d len %u/%u\n", - ep->ep.name, &req->req, status, - req->req.actual, req->req.length); - - /* don't modify queue heads during completion callback */ - ep->stopped = 1; - req->req.complete(&ep->ep, &req->req); - ep->stopped = stopped; -} - - -static inline void ep0_idle(struct pxa25x_udc *dev) -{ - dev->ep0state = EP0_IDLE; -} - -static int -write_packet(u32 *uddr, struct pxa25x_request *req, unsigned max) -{ - u8 *buf; - unsigned length, count; - - debug("%s(): uddr %p\n", __func__, uddr); - - buf = req->req.buf + req->req.actual; - prefetch(buf); - - /* how big will this packet be? */ - length = min(req->req.length - req->req.actual, max); - req->req.actual += length; - - count = length; - while (likely(count--)) - writeb(*buf++, uddr); - - return length; -} - -/* - * write to an IN endpoint fifo, as many packets as possible. - * irqs will use this to write the rest later. - * caller guarantees at least one packet buffer is ready (or a zlp). - */ -static int -write_fifo(struct pxa25x_ep *ep, struct pxa25x_request *req) -{ - unsigned max; - - max = le16_to_cpu(get_unaligned(&ep->desc->wMaxPacketSize)); - do { - unsigned count; - int is_last, is_short; - - count = write_packet(ep->reg_uddr, req, max); - - /* last packet is usually short (or a zlp) */ - if (unlikely(count != max)) - is_last = is_short = 1; - else { - if (likely(req->req.length != req->req.actual) - || req->req.zero) - is_last = 0; - else - is_last = 1; - /* interrupt/iso maxpacket may not fill the fifo */ - is_short = unlikely(max < ep->fifo_size); - } - - debug_cond(NOISY, "wrote %s %d bytes%s%s %d left %p\n", - ep->ep.name, count, - is_last ? "/L" : "", is_short ? "/S" : "", - req->req.length - req->req.actual, req); - - /* - * let loose that packet. maybe try writing another one, - * double buffering might work. TSP, TPC, and TFS - * bit values are the same for all normal IN endpoints. - */ - writel(UDCCS_BI_TPC, ep->reg_udccs); - if (is_short) - writel(UDCCS_BI_TSP, ep->reg_udccs); - - /* requests complete when all IN data is in the FIFO */ - if (is_last) { - done(ep, req, 0); - if (list_empty(&ep->queue)) - pio_irq_disable(ep->bEndpointAddress); - return 1; - } - - /* - * TODO experiment: how robust can fifo mode tweaking be? - * double buffering is off in the default fifo mode, which - * prevents TFS from being set here. - */ - - } while (readl(ep->reg_udccs) & UDCCS_BI_TFS); - return 0; -} - -/* - * caller asserts req->pending (ep0 irq status nyet cleared); starts - * ep0 data stage. these chips want very simple state transitions. - */ -static inline -void ep0start(struct pxa25x_udc *dev, u32 flags, const char *tag) -{ - writel(flags|UDCCS0_SA|UDCCS0_OPR, &dev->regs->udccs[0]); - writel(USIR0_IR0, &dev->regs->usir0); - dev->req_pending = 0; - debug_cond(NOISY, "%s() %s, udccs0: %02x/%02x usir: %X.%X\n", - __func__, tag, readl(&dev->regs->udccs[0]), flags, - readl(&dev->regs->usir1), readl(&dev->regs->usir0)); -} - -static int -write_ep0_fifo(struct pxa25x_ep *ep, struct pxa25x_request *req) -{ - unsigned count; - int is_short; - - count = write_packet(&ep->dev->regs->uddr0, req, EP0_FIFO_SIZE); - ep->dev->stats.write.bytes += count; - - /* last packet "must be" short (or a zlp) */ - is_short = (count != EP0_FIFO_SIZE); - - debug_cond(NOISY, "ep0in %d bytes %d left %p\n", count, - req->req.length - req->req.actual, req); - - if (unlikely(is_short)) { - if (ep->dev->req_pending) - ep0start(ep->dev, UDCCS0_IPR, "short IN"); - else - writel(UDCCS0_IPR, &ep->dev->regs->udccs[0]); - - count = req->req.length; - done(ep, req, 0); - ep0_idle(ep->dev); - - /* - * This seems to get rid of lost status irqs in some cases: - * host responds quickly, or next request involves config - * change automagic, or should have been hidden, or ... - * - * FIXME get rid of all udelays possible... - */ - if (count >= EP0_FIFO_SIZE) { - count = 100; - do { - if ((readl(&ep->dev->regs->udccs[0]) & - UDCCS0_OPR) != 0) { - /* clear OPR, generate ack */ - writel(UDCCS0_OPR, - &ep->dev->regs->udccs[0]); - break; - } - count--; - udelay(1); - } while (count); - } - } else if (ep->dev->req_pending) - ep0start(ep->dev, 0, "IN"); - - return is_short; -} - - -/* - * read_fifo - unload packet(s) from the fifo we use for usb OUT - * transfers and put them into the request. caller should have made - * sure there's at least one packet ready. - * - * returns true if the request completed because of short packet or the - * request buffer having filled (and maybe overran till end-of-packet). - */ -static int -read_fifo(struct pxa25x_ep *ep, struct pxa25x_request *req) -{ - u32 udccs; - u8 *buf; - unsigned bufferspace, count, is_short; - - for (;;) { - /* - * make sure there's a packet in the FIFO. - * UDCCS_{BO,IO}_RPC are all the same bit value. - * UDCCS_{BO,IO}_RNE are all the same bit value. - */ - udccs = readl(ep->reg_udccs); - if (unlikely((udccs & UDCCS_BO_RPC) == 0)) - break; - buf = req->req.buf + req->req.actual; - prefetchw(buf); - bufferspace = req->req.length - req->req.actual; - - /* read all bytes from this packet */ - if (likely(udccs & UDCCS_BO_RNE)) { - count = 1 + (0x0ff & readl(ep->reg_ubcr)); - req->req.actual += min(count, bufferspace); - } else /* zlp */ - count = 0; - is_short = (count < ep->ep.maxpacket); - debug_cond(NOISY, "read %s %02x, %d bytes%s req %p %d/%d\n", - ep->ep.name, udccs, count, - is_short ? "/S" : "", - req, req->req.actual, req->req.length); - while (likely(count-- != 0)) { - u8 byte = readb(ep->reg_uddr); - - if (unlikely(bufferspace == 0)) { - /* - * this happens when the driver's buffer - * is smaller than what the host sent. - * discard the extra data. - */ - if (req->req.status != -EOVERFLOW) - printf("%s overflow %d\n", - ep->ep.name, count); - req->req.status = -EOVERFLOW; - } else { - *buf++ = byte; - bufferspace--; - } - } - writel(UDCCS_BO_RPC, ep->reg_udccs); - /* RPC/RSP/RNE could now reflect the other packet buffer */ - - /* iso is one request per packet */ - if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) { - if (udccs & UDCCS_IO_ROF) - req->req.status = -EHOSTUNREACH; - /* more like "is_done" */ - is_short = 1; - } - - /* completion */ - if (is_short || req->req.actual == req->req.length) { - done(ep, req, 0); - if (list_empty(&ep->queue)) - pio_irq_disable(ep->bEndpointAddress); - return 1; - } - - /* finished that packet. the next one may be waiting... */ - } - return 0; -} - -/* - * special ep0 version of the above. no UBCR0 or double buffering; status - * handshaking is magic. most device protocols don't need control-OUT. - * CDC vendor commands (and RNDIS), mass storage CB/CBI, and some other - * protocols do use them. - */ -static int -read_ep0_fifo(struct pxa25x_ep *ep, struct pxa25x_request *req) -{ - u8 *buf, byte; - unsigned bufferspace; - - buf = req->req.buf + req->req.actual; - bufferspace = req->req.length - req->req.actual; - - while (readl(&ep->dev->regs->udccs[0]) & UDCCS0_RNE) { - byte = (u8)readb(&ep->dev->regs->uddr0); - - if (unlikely(bufferspace == 0)) { - /* - * this happens when the driver's buffer - * is smaller than what the host sent. - * discard the extra data. - */ - if (req->req.status != -EOVERFLOW) - printf("%s overflow\n", ep->ep.name); - req->req.status = -EOVERFLOW; - } else { - *buf++ = byte; - req->req.actual++; - bufferspace--; - } - } - - writel(UDCCS0_OPR | UDCCS0_IPR, &ep->dev->regs->udccs[0]); - - /* completion */ - if (req->req.actual >= req->req.length) - return 1; - - /* finished that packet. the next one may be waiting... */ - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static int -pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) -{ - struct pxa25x_request *req; - struct pxa25x_ep *ep; - struct pxa25x_udc *dev; - unsigned long flags; - - req = container_of(_req, struct pxa25x_request, req); - if (unlikely(!_req || !_req->complete || !_req->buf - || !list_empty(&req->queue))) { - printf("%s, bad params\n", __func__); - return -EINVAL; - } - - ep = container_of(_ep, struct pxa25x_ep, ep); - if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { - printf("%s, bad ep\n", __func__); - return -EINVAL; - } - - dev = ep->dev; - if (unlikely(!dev->driver - || dev->gadget.speed == USB_SPEED_UNKNOWN)) { - printf("%s, bogus device state\n", __func__); - return -ESHUTDOWN; - } - - /* - * iso is always one packet per request, that's the only way - * we can report per-packet status. that also helps with dma. - */ - if (unlikely(ep->bmAttributes == USB_ENDPOINT_XFER_ISOC - && req->req.length > - le16_to_cpu(get_unaligned(&ep->desc->wMaxPacketSize)))) - return -EMSGSIZE; - - debug_cond(NOISY, "%s queue req %p, len %d buf %p\n", - _ep->name, _req, _req->length, _req->buf); - - local_irq_save(flags); - - _req->status = -EINPROGRESS; - _req->actual = 0; - - /* kickstart this i/o queue? */ - if (list_empty(&ep->queue) && !ep->stopped) { - if (ep->desc == NULL/* ep0 */) { - unsigned length = _req->length; - - switch (dev->ep0state) { - case EP0_IN_DATA_PHASE: - dev->stats.write.ops++; - if (write_ep0_fifo(ep, req)) - req = NULL; - break; - - case EP0_OUT_DATA_PHASE: - dev->stats.read.ops++; - /* messy ... */ - if (dev->req_config) { - debug("ep0 config ack%s\n", - dev->has_cfr ? "" : " raced"); - if (dev->has_cfr) - writel(UDCCFR_AREN|UDCCFR_ACM - |UDCCFR_MB1, - &ep->dev->regs->udccfr); - done(ep, req, 0); - dev->ep0state = EP0_END_XFER; - local_irq_restore(flags); - return 0; - } - if (dev->req_pending) - ep0start(dev, UDCCS0_IPR, "OUT"); - if (length == 0 || - ((readl( - &ep->dev->regs->udccs[0]) - & UDCCS0_RNE) != 0 - && read_ep0_fifo(ep, req))) { - ep0_idle(dev); - done(ep, req, 0); - req = NULL; - } - break; - - default: - printf("ep0 i/o, odd state %d\n", - dev->ep0state); - local_irq_restore(flags); - return -EL2HLT; - } - /* can the FIFO can satisfy the request immediately? */ - } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) { - if ((readl(ep->reg_udccs) & UDCCS_BI_TFS) != 0 - && write_fifo(ep, req)) - req = NULL; - } else if ((readl(ep->reg_udccs) & UDCCS_BO_RFS) != 0 - && read_fifo(ep, req)) { - req = NULL; - } - - if (likely(req && ep->desc)) - pio_irq_enable(ep->bEndpointAddress); - } - - /* pio or dma irq handler advances the queue. */ - if (likely(req != NULL)) - list_add_tail(&req->queue, &ep->queue); - local_irq_restore(flags); - - return 0; -} - - -/* - * nuke - dequeue ALL requests - */ -static void nuke(struct pxa25x_ep *ep, int status) -{ - struct pxa25x_request *req; - - /* called with irqs blocked */ - while (!list_empty(&ep->queue)) { - req = list_entry(ep->queue.next, - struct pxa25x_request, - queue); - done(ep, req, status); - } - if (ep->desc) - pio_irq_disable(ep->bEndpointAddress); -} - - -/* dequeue JUST ONE request */ -static int pxa25x_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) -{ - struct pxa25x_ep *ep; - struct pxa25x_request *req; - unsigned long flags; - - ep = container_of(_ep, struct pxa25x_ep, ep); - if (!_ep || ep->ep.name == ep0name) - return -EINVAL; - - local_irq_save(flags); - - /* make sure it's actually queued on this endpoint */ - list_for_each_entry(req, &ep->queue, queue) { - if (&req->req == _req) - break; - } - if (&req->req != _req) { - local_irq_restore(flags); - return -EINVAL; - } - - done(ep, req, -ECONNRESET); - - local_irq_restore(flags); - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value) -{ - struct pxa25x_ep *ep; - unsigned long flags; - - ep = container_of(_ep, struct pxa25x_ep, ep); - if (unlikely(!_ep - || (!ep->desc && ep->ep.name != ep0name)) - || ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) { - printf("%s, bad ep\n", __func__); - return -EINVAL; - } - if (value == 0) { - /* - * this path (reset toggle+halt) is needed to implement - * SET_INTERFACE on normal hardware. but it can't be - * done from software on the PXA UDC, and the hardware - * forgets to do it as part of SET_INTERFACE automagic. - */ - printf("only host can clear %s halt\n", _ep->name); - return -EROFS; - } - - local_irq_save(flags); - - if ((ep->bEndpointAddress & USB_DIR_IN) != 0 - && ((readl(ep->reg_udccs) & UDCCS_BI_TFS) == 0 - || !list_empty(&ep->queue))) { - local_irq_restore(flags); - return -EAGAIN; - } - - /* FST bit is the same for control, bulk in, bulk out, interrupt in */ - writel(UDCCS_BI_FST|UDCCS_BI_FTF, ep->reg_udccs); - - /* ep0 needs special care */ - if (!ep->desc) { - start_watchdog(ep->dev); - ep->dev->req_pending = 0; - ep->dev->ep0state = EP0_STALL; - - /* and bulk/intr endpoints like dropping stalls too */ - } else { - unsigned i; - for (i = 0; i < 1000; i += 20) { - if (readl(ep->reg_udccs) & UDCCS_BI_SST) - break; - udelay(20); - } - } - local_irq_restore(flags); - - debug("%s halt\n", _ep->name); - return 0; -} - -static int pxa25x_ep_fifo_status(struct usb_ep *_ep) -{ - struct pxa25x_ep *ep; - - ep = container_of(_ep, struct pxa25x_ep, ep); - if (!_ep) { - printf("%s, bad ep\n", __func__); - return -ENODEV; - } - /* pxa can't report unclaimed bytes from IN fifos */ - if ((ep->bEndpointAddress & USB_DIR_IN) != 0) - return -EOPNOTSUPP; - if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN - || (readl(ep->reg_udccs) & UDCCS_BO_RFS) == 0) - return 0; - else - return (readl(ep->reg_ubcr) & 0xfff) + 1; -} - -static void pxa25x_ep_fifo_flush(struct usb_ep *_ep) -{ - struct pxa25x_ep *ep; - - ep = container_of(_ep, struct pxa25x_ep, ep); - if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) { - printf("%s, bad ep\n", __func__); - return; - } - - /* toggle and halt bits stay unchanged */ - - /* for OUT, just read and discard the FIFO contents. */ - if ((ep->bEndpointAddress & USB_DIR_IN) == 0) { - while (((readl(ep->reg_udccs)) & UDCCS_BO_RNE) != 0) - (void)readb(ep->reg_uddr); - return; - } - - /* most IN status is the same, but ISO can't stall */ - writel(UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR - | (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC - ? 0 : UDCCS_BI_SST), ep->reg_udccs); -} - - -static struct usb_ep_ops pxa25x_ep_ops = { - .enable = pxa25x_ep_enable, - .disable = pxa25x_ep_disable, - - .alloc_request = pxa25x_ep_alloc_request, - .free_request = pxa25x_ep_free_request, - - .queue = pxa25x_ep_queue, - .dequeue = pxa25x_ep_dequeue, - - .set_halt = pxa25x_ep_set_halt, - .fifo_status = pxa25x_ep_fifo_status, - .fifo_flush = pxa25x_ep_fifo_flush, -}; - - -/* --------------------------------------------------------------------------- - * device-scoped parts of the api to the usb controller hardware - * --------------------------------------------------------------------------- - */ - -static int pxa25x_udc_get_frame(struct usb_gadget *_gadget) -{ - return ((readl(&the_controller->regs->ufnrh) & 0x07) << 8) | - (readl(&the_controller->regs->ufnrl) & 0xff); -} - -static int pxa25x_udc_wakeup(struct usb_gadget *_gadget) -{ - /* host may not have enabled remote wakeup */ - if ((readl(&the_controller->regs->udccs[0]) & UDCCS0_DRWF) == 0) - return -EHOSTUNREACH; - udc_set_mask_UDCCR(UDCCR_RSM); - return 0; -} - -static void stop_activity(struct pxa25x_udc *, struct usb_gadget_driver *); -static void udc_enable(struct pxa25x_udc *); -static void udc_disable(struct pxa25x_udc *); - -/* - * We disable the UDC -- and its 48 MHz clock -- whenever it's not - * in active use. - */ -static int pullup(struct pxa25x_udc *udc) -{ - if (udc->pullup) - pullup_on(); - else - pullup_off(); - - - int is_active = udc->pullup; - if (is_active) { - if (!udc->active) { - udc->active = 1; - udc_enable(udc); - } - } else { - if (udc->active) { - if (udc->gadget.speed != USB_SPEED_UNKNOWN) - stop_activity(udc, udc->driver); - udc_disable(udc); - udc->active = 0; - } - - } - return 0; -} - -/* VBUS reporting logically comes from a transceiver */ -static int pxa25x_udc_vbus_session(struct usb_gadget *_gadget, int is_active) -{ - struct pxa25x_udc *udc; - - udc = container_of(_gadget, struct pxa25x_udc, gadget); - printf("vbus %s\n", is_active ? "supplied" : "inactive"); - pullup(udc); - return 0; -} - -/* drivers may have software control over D+ pullup */ -static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active) -{ - struct pxa25x_udc *udc; - - udc = container_of(_gadget, struct pxa25x_udc, gadget); - - /* not all boards support pullup control */ - if (!udc->mach->udc_command) - return -EOPNOTSUPP; - - udc->pullup = (is_active != 0); - pullup(udc); - return 0; -} - -/* - * boards may consume current from VBUS, up to 100-500mA based on config. - * the 500uA suspend ceiling means that exclusively vbus-powered PXA designs - * violate USB specs. - */ -static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) -{ - return -EOPNOTSUPP; -} - -static const struct usb_gadget_ops pxa25x_udc_ops = { - .get_frame = pxa25x_udc_get_frame, - .wakeup = pxa25x_udc_wakeup, - .vbus_session = pxa25x_udc_vbus_session, - .pullup = pxa25x_udc_pullup, - .vbus_draw = pxa25x_udc_vbus_draw, -}; - -/*-------------------------------------------------------------------------*/ - -/* - * udc_disable - disable USB device controller - */ -static void udc_disable(struct pxa25x_udc *dev) -{ - /* block all irqs */ - udc_set_mask_UDCCR(UDCCR_SRM|UDCCR_REM); - writel(0xff, &dev->regs->uicr0); - writel(0xff, &dev->regs->uicr1); - writel(UFNRH_SIM, &dev->regs->ufnrh); - - /* if hardware supports it, disconnect from usb */ - pullup_off(); - - udc_clear_mask_UDCCR(UDCCR_UDE); - - ep0_idle(dev); - dev->gadget.speed = USB_SPEED_UNKNOWN; -} - -/* - * udc_reinit - initialize software state - */ -static void udc_reinit(struct pxa25x_udc *dev) -{ - u32 i; - - /* device/ep0 records init */ - INIT_LIST_HEAD(&dev->gadget.ep_list); - INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); - dev->ep0state = EP0_IDLE; - - /* basic endpoint records init */ - for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) { - struct pxa25x_ep *ep = &dev->ep[i]; - - if (i != 0) - list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); - - ep->desc = NULL; - ep->stopped = 0; - INIT_LIST_HEAD(&ep->queue); - ep->pio_irqs = 0; - } - - /* the rest was statically initialized, and is read-only */ -} - -/* - * until it's enabled, this UDC should be completely invisible - * to any USB host. - */ -static void udc_enable(struct pxa25x_udc *dev) -{ - debug("udc: enabling udc\n"); - - udc_clear_mask_UDCCR(UDCCR_UDE); - - /* - * Try to clear these bits before we enable the udc. - * Do not touch reset ack bit, we would take care of it in - * interrupt handle routine - */ - udc_ack_int_UDCCR(UDCCR_SUSIR|UDCCR_RESIR); - - ep0_idle(dev); - dev->gadget.speed = USB_SPEED_UNKNOWN; - dev->stats.irqs = 0; - - /* - * sequence taken from chapter 12.5.10, PXA250 AppProcDevManual: - * - enable UDC - * - if RESET is already in progress, ack interrupt - * - unmask reset interrupt - */ - udc_set_mask_UDCCR(UDCCR_UDE); - if (!(readl(&dev->regs->udccr) & UDCCR_UDA)) - udc_ack_int_UDCCR(UDCCR_RSTIR); - - if (dev->has_cfr /* UDC_RES2 is defined */) { - /* - * pxa255 (a0+) can avoid a set_config race that could - * prevent gadget drivers from configuring correctly - */ - writel(UDCCFR_ACM | UDCCFR_MB1, &dev->regs->udccfr); - } - - /* enable suspend/resume and reset irqs */ - udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM); - - /* enable ep0 irqs */ - clrbits_le32(&dev->regs->uicr0, UICR0_IM0); - - /* if hardware supports it, pullup D+ and wait for reset */ - pullup_on(); -} - -static inline void clear_ep_state(struct pxa25x_udc *dev) -{ - unsigned i; - - /* - * hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint - * fifos, and pending transactions mustn't be continued in any case. - */ - for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) - nuke(&dev->ep[i], -ECONNABORTED); -} - -static void handle_ep0(struct pxa25x_udc *dev) -{ - u32 udccs0 = readl(&dev->regs->udccs[0]); - struct pxa25x_ep *ep = &dev->ep[0]; - struct pxa25x_request *req; - union { - struct usb_ctrlrequest r; - u8 raw[8]; - u32 word[2]; - } u; - - if (list_empty(&ep->queue)) - req = NULL; - else - req = list_entry(ep->queue.next, struct pxa25x_request, queue); - - /* clear stall status */ - if (udccs0 & UDCCS0_SST) { - nuke(ep, -EPIPE); - writel(UDCCS0_SST, &dev->regs->udccs[0]); - stop_watchdog(dev); - ep0_idle(dev); - } - - /* previous request unfinished? non-error iff back-to-back ... */ - if ((udccs0 & UDCCS0_SA) != 0 && dev->ep0state != EP0_IDLE) { - nuke(ep, 0); - stop_watchdog(dev); - ep0_idle(dev); - } - - switch (dev->ep0state) { - case EP0_IDLE: - /* late-breaking status? */ - udccs0 = readl(&dev->regs->udccs[0]); - - /* start control request? */ - if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE)) - == (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))) { - int i; - - nuke(ep, -EPROTO); - - /* read SETUP packet */ - for (i = 0; i < 8; i++) { - if (unlikely(!(readl(&dev->regs->udccs[0]) & - UDCCS0_RNE))) { -bad_setup: - debug("SETUP %d!\n", i); - goto stall; - } - u.raw[i] = (u8)readb(&dev->regs->uddr0); - } - if (unlikely((readl(&dev->regs->udccs[0]) & - UDCCS0_RNE) != 0)) - goto bad_setup; - -got_setup: - debug("SETUP %02x.%02x v%04x i%04x l%04x\n", - u.r.bRequestType, u.r.bRequest, - le16_to_cpu(u.r.wValue), - le16_to_cpu(u.r.wIndex), - le16_to_cpu(u.r.wLength)); - - /* cope with automagic for some standard requests. */ - dev->req_std = (u.r.bRequestType & USB_TYPE_MASK) - == USB_TYPE_STANDARD; - dev->req_config = 0; - dev->req_pending = 1; - switch (u.r.bRequest) { - /* hardware restricts gadget drivers here! */ - case USB_REQ_SET_CONFIGURATION: - debug("GOT SET_CONFIGURATION\n"); - if (u.r.bRequestType == USB_RECIP_DEVICE) { - /* - * reflect hardware's automagic - * up to the gadget driver. - */ -config_change: - dev->req_config = 1; - clear_ep_state(dev); - /* - * if !has_cfr, there's no synch - * else use AREN (later) not SA|OPR - * USIR0_IR0 acts edge sensitive - */ - } - break; - /* ... and here, even more ... */ - case USB_REQ_SET_INTERFACE: - if (u.r.bRequestType == USB_RECIP_INTERFACE) { - /* - * udc hardware is broken by design: - * - altsetting may only be zero; - * - hw resets all interfaces' eps; - * - ep reset doesn't include halt(?). - */ - printf("broken set_interface (%d/%d)\n", - le16_to_cpu(u.r.wIndex), - le16_to_cpu(u.r.wValue)); - goto config_change; - } - break; - /* hardware was supposed to hide this */ - case USB_REQ_SET_ADDRESS: - debug("GOT SET ADDRESS\n"); - if (u.r.bRequestType == USB_RECIP_DEVICE) { - ep0start(dev, 0, "address"); - return; - } - break; - } - - if (u.r.bRequestType & USB_DIR_IN) - dev->ep0state = EP0_IN_DATA_PHASE; - else - dev->ep0state = EP0_OUT_DATA_PHASE; - - i = dev->driver->setup(&dev->gadget, &u.r); - if (i < 0) { - /* hardware automagic preventing STALL... */ - if (dev->req_config) { - /* - * hardware sometimes neglects to tell - * tell us about config change events, - * so later ones may fail... - */ - printf("config change %02x fail %d?\n", - u.r.bRequest, i); - return; - /* - * TODO experiment: if has_cfr, - * hardware didn't ACK; maybe we - * could actually STALL! - */ - } - if (0) { -stall: - /* uninitialized when goto stall */ - i = 0; - } - debug("protocol STALL, " - "%02x err %d\n", - readl(&dev->regs->udccs[0]), i); - - /* - * the watchdog timer helps deal with cases - * where udc seems to clear FST wrongly, and - * then NAKs instead of STALLing. - */ - ep0start(dev, UDCCS0_FST|UDCCS0_FTF, "stall"); - start_watchdog(dev); - dev->ep0state = EP0_STALL; - - /* deferred i/o == no response yet */ - } else if (dev->req_pending) { - if (likely(dev->ep0state == EP0_IN_DATA_PHASE - || dev->req_std || u.r.wLength)) - ep0start(dev, 0, "defer"); - else - ep0start(dev, UDCCS0_IPR, "defer/IPR"); - } - - /* expect at least one data or status stage irq */ - return; - - } else if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA)) - == (UDCCS0_OPR|UDCCS0_SA))) { - unsigned i; - - /* - * pxa210/250 erratum 131 for B0/B1 says RNE lies. - * still observed on a pxa255 a0. - */ - debug("e131\n"); - nuke(ep, -EPROTO); - - /* read SETUP data, but don't trust it too much */ - for (i = 0; i < 8; i++) - u.raw[i] = (u8)readb(&dev->regs->uddr0); - if ((u.r.bRequestType & USB_RECIP_MASK) - > USB_RECIP_OTHER) - goto stall; - if (u.word[0] == 0 && u.word[1] == 0) - goto stall; - goto got_setup; - } else { - /* - * some random early IRQ: - * - we acked FST - * - IPR cleared - * - OPR got set, without SA (likely status stage) - */ - debug("random IRQ %X %X\n", udccs0, - readl(&dev->regs->udccs[0])); - writel(udccs0 & (UDCCS0_SA|UDCCS0_OPR), - &dev->regs->udccs[0]); - } - break; - case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR etc */ - if (udccs0 & UDCCS0_OPR) { - debug("ep0in premature status\n"); - if (req) - done(ep, req, 0); - ep0_idle(dev); - } else /* irq was IPR clearing */ { - if (req) { - debug("next ep0 in packet\n"); - /* this IN packet might finish the request */ - (void) write_ep0_fifo(ep, req); - } /* else IN token before response was written */ - } - break; - case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR etc */ - if (udccs0 & UDCCS0_OPR) { - if (req) { - /* this OUT packet might finish the request */ - if (read_ep0_fifo(ep, req)) - done(ep, req, 0); - /* else more OUT packets expected */ - } /* else OUT token before read was issued */ - } else /* irq was IPR clearing */ { - debug("ep0out premature status\n"); - if (req) - done(ep, req, 0); - ep0_idle(dev); - } - break; - case EP0_END_XFER: - if (req) - done(ep, req, 0); - /* - * ack control-IN status (maybe in-zlp was skipped) - * also appears after some config change events. - */ - if (udccs0 & UDCCS0_OPR) - writel(UDCCS0_OPR, &dev->regs->udccs[0]); - ep0_idle(dev); - break; - case EP0_STALL: - writel(UDCCS0_FST, &dev->regs->udccs[0]); - break; - } - - writel(USIR0_IR0, &dev->regs->usir0); -} - -static void handle_ep(struct pxa25x_ep *ep) -{ - struct pxa25x_request *req; - int is_in = ep->bEndpointAddress & USB_DIR_IN; - int completed; - u32 udccs, tmp; - - do { - completed = 0; - if (likely(!list_empty(&ep->queue))) - req = list_entry(ep->queue.next, - struct pxa25x_request, queue); - else - req = NULL; - - /* TODO check FST handling */ - - udccs = readl(ep->reg_udccs); - if (unlikely(is_in)) { /* irq from TPC, SST, or (ISO) TUR */ - tmp = UDCCS_BI_TUR; - if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK)) - tmp |= UDCCS_BI_SST; - tmp &= udccs; - if (likely(tmp)) - writel(tmp, ep->reg_udccs); - if (req && likely((udccs & UDCCS_BI_TFS) != 0)) - completed = write_fifo(ep, req); - - } else { /* irq from RPC (or for ISO, ROF) */ - if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK)) - tmp = UDCCS_BO_SST | UDCCS_BO_DME; - else - tmp = UDCCS_IO_ROF | UDCCS_IO_DME; - tmp &= udccs; - if (likely(tmp)) - writel(tmp, ep->reg_udccs); - - /* fifos can hold packets, ready for reading... */ - if (likely(req)) - completed = read_fifo(ep, req); - else - pio_irq_disable(ep->bEndpointAddress); - } - ep->pio_irqs++; - } while (completed); -} - -/* - * pxa25x_udc_irq - interrupt handler - * - * avoid delays in ep0 processing. the control handshaking isn't always - * under software control (pxa250c0 and the pxa255 are better), and delays - * could cause usb protocol errors. - */ -static struct pxa25x_udc memory; -static int -pxa25x_udc_irq(void) -{ - struct pxa25x_udc *dev = &memory; - int handled; - - test_watchdog(dev); - - dev->stats.irqs++; - do { - u32 udccr = readl(&dev->regs->udccr); - - handled = 0; - - /* SUSpend Interrupt Request */ - if (unlikely(udccr & UDCCR_SUSIR)) { - udc_ack_int_UDCCR(UDCCR_SUSIR); - handled = 1; - debug("USB suspend\n"); - - if (dev->gadget.speed != USB_SPEED_UNKNOWN - && dev->driver - && dev->driver->suspend) - dev->driver->suspend(&dev->gadget); - ep0_idle(dev); - } - - /* RESume Interrupt Request */ - if (unlikely(udccr & UDCCR_RESIR)) { - udc_ack_int_UDCCR(UDCCR_RESIR); - handled = 1; - debug("USB resume\n"); - - if (dev->gadget.speed != USB_SPEED_UNKNOWN - && dev->driver - && dev->driver->resume) - dev->driver->resume(&dev->gadget); - } - - /* ReSeT Interrupt Request - USB reset */ - if (unlikely(udccr & UDCCR_RSTIR)) { - udc_ack_int_UDCCR(UDCCR_RSTIR); - handled = 1; - - if ((readl(&dev->regs->udccr) & UDCCR_UDA) == 0) { - debug("USB reset start\n"); - - /* - * reset driver and endpoints, - * in case that's not yet done - */ - stop_activity(dev, dev->driver); - - } else { - debug("USB reset end\n"); - dev->gadget.speed = USB_SPEED_FULL; - memset(&dev->stats, 0, sizeof dev->stats); - /* driver and endpoints are still reset */ - } - - } else { - u32 uicr0 = readl(&dev->regs->uicr0); - u32 uicr1 = readl(&dev->regs->uicr1); - u32 usir0 = readl(&dev->regs->usir0); - u32 usir1 = readl(&dev->regs->usir1); - - usir0 = usir0 & ~uicr0; - usir1 = usir1 & ~uicr1; - int i; - - if (unlikely(!usir0 && !usir1)) - continue; - - debug_cond(NOISY, "irq %02x.%02x\n", usir1, usir0); - - /* control traffic */ - if (usir0 & USIR0_IR0) { - dev->ep[0].pio_irqs++; - handle_ep0(dev); - handled = 1; - } - - /* endpoint data transfers */ - for (i = 0; i < 8; i++) { - u32 tmp = 1 << i; - - if (i && (usir0 & tmp)) { - handle_ep(&dev->ep[i]); - setbits_le32(&dev->regs->usir0, tmp); - handled = 1; - } -#ifndef CONFIG_USB_PXA25X_SMALL - if (usir1 & tmp) { - handle_ep(&dev->ep[i+8]); - setbits_le32(&dev->regs->usir1, tmp); - handled = 1; - } -#endif - } - } - - /* we could also ask for 1 msec SOF (SIR) interrupts */ - - } while (handled); - return IRQ_HANDLED; -} - -/*-------------------------------------------------------------------------*/ - -/* - * this uses load-time allocation and initialization (instead of - * doing it at run-time) to save code, eliminate fault paths, and - * be more obviously correct. - */ -static struct pxa25x_udc memory = { - .regs = UDC_REGS, - - .gadget = { - .ops = &pxa25x_udc_ops, - .ep0 = &memory.ep[0].ep, - .name = driver_name, - }, - - /* control endpoint */ - .ep[0] = { - .ep = { - .name = ep0name, - .ops = &pxa25x_ep_ops, - .maxpacket = EP0_FIFO_SIZE, - }, - .dev = &memory, - .reg_udccs = &UDC_REGS->udccs[0], - .reg_uddr = &UDC_REGS->uddr0, - }, - - /* first group of endpoints */ - .ep[1] = { - .ep = { - .name = "ep1in-bulk", - .ops = &pxa25x_ep_ops, - .maxpacket = BULK_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = BULK_FIFO_SIZE, - .bEndpointAddress = USB_DIR_IN | 1, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDC_REGS->udccs[1], - .reg_uddr = &UDC_REGS->uddr1, - }, - .ep[2] = { - .ep = { - .name = "ep2out-bulk", - .ops = &pxa25x_ep_ops, - .maxpacket = BULK_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = BULK_FIFO_SIZE, - .bEndpointAddress = 2, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDC_REGS->udccs[2], - .reg_ubcr = &UDC_REGS->ubcr2, - .reg_uddr = &UDC_REGS->uddr2, - }, -#ifndef CONFIG_USB_PXA25X_SMALL - .ep[3] = { - .ep = { - .name = "ep3in-iso", - .ops = &pxa25x_ep_ops, - .maxpacket = ISO_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = ISO_FIFO_SIZE, - .bEndpointAddress = USB_DIR_IN | 3, - .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDC_REGS->udccs[3], - .reg_uddr = &UDC_REGS->uddr3, - }, - .ep[4] = { - .ep = { - .name = "ep4out-iso", - .ops = &pxa25x_ep_ops, - .maxpacket = ISO_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = ISO_FIFO_SIZE, - .bEndpointAddress = 4, - .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDC_REGS->udccs[4], - .reg_ubcr = &UDC_REGS->ubcr4, - .reg_uddr = &UDC_REGS->uddr4, - }, - .ep[5] = { - .ep = { - .name = "ep5in-int", - .ops = &pxa25x_ep_ops, - .maxpacket = INT_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = INT_FIFO_SIZE, - .bEndpointAddress = USB_DIR_IN | 5, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .reg_udccs = &UDC_REGS->udccs[5], - .reg_uddr = &UDC_REGS->uddr5, - }, - - /* second group of endpoints */ - .ep[6] = { - .ep = { - .name = "ep6in-bulk", - .ops = &pxa25x_ep_ops, - .maxpacket = BULK_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = BULK_FIFO_SIZE, - .bEndpointAddress = USB_DIR_IN | 6, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDC_REGS->udccs[6], - .reg_uddr = &UDC_REGS->uddr6, - }, - .ep[7] = { - .ep = { - .name = "ep7out-bulk", - .ops = &pxa25x_ep_ops, - .maxpacket = BULK_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = BULK_FIFO_SIZE, - .bEndpointAddress = 7, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDC_REGS->udccs[7], - .reg_ubcr = &UDC_REGS->ubcr7, - .reg_uddr = &UDC_REGS->uddr7, - }, - .ep[8] = { - .ep = { - .name = "ep8in-iso", - .ops = &pxa25x_ep_ops, - .maxpacket = ISO_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = ISO_FIFO_SIZE, - .bEndpointAddress = USB_DIR_IN | 8, - .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDC_REGS->udccs[8], - .reg_uddr = &UDC_REGS->uddr8, - }, - .ep[9] = { - .ep = { - .name = "ep9out-iso", - .ops = &pxa25x_ep_ops, - .maxpacket = ISO_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = ISO_FIFO_SIZE, - .bEndpointAddress = 9, - .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDC_REGS->udccs[9], - .reg_ubcr = &UDC_REGS->ubcr9, - .reg_uddr = &UDC_REGS->uddr9, - }, - .ep[10] = { - .ep = { - .name = "ep10in-int", - .ops = &pxa25x_ep_ops, - .maxpacket = INT_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = INT_FIFO_SIZE, - .bEndpointAddress = USB_DIR_IN | 10, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .reg_udccs = &UDC_REGS->udccs[10], - .reg_uddr = &UDC_REGS->uddr10, - }, - - /* third group of endpoints */ - .ep[11] = { - .ep = { - .name = "ep11in-bulk", - .ops = &pxa25x_ep_ops, - .maxpacket = BULK_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = BULK_FIFO_SIZE, - .bEndpointAddress = USB_DIR_IN | 11, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDC_REGS->udccs[11], - .reg_uddr = &UDC_REGS->uddr11, - }, - .ep[12] = { - .ep = { - .name = "ep12out-bulk", - .ops = &pxa25x_ep_ops, - .maxpacket = BULK_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = BULK_FIFO_SIZE, - .bEndpointAddress = 12, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDC_REGS->udccs[12], - .reg_ubcr = &UDC_REGS->ubcr12, - .reg_uddr = &UDC_REGS->uddr12, - }, - .ep[13] = { - .ep = { - .name = "ep13in-iso", - .ops = &pxa25x_ep_ops, - .maxpacket = ISO_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = ISO_FIFO_SIZE, - .bEndpointAddress = USB_DIR_IN | 13, - .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDC_REGS->udccs[13], - .reg_uddr = &UDC_REGS->uddr13, - }, - .ep[14] = { - .ep = { - .name = "ep14out-iso", - .ops = &pxa25x_ep_ops, - .maxpacket = ISO_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = ISO_FIFO_SIZE, - .bEndpointAddress = 14, - .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDC_REGS->udccs[14], - .reg_ubcr = &UDC_REGS->ubcr14, - .reg_uddr = &UDC_REGS->uddr14, - }, - .ep[15] = { - .ep = { - .name = "ep15in-int", - .ops = &pxa25x_ep_ops, - .maxpacket = INT_FIFO_SIZE, - }, - .dev = &memory, - .fifo_size = INT_FIFO_SIZE, - .bEndpointAddress = USB_DIR_IN | 15, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .reg_udccs = &UDC_REGS->udccs[15], - .reg_uddr = &UDC_REGS->uddr15, - }, -#endif /* !CONFIG_USB_PXA25X_SMALL */ -}; - -static void udc_command(int cmd) -{ - switch (cmd) { - case PXA2XX_UDC_CMD_CONNECT: - setbits_le32(GPDR(CONFIG_USB_DEV_PULLUP_GPIO), - GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO)); - - /* enable pullup */ - writel(GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO), - GPCR(CONFIG_USB_DEV_PULLUP_GPIO)); - - debug("Connected to USB\n"); - break; - - case PXA2XX_UDC_CMD_DISCONNECT: - /* disable pullup resistor */ - writel(GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO), - GPSR(CONFIG_USB_DEV_PULLUP_GPIO)); - - /* setup pin as input, line will float */ - clrbits_le32(GPDR(CONFIG_USB_DEV_PULLUP_GPIO), - GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO)); - - debug("Disconnected from USB\n"); - break; - } -} - -static struct pxa2xx_udc_mach_info mach_info = { - .udc_command = udc_command, -}; - -/* - * when a driver is successfully registered, it will receive - * control requests including set_configuration(), which enables - * non-control requests. then usb traffic follows until a - * disconnect is reported. then a host may connect again, or - * the driver might get unbound. - */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) -{ - struct pxa25x_udc *dev = &memory; - int retval; - uint32_t chiprev; - - if (!driver - || driver->speed < USB_SPEED_FULL - || !driver->disconnect - || !driver->setup) - return -EINVAL; - if (!dev) - return -ENODEV; - if (dev->driver) - return -EBUSY; - - /* Enable clock for usb controller */ - setbits_le32(CKEN, CKEN11_USB); - - /* first hook up the driver ... */ - dev->driver = driver; - dev->pullup = 1; - - /* trigger chiprev-specific logic */ - switch ((chiprev = pxa_get_cpu_revision())) { - case PXA255_A0: - dev->has_cfr = 1; - break; - case PXA250_A0: - case PXA250_A1: - /* A0/A1 "not released"; ep 13, 15 unusable */ - /* fall through */ - case PXA250_B2: case PXA210_B2: - case PXA250_B1: case PXA210_B1: - case PXA250_B0: case PXA210_B0: - /* OUT-DMA is broken ... */ - /* fall through */ - case PXA250_C0: case PXA210_C0: - break; - default: - printf("%s: unrecognized processor: %08x\n", - DRIVER_NAME, chiprev); - return -ENODEV; - } - - the_controller = dev; - - /* prepare watchdog timer */ - dev->watchdog.running = 0; - dev->watchdog.period = 5000 * CONFIG_SYS_HZ / 1000000; /* 5 ms */ - dev->watchdog.function = udc_watchdog; - - udc_disable(dev); - udc_reinit(dev); - - dev->mach = &mach_info; - - dev->gadget.name = "pxa2xx_udc"; - retval = driver->bind(&dev->gadget); - if (retval) { - printf("bind to driver %s --> error %d\n", - DRIVER_NAME, retval); - dev->driver = NULL; - return retval; - } - - /* - * ... then enable host detection and ep0; and we're ready - * for set_configuration as well as eventual disconnect. - */ - printf("registered gadget driver '%s'\n", DRIVER_NAME); - - pullup(dev); - dump_state(dev); - return 0; -} - -static void -stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver) -{ - int i; - - /* don't disconnect drivers more than once */ - if (dev->gadget.speed == USB_SPEED_UNKNOWN) - driver = NULL; - dev->gadget.speed = USB_SPEED_UNKNOWN; - - /* prevent new request submissions, kill any outstanding requests */ - for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) { - struct pxa25x_ep *ep = &dev->ep[i]; - - ep->stopped = 1; - nuke(ep, -ESHUTDOWN); - } - stop_watchdog(dev); - - /* report disconnect; the driver is already quiesced */ - if (driver) - driver->disconnect(&dev->gadget); - - /* re-init driver-visible data structures */ - udc_reinit(dev); -} - -int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -{ - struct pxa25x_udc *dev = the_controller; - - if (!dev) - return -ENODEV; - if (!driver || driver != dev->driver || !driver->unbind) - return -EINVAL; - - local_irq_disable(); - dev->pullup = 0; - pullup(dev); - stop_activity(dev, driver); - local_irq_enable(); - - driver->unbind(&dev->gadget); - dev->driver = NULL; - - printf("unregistered gadget driver '%s'\n", DRIVER_NAME); - dump_state(dev); - - the_controller = NULL; - - clrbits_le32(CKEN, CKEN11_USB); - - return 0; -} - -extern void udc_disconnect(void) -{ - setbits_le32(CKEN, CKEN11_USB); - udc_clear_mask_UDCCR(UDCCR_UDE); - udc_command(PXA2XX_UDC_CMD_DISCONNECT); - clrbits_le32(CKEN, CKEN11_USB); -} - -/*-------------------------------------------------------------------------*/ - -extern int -usb_gadget_handle_interrupts(void) -{ - return pxa25x_udc_irq(); -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/pxa25x_udc.h b/qemu/roms/u-boot/drivers/usb/gadget/pxa25x_udc.h deleted file mode 100644 index f543b2d58..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/pxa25x_udc.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Intel PXA25x on-chip full speed USB device controller - * - * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix - * Copyright (C) 2003 David Brownell - * Copyright (C) 2012 Lukasz Dalek <luk0104@gmail.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __LINUX_USB_GADGET_PXA25X_H -#define __LINUX_USB_GADGET_PXA25X_H - -#include <linux/types.h> -#include <asm/arch/regs-usb.h> - -/* - * Prefetching support - only ARMv5. - */ - -#ifdef ARCH_HAS_PREFETCH -static inline void prefetch(const void *ptr) -{ - __asm__ __volatile__( - "pld\t%a0" - : - : "p" (ptr) - : "cc"); -} - -#define prefetchw(ptr) prefetch(ptr) -#endif /* ARCH_HAS_PREFETCH */ - -/*-------------------------------------------------------------------------*/ - -#define UDC_REGS ((struct pxa25x_udc_regs *)PXA25X_UDC_BASE) - -/*-------------------------------------------------------------------------*/ - -struct pxa2xx_udc_mach_info { - int (*udc_is_connected)(void); /* do we see host? */ - void (*udc_command)(int cmd); -#define PXA2XX_UDC_CMD_CONNECT 0 /* let host see us */ -#define PXA2XX_UDC_CMD_DISCONNECT 1 /* so host won't see us */ -}; - -struct pxa25x_udc; - -struct pxa25x_ep { - struct usb_ep ep; - struct pxa25x_udc *dev; - - const struct usb_endpoint_descriptor *desc; - struct list_head queue; - unsigned long pio_irqs; - - unsigned short fifo_size; - u8 bEndpointAddress; - u8 bmAttributes; - - unsigned stopped:1; - - /* UDCCS = UDC Control/Status for this EP - * UBCR = UDC Byte Count Remaining (contents of OUT fifo) - * UDDR = UDC Endpoint Data Register (the fifo) - * DRCM = DMA Request Channel Map - */ - u32 *reg_udccs; - u32 *reg_ubcr; - u32 *reg_uddr; -}; - -struct pxa25x_request { - struct usb_request req; - struct list_head queue; -}; - -enum ep0_state { - EP0_IDLE, - EP0_IN_DATA_PHASE, - EP0_OUT_DATA_PHASE, - EP0_END_XFER, - EP0_STALL, -}; - -#define EP0_FIFO_SIZE 16U -#define BULK_FIFO_SIZE 64U -#define ISO_FIFO_SIZE 256U -#define INT_FIFO_SIZE 8U - -struct udc_stats { - struct ep0stats { - unsigned long ops; - unsigned long bytes; - } read, write; - unsigned long irqs; -}; - -#ifdef CONFIG_USB_PXA25X_SMALL -/* when memory's tight, SMALL config saves code+data. */ -#define PXA_UDC_NUM_ENDPOINTS 3 -#endif - -#ifndef PXA_UDC_NUM_ENDPOINTS -#define PXA_UDC_NUM_ENDPOINTS 16 -#endif - -struct pxa25x_watchdog { - unsigned running:1; - ulong period; - ulong base; - struct pxa25x_udc *udc; - - void (*function)(struct pxa25x_udc *udc); -}; - -struct pxa25x_udc { - struct usb_gadget gadget; - struct usb_gadget_driver *driver; - struct pxa25x_udc_regs *regs; - - enum ep0_state ep0state; - struct udc_stats stats; - unsigned got_irq:1, - pullup:1, - has_cfr:1, - req_pending:1, - req_std:1, - req_config:1, - active:1; - - struct clk *clk; - struct pxa2xx_udc_mach_info *mach; - u64 dma_mask; - struct pxa25x_ep ep[PXA_UDC_NUM_ENDPOINTS]; - - struct pxa25x_watchdog watchdog; -}; - -/*-------------------------------------------------------------------------*/ - -static struct pxa25x_udc *the_controller; - -/*-------------------------------------------------------------------------*/ - -#ifndef DEBUG -# define NOISY 0 -#endif - -#endif /* __LINUX_USB_GADGET_PXA25X_H */ diff --git a/qemu/roms/u-boot/drivers/usb/gadget/pxa27x_udc.c b/qemu/roms/u-boot/drivers/usb/gadget/pxa27x_udc.c deleted file mode 100644 index 733558def..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/pxa27x_udc.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - * PXA27x USB device driver for u-boot. - * - * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it> - * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it> - * Copyright (C) 2008 Vivek Kutal <vivek.kutal@azingo.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - - -#include <common.h> -#include <config.h> -#include <asm/byteorder.h> -#include <usbdevice.h> -#include <asm/arch/hardware.h> -#include <asm/io.h> -#include <usb/pxa27x_udc.h> -#include <usb/udc.h> - -#include "ep0.h" - -/* number of endpoints on this UDC */ -#define UDC_MAX_ENDPOINTS 24 - -static struct urb *ep0_urb; -static struct usb_device_instance *udc_device; -static int ep0state = EP0_IDLE; - -#ifdef USBDDBG -static void udc_dump_buffer(char *name, u8 *buf, int len) -{ - usbdbg("%s - buf %p, len %d", name, buf, len); - print_buffer(0, buf, 1, len, 0); -} -#else -#define udc_dump_buffer(name, buf, len) /* void */ -#endif - -static inline void udc_ack_int_UDCCR(int mask) -{ - writel(readl(USIR1) | mask, USIR1); -} - -/* - * If the endpoint has an active tx_urb, then the next packet of data from the - * URB is written to the tx FIFO. - * The total amount of data in the urb is given by urb->actual_length. - * The maximum amount of data that can be sent in any one packet is given by - * endpoint->tx_packetSize. - * The number of data bytes from this URB that have already been transmitted - * is given by endpoint->sent. - * endpoint->last is updated by this routine with the number of data bytes - * transmitted in this packet. - */ -static int udc_write_urb(struct usb_endpoint_instance *endpoint) -{ - struct urb *urb = endpoint->tx_urb; - int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK; - u32 *data32 = (u32 *) urb->buffer; - u8 *data8 = (u8 *) urb->buffer; - unsigned int i, n, w, b, is_short; - int timeout = 2000; /* 2ms */ - - if (!urb || !urb->actual_length) - return -1; - - n = MIN(urb->actual_length - endpoint->sent, endpoint->tx_packetSize); - if (n <= 0) - return -1; - - usbdbg("write urb on ep %d", ep_num); -#if defined(USBDDBG) && defined(USBDPARANOIA) - usbdbg("urb: buf %p, buf_len %d, actual_len %d", - urb->buffer, urb->buffer_length, urb->actual_length); - usbdbg("endpoint: sent %d, tx_packetSize %d, last %d", - endpoint->sent, endpoint->tx_packetSize, endpoint->last); -#endif - - is_short = n != endpoint->tx_packetSize; - w = n / 4; - b = n % 4; - usbdbg("n %d%s w %d b %d", n, is_short ? "-s" : "", w, b); - udc_dump_buffer("urb write", data8 + endpoint->sent, n); - - /* Prepare for data send */ - if (ep_num) - writel(UDCCSR_PC ,UDCCSN(ep_num)); - - for (i = 0; i < w; i++) - writel(data32[endpoint->sent / 4 + i], UDCDN(ep_num)); - - for (i = 0; i < b; i++) - writeb(data8[endpoint->sent + w * 4 + i], UDCDN(ep_num)); - - /* Set "Packet Complete" if less data then tx_packetSize */ - if (is_short) - writel(ep_num ? UDCCSR_SP : UDCCSR0_IPR, UDCCSN(ep_num)); - - /* Wait for data sent */ - if (ep_num) { - while (!(readl(UDCCSN(ep_num)) & UDCCSR_PC)) { - if (timeout-- == 0) - return -1; - else - udelay(1); - } - } - - endpoint->last = n; - - if (ep_num) { - usbd_tx_complete(endpoint); - } else { - endpoint->sent += n; - endpoint->last -= n; - } - - if (endpoint->sent >= urb->actual_length) { - urb->actual_length = 0; - endpoint->sent = 0; - endpoint->last = 0; - } - - if ((endpoint->sent >= urb->actual_length) && (!ep_num)) { - usbdbg("ep0 IN stage done"); - if (is_short) - ep0state = EP0_IDLE; - else - ep0state = EP0_XFER_COMPLETE; - } - - return 0; -} - -static int udc_read_urb(struct usb_endpoint_instance *endpoint) -{ - struct urb *urb = endpoint->rcv_urb; - int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK; - u32 *data32 = (u32 *) urb->buffer; - unsigned int i, n; - - usbdbg("read urb on ep %d", ep_num); -#if defined(USBDDBG) && defined(USBDPARANOIA) - usbdbg("urb: buf %p, buf_len %d, actual_len %d", - urb->buffer, urb->buffer_length, urb->actual_length); - usbdbg("endpoint: rcv_packetSize %d", - endpoint->rcv_packetSize); -#endif - - if (readl(UDCCSN(ep_num)) & UDCCSR_BNE) - n = readl(UDCBCN(ep_num)) & 0x3ff; - else /* zlp */ - n = 0; - - usbdbg("n %d%s", n, n != endpoint->rcv_packetSize ? "-s" : ""); - for (i = 0; i < n; i += 4) - data32[urb->actual_length / 4 + i / 4] = readl(UDCDN(ep_num)); - - udc_dump_buffer("urb read", (u8 *) data32, urb->actual_length + n); - usbd_rcv_complete(endpoint, n, 0); - - return 0; -} - -static int udc_read_urb_ep0(void) -{ - u32 *data32 = (u32 *) ep0_urb->buffer; - u8 *data8 = (u8 *) ep0_urb->buffer; - unsigned int i, n, w, b; - - usbdbg("read urb on ep 0"); -#if defined(USBDDBG) && defined(USBDPARANOIA) - usbdbg("urb: buf %p, buf_len %d, actual_len %d", - ep0_urb->buffer, ep0_urb->buffer_length, ep0_urb->actual_length); -#endif - - n = readl(UDCBCR0); - w = n / 4; - b = n % 4; - - for (i = 0; i < w; i++) { - data32[ep0_urb->actual_length / 4 + i] = readl(UDCDN(0)); - /* ep0_urb->actual_length += 4; */ - } - - for (i = 0; i < b; i++) { - data8[ep0_urb->actual_length + w * 4 + i] = readb(UDCDN(0)); - /* ep0_urb->actual_length++; */ - } - - ep0_urb->actual_length += n; - - udc_dump_buffer("urb read", (u8 *) data32, ep0_urb->actual_length); - - writel(UDCCSR0_OPC | UDCCSR0_IPR, UDCCSR0); - if (ep0_urb->actual_length == ep0_urb->device_request.wLength) - return 1; - - return 0; -} - -static void udc_handle_ep0(struct usb_endpoint_instance *endpoint) -{ - u32 udccsr0 = readl(UDCCSR0); - u32 *data = (u32 *) &ep0_urb->device_request; - int i; - - usbdbg("udccsr0 %x", udccsr0); - - /* Clear stall status */ - if (udccsr0 & UDCCSR0_SST) { - usberr("clear stall status"); - writel(UDCCSR0_SST, UDCCSR0); - ep0state = EP0_IDLE; - } - - /* previous request unfinished? non-error iff back-to-back ... */ - if ((udccsr0 & UDCCSR0_SA) != 0 && ep0state != EP0_IDLE) - ep0state = EP0_IDLE; - - switch (ep0state) { - - case EP0_IDLE: - udccsr0 = readl(UDCCSR0); - /* Start control request? */ - if ((udccsr0 & (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)) - == (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)) { - - /* Read SETUP packet. - * SETUP packet size is 8 bytes (aka 2 words) - */ - usbdbg("try reading SETUP packet"); - for (i = 0; i < 2; i++) { - if ((readl(UDCCSR0) & UDCCSR0_RNE) == 0) { - usberr("setup packet too short:%d", i); - goto stall; - } - data[i] = readl(UDCDR0); - } - - writel(readl(UDCCSR0) | UDCCSR0_OPC | UDCCSR0_SA, UDCCSR0); - if ((readl(UDCCSR0) & UDCCSR0_RNE) != 0) { - usberr("setup packet too long"); - goto stall; - } - - udc_dump_buffer("ep0 setup read", (u8 *) data, 8); - - if (ep0_urb->device_request.wLength == 0) { - usbdbg("Zero Data control Packet\n"); - if (ep0_recv_setup(ep0_urb)) { - usberr("Invalid Setup Packet\n"); - udc_dump_buffer("ep0 setup read", - (u8 *)data, 8); - goto stall; - } - writel(UDCCSR0_IPR, UDCCSR0); - ep0state = EP0_IDLE; - } else { - /* Check direction */ - if ((ep0_urb->device_request.bmRequestType & - USB_REQ_DIRECTION_MASK) - == USB_REQ_HOST2DEVICE) { - ep0state = EP0_OUT_DATA; - ep0_urb->buffer = - (u8 *)ep0_urb->buffer_data; - ep0_urb->buffer_length = - sizeof(ep0_urb->buffer_data); - ep0_urb->actual_length = 0; - writel(UDCCSR0_IPR, UDCCSR0); - } else { - /* The ep0_recv_setup function has - * already placed our response packet - * data in ep0_urb->buffer and the - * packet length in - * ep0_urb->actual_length. - */ - if (ep0_recv_setup(ep0_urb)) { -stall: - usberr("Invalid setup packet"); - udc_dump_buffer("ep0 setup read" - , (u8 *) data, 8); - ep0state = EP0_IDLE; - - writel(UDCCSR0_SA | - UDCCSR0_OPC | UDCCSR0_FST | - UDCCS0_FTF, UDCCSR0); - - return; - } - - endpoint->tx_urb = ep0_urb; - endpoint->sent = 0; - usbdbg("EP0_IN_DATA"); - ep0state = EP0_IN_DATA; - if (udc_write_urb(endpoint) < 0) - goto stall; - - } - } - return; - } else if ((udccsr0 & (UDCCSR0_OPC | UDCCSR0_SA)) - == (UDCCSR0_OPC|UDCCSR0_SA)) { - usberr("Setup Active but no data. Stalling ....\n"); - goto stall; - } else { - usbdbg("random early IRQs"); - /* Some random early IRQs: - * - we acked FST - * - IPR cleared - * - OPC got set, without SA (likely status stage) - */ - writel(udccsr0 & (UDCCSR0_SA | UDCCSR0_OPC), UDCCSR0); - } - break; - - case EP0_OUT_DATA: - - if ((udccsr0 & UDCCSR0_OPC) && !(udccsr0 & UDCCSR0_SA)) { - if (udc_read_urb_ep0()) { -read_complete: - ep0state = EP0_IDLE; - if (ep0_recv_setup(ep0_urb)) { - /* Not a setup packet, stall next - * EP0 transaction - */ - udc_dump_buffer("ep0 setup read", - (u8 *) data, 8); - usberr("can't parse setup packet\n"); - goto stall; - } - } - } else if (!(udccsr0 & UDCCSR0_OPC) && - !(udccsr0 & UDCCSR0_IPR)) { - if (ep0_urb->device_request.wLength == - ep0_urb->actual_length) - goto read_complete; - - usberr("Premature Status\n"); - ep0state = EP0_IDLE; - } - break; - - case EP0_IN_DATA: - /* GET_DESCRIPTOR etc */ - if (udccsr0 & UDCCSR0_OPC) { - writel(UDCCSR0_OPC | UDCCSR0_FTF, UDCCSR0); - usberr("ep0in premature status"); - ep0state = EP0_IDLE; - } else { - /* irq was IPR clearing */ - if (udc_write_urb(endpoint) < 0) { - usberr("ep0_write_error\n"); - goto stall; - } - } - break; - - case EP0_XFER_COMPLETE: - writel(UDCCSR0_IPR, UDCCSR0); - ep0state = EP0_IDLE; - break; - - default: - usbdbg("Default\n"); - } - writel(USIR0_IR0, USIR0); -} - -static void udc_handle_ep(struct usb_endpoint_instance *endpoint) -{ - int ep_addr = endpoint->endpoint_address; - int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; - int ep_isout = (ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT; - - u32 flags = readl(UDCCSN(ep_num)) & (UDCCSR_SST | UDCCSR_TRN); - if (flags) - writel(flags, UDCCSN(ep_num)); - - if (ep_isout) - udc_read_urb(endpoint); - else - udc_write_urb(endpoint); - - writel(UDCCSR_PC, UDCCSN(ep_num)); -} - -static void udc_state_changed(void) -{ - - writel(readl(UDCCR) | UDCCR_SMAC, UDCCR); - - usbdbg("New UDC settings are: conf %d - inter %d - alter %d", - (readl(UDCCR) & UDCCR_ACN) >> UDCCR_ACN_S, - (readl(UDCCR) & UDCCR_AIN) >> UDCCR_AIN_S, - (readl(UDCCR) & UDCCR_AAISN) >> UDCCR_AAISN_S); - - usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0); - writel(UDCISR1_IRCC, UDCISR1); -} - -void udc_irq(void) -{ - int handled; - struct usb_endpoint_instance *endpoint; - int ep_num, i; - u32 udcisr0; - - do { - handled = 0; - /* Suspend Interrupt Request */ - if (readl(USIR1) & UDCCR_SUSIR) { - usbdbg("Suspend\n"); - udc_ack_int_UDCCR(UDCCR_SUSIR); - handled = 1; - ep0state = EP0_IDLE; - } - - /* Resume Interrupt Request */ - if (readl(USIR1) & UDCCR_RESIR) { - udc_ack_int_UDCCR(UDCCR_RESIR); - handled = 1; - usbdbg("USB resume\n"); - } - - if (readl(USIR1) & (1<<31)) { - handled = 1; - udc_state_changed(); - } - - /* Reset Interrupt Request */ - if (readl(USIR1) & UDCCR_RSTIR) { - udc_ack_int_UDCCR(UDCCR_RSTIR); - handled = 1; - usbdbg("Reset\n"); - usbd_device_event_irq(udc_device, DEVICE_RESET, 0); - } else { - if (readl(USIR0)) - usbdbg("UISR0: %x \n", readl(USIR0)); - - if (readl(USIR0) & 0x2) - writel(0x2, USIR0); - - /* Control traffic */ - if (readl(USIR0) & USIR0_IR0) { - handled = 1; - writel(USIR0_IR0, USIR0); - udc_handle_ep0(udc_device->bus->endpoint_array); - } - - endpoint = udc_device->bus->endpoint_array; - for (i = 0; i < udc_device->bus->max_endpoints; i++) { - ep_num = (endpoint[i].endpoint_address) & - USB_ENDPOINT_NUMBER_MASK; - if (!ep_num) - continue; - udcisr0 = readl(UDCISR0); - if (udcisr0 & - UDCISR_INT(ep_num, UDC_INT_PACKETCMP)) { - writel(UDCISR_INT(ep_num, UDC_INT_PACKETCMP), - UDCISR0); - udc_handle_ep(&endpoint[i]); - } - } - } - - } while (handled); -} - -/* The UDCCR reg contains mask and interrupt status bits, - * so using '|=' isn't safe as it may ack an interrupt. - */ -#define UDCCR_OEN (1 << 31) /* On-the-Go Enable */ -#define UDCCR_MASK_BITS (UDCCR_OEN | UDCCR_UDE) - -static inline void udc_set_mask_UDCCR(int mask) -{ - writel((readl(UDCCR) & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS), UDCCR); -} - -static inline void udc_clear_mask_UDCCR(int mask) -{ - writel((readl(UDCCR) & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS), UDCCR); -} - -static void pio_irq_enable(int ep_num) -{ - if (ep_num < 16) - writel(readl(UDCICR0) | 3 << (ep_num * 2), UDCICR0); - else { - ep_num -= 16; - writel(readl(UDCICR1) | 3 << (ep_num * 2), UDCICR1); - } -} - -/* - * udc_set_nak - * - * Allow upper layers to signal lower layers should not accept more RX data - */ -void udc_set_nak(int ep_num) -{ - /* TODO */ -} - -/* - * udc_unset_nak - * - * Suspend sending of NAK tokens for DATA OUT tokens on a given endpoint. - * Switch off NAKing on this endpoint to accept more data output from host. - */ -void udc_unset_nak(int ep_num) -{ - /* TODO */ -} - -int udc_endpoint_write(struct usb_endpoint_instance *endpoint) -{ - return udc_write_urb(endpoint); -} - -/* Associate a physical endpoint with endpoint instance */ -void udc_setup_ep(struct usb_device_instance *device, unsigned int id, - struct usb_endpoint_instance *endpoint) -{ - int ep_num, ep_addr, ep_isout, ep_type, ep_size; - int config, interface, alternate; - u32 tmp; - - usbdbg("setting up endpoint id %d", id); - - if (!endpoint) { - usberr("endpoint void!"); - return; - } - - ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK; - if (ep_num >= UDC_MAX_ENDPOINTS) { - usberr("unable to setup ep %d!", ep_num); - return; - } - - pio_irq_enable(ep_num); - if (ep_num == 0) { - /* Done for ep0 */ - return; - } - - config = 1; - interface = 0; - alternate = 0; - - usbdbg("config %d - interface %d - alternate %d", - config, interface, alternate); - - ep_addr = endpoint->endpoint_address; - ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; - ep_isout = (ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT; - ep_type = ep_isout ? endpoint->rcv_attributes : endpoint->tx_attributes; - ep_size = ep_isout ? endpoint->rcv_packetSize : endpoint->tx_packetSize; - - usbdbg("addr %x, num %d, dir %s, type %s, packet size %d", - ep_addr, ep_num, - ep_isout ? "out" : "in", - ep_type == USB_ENDPOINT_XFER_ISOC ? "isoc" : - ep_type == USB_ENDPOINT_XFER_BULK ? "bulk" : - ep_type == USB_ENDPOINT_XFER_INT ? "int" : "???", - ep_size - ); - - /* Configure UDCCRx */ - tmp = 0; - tmp |= (config << UDCCONR_CN_S) & UDCCONR_CN; - tmp |= (interface << UDCCONR_IN_S) & UDCCONR_IN; - tmp |= (alternate << UDCCONR_AISN_S) & UDCCONR_AISN; - tmp |= (ep_num << UDCCONR_EN_S) & UDCCONR_EN; - tmp |= (ep_type << UDCCONR_ET_S) & UDCCONR_ET; - tmp |= ep_isout ? 0 : UDCCONR_ED; - tmp |= (ep_size << UDCCONR_MPS_S) & UDCCONR_MPS; - tmp |= UDCCONR_EE; - - writel(tmp, UDCCN(ep_num)); - - usbdbg("UDCCR%c = %x", 'A' + ep_num-1, readl(UDCCN(ep_num))); - usbdbg("UDCCSR%c = %x", 'A' + ep_num-1, readl(UDCCSN(ep_num))); -} - -/* Connect the USB device to the bus */ -void udc_connect(void) -{ - usbdbg("UDC connect"); - -#ifdef CONFIG_USB_DEV_PULLUP_GPIO - /* Turn on the USB connection by enabling the pullup resistor */ - writel(readl(GPDR(CONFIG_USB_DEV_PULLUP_GPIO)) - | GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO), - GPDR(CONFIG_USB_DEV_PULLUP_GPIO)); - writel(GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO), GPSR(CONFIG_USB_DEV_PULLUP_GPIO)); -#else - /* Host port 2 transceiver D+ pull up enable */ - writel(readl(UP2OCR) | UP2OCR_DPPUE, UP2OCR); -#endif -} - -/* Disconnect the USB device to the bus */ -void udc_disconnect(void) -{ - usbdbg("UDC disconnect"); - -#ifdef CONFIG_USB_DEV_PULLUP_GPIO - /* Turn off the USB connection by disabling the pullup resistor */ - writel(GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO), GPCR(CONFIG_USB_DEV_PULLUP_GPIO)); -#else - /* Host port 2 transceiver D+ pull up disable */ - writel(readl(UP2OCR) & ~UP2OCR_DPPUE, UP2OCR); -#endif -} - -/* Switch on the UDC */ -void udc_enable(struct usb_device_instance *device) -{ - - ep0state = EP0_IDLE; - - /* enable endpoint 0, A, B's Packet Complete Interrupt. */ - writel(0xffffffff, UDCICR0); - writel(0xa8000000, UDCICR1); - - /* clear the interrupt status/control registers */ - writel(0xffffffff, UDCISR0); - writel(0xffffffff, UDCISR1); - - /* set UDC-enable */ - udc_set_mask_UDCCR(UDCCR_UDE); - - udc_device = device; - if (!ep0_urb) - ep0_urb = usbd_alloc_urb(udc_device, - udc_device->bus->endpoint_array); - else - usbinfo("ep0_urb %p already allocated", ep0_urb); - - usbdbg("UDC Enabled\n"); -} - -/* Need to check this again */ -void udc_disable(void) -{ - usbdbg("disable UDC"); - - udc_clear_mask_UDCCR(UDCCR_UDE); - - /* Disable clock for USB device */ - writel(readl(CKEN) & ~CKEN11_USB, CKEN); - - /* Free ep0 URB */ - if (ep0_urb) { - usbd_dealloc_urb(ep0_urb); - ep0_urb = NULL; - } - - /* Reset device pointer */ - udc_device = NULL; -} - -/* Allow udc code to do any additional startup */ -void udc_startup_events(struct usb_device_instance *device) -{ - /* The DEVICE_INIT event puts the USB device in the state STATE_INIT */ - usbd_device_event_irq(device, DEVICE_INIT, 0); - - /* The DEVICE_CREATE event puts the USB device in the state - * STATE_ATTACHED */ - usbd_device_event_irq(device, DEVICE_CREATE, 0); - - /* Some USB controller driver implementations signal - * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here. - * DEVICE_HUB_CONFIGURED causes a transition to the state - * STATE_POWERED, and DEVICE_RESET causes a transition to - * the state STATE_DEFAULT. - */ - udc_enable(device); -} - -/* Initialize h/w stuff */ -int udc_init(void) -{ - udc_device = NULL; - usbdbg("PXA27x usbd start"); - - /* Enable clock for USB device */ - writel(readl(CKEN) | CKEN11_USB, CKEN); - - /* Disable the UDC */ - udc_clear_mask_UDCCR(UDCCR_UDE); - - /* Disable IRQs: we don't use them */ - writel(0, UDCICR0); - writel(0, UDCICR1); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/regs-otg.h b/qemu/roms/u-boot/drivers/usb/gadget/regs-otg.h deleted file mode 100644 index ac5d11213..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/regs-otg.h +++ /dev/null @@ -1,273 +0,0 @@ -/* linux/arch/arm/plat-s3c/include/plat/regs-otg.h - * - * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at> - * - * Registers remapping: - * Lukasz Majewski <l.majewski@samsumg.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __ASM_ARCH_REGS_USB_OTG_HS_H -#define __ASM_ARCH_REGS_USB_OTG_HS_H - -/* USB2.0 OTG Controller register */ -struct s3c_usbotg_phy { - u32 phypwr; - u32 phyclk; - u32 rstcon; -}; - -/* Device Logical IN Endpoint-Specific Registers */ -struct s3c_dev_in_endp { - u32 diepctl; - u8 res1[4]; - u32 diepint; - u8 res2[4]; - u32 dieptsiz; - u32 diepdma; - u8 res3[4]; - u32 diepdmab; -}; - -/* Device Logical OUT Endpoint-Specific Registers */ -struct s3c_dev_out_endp { - u32 doepctl; - u8 res1[4]; - u32 doepint; - u8 res2[4]; - u32 doeptsiz; - u32 doepdma; - u8 res3[4]; - u32 doepdmab; -}; - -struct ep_fifo { - u32 fifo; - u8 res[4092]; -}; - -/* USB2.0 OTG Controller register */ -struct s3c_usbotg_reg { - /* Core Global Registers */ - u32 gotgctl; /* OTG Control & Status */ - u32 gotgint; /* OTG Interrupt */ - u32 gahbcfg; /* Core AHB Configuration */ - u32 gusbcfg; /* Core USB Configuration */ - u32 grstctl; /* Core Reset */ - u32 gintsts; /* Core Interrupt */ - u32 gintmsk; /* Core Interrupt Mask */ - u32 grxstsr; /* Receive Status Debug Read/Status Read */ - u32 grxstsp; /* Receive Status Debug Pop/Status Pop */ - u32 grxfsiz; /* Receive FIFO Size */ - u32 gnptxfsiz; /* Non-Periodic Transmit FIFO Size */ - u8 res1[216]; - u32 dieptxf[15]; /* Device Periodic Transmit FIFO size register */ - u8 res2[1728]; - /* Device Configuration */ - u32 dcfg; /* Device Configuration Register */ - u32 dctl; /* Device Control */ - u32 dsts; /* Device Status */ - u8 res3[4]; - u32 diepmsk; /* Device IN Endpoint Common Interrupt Mask */ - u32 doepmsk; /* Device OUT Endpoint Common Interrupt Mask */ - u32 daint; /* Device All Endpoints Interrupt */ - u32 daintmsk; /* Device All Endpoints Interrupt Mask */ - u8 res4[224]; - struct s3c_dev_in_endp in_endp[16]; - struct s3c_dev_out_endp out_endp[16]; - u8 res5[768]; - struct ep_fifo ep[16]; -}; - -/*===================================================================== */ -/*definitions related to CSR setting */ - -/* S3C_UDC_OTG_GOTGCTL */ -#define B_SESSION_VALID (0x1<<19) -#define A_SESSION_VALID (0x1<<18) - -/* S3C_UDC_OTG_GAHBCFG */ -#define PTXFE_HALF (0<<8) -#define PTXFE_ZERO (1<<8) -#define NPTXFE_HALF (0<<7) -#define NPTXFE_ZERO (1<<7) -#define MODE_SLAVE (0<<5) -#define MODE_DMA (1<<5) -#define BURST_SINGLE (0<<1) -#define BURST_INCR (1<<1) -#define BURST_INCR4 (3<<1) -#define BURST_INCR8 (5<<1) -#define BURST_INCR16 (7<<1) -#define GBL_INT_UNMASK (1<<0) -#define GBL_INT_MASK (0<<0) - -/* S3C_UDC_OTG_GRSTCTL */ -#define AHB_MASTER_IDLE (1u<<31) -#define CORE_SOFT_RESET (0x1<<0) - -/* S3C_UDC_OTG_GINTSTS/S3C_UDC_OTG_GINTMSK core interrupt register */ -#define INT_RESUME (1u<<31) -#define INT_DISCONN (0x1<<29) -#define INT_CONN_ID_STS_CNG (0x1<<28) -#define INT_OUT_EP (0x1<<19) -#define INT_IN_EP (0x1<<18) -#define INT_ENUMDONE (0x1<<13) -#define INT_RESET (0x1<<12) -#define INT_SUSPEND (0x1<<11) -#define INT_EARLY_SUSPEND (0x1<<10) -#define INT_NP_TX_FIFO_EMPTY (0x1<<5) -#define INT_RX_FIFO_NOT_EMPTY (0x1<<4) -#define INT_SOF (0x1<<3) -#define INT_DEV_MODE (0x0<<0) -#define INT_HOST_MODE (0x1<<1) -#define INT_GOUTNakEff (0x01<<7) -#define INT_GINNakEff (0x01<<6) - -#define FULL_SPEED_CONTROL_PKT_SIZE 8 -#define FULL_SPEED_BULK_PKT_SIZE 64 - -#define HIGH_SPEED_CONTROL_PKT_SIZE 64 -#define HIGH_SPEED_BULK_PKT_SIZE 512 - -#define RX_FIFO_SIZE (1024*4) -#define NPTX_FIFO_SIZE (1024*4) -#define PTX_FIFO_SIZE (1536*1) - -#define DEPCTL_TXFNUM_0 (0x0<<22) -#define DEPCTL_TXFNUM_1 (0x1<<22) -#define DEPCTL_TXFNUM_2 (0x2<<22) -#define DEPCTL_TXFNUM_3 (0x3<<22) -#define DEPCTL_TXFNUM_4 (0x4<<22) - -/* Enumeration speed */ -#define USB_HIGH_30_60MHZ (0x0<<1) -#define USB_FULL_30_60MHZ (0x1<<1) -#define USB_LOW_6MHZ (0x2<<1) -#define USB_FULL_48MHZ (0x3<<1) - -/* S3C_UDC_OTG_GRXSTSP STATUS */ -#define OUT_PKT_RECEIVED (0x2<<17) -#define OUT_TRANSFER_COMPLELTED (0x3<<17) -#define SETUP_TRANSACTION_COMPLETED (0x4<<17) -#define SETUP_PKT_RECEIVED (0x6<<17) -#define GLOBAL_OUT_NAK (0x1<<17) - -/* S3C_UDC_OTG_DCTL device control register */ -#define NORMAL_OPERATION (0x1<<0) -#define SOFT_DISCONNECT (0x1<<1) - -/* S3C_UDC_OTG_DAINT device all endpoint interrupt register */ -#define DAINT_OUT_BIT (16) -#define DAINT_MASK (0xFFFF) - -/* S3C_UDC_OTG_DIEPCTL0/DOEPCTL0 device - control IN/OUT endpoint 0 control register */ -#define DEPCTL_EPENA (0x1<<31) -#define DEPCTL_EPDIS (0x1<<30) -#define DEPCTL_SETD1PID (0x1<<29) -#define DEPCTL_SETD0PID (0x1<<28) -#define DEPCTL_SNAK (0x1<<27) -#define DEPCTL_CNAK (0x1<<26) -#define DEPCTL_STALL (0x1<<21) -#define DEPCTL_TYPE_BIT (18) -#define DEPCTL_TYPE_MASK (0x3<<18) -#define DEPCTL_CTRL_TYPE (0x0<<18) -#define DEPCTL_ISO_TYPE (0x1<<18) -#define DEPCTL_BULK_TYPE (0x2<<18) -#define DEPCTL_INTR_TYPE (0x3<<18) -#define DEPCTL_USBACTEP (0x1<<15) -#define DEPCTL_NEXT_EP_BIT (11) -#define DEPCTL_MPS_BIT (0) -#define DEPCTL_MPS_MASK (0x7FF) - -#define DEPCTL0_MPS_64 (0x0<<0) -#define DEPCTL0_MPS_32 (0x1<<0) -#define DEPCTL0_MPS_16 (0x2<<0) -#define DEPCTL0_MPS_8 (0x3<<0) -#define DEPCTL_MPS_BULK_512 (512<<0) -#define DEPCTL_MPS_INT_MPS_16 (16<<0) - -#define DIEPCTL0_NEXT_EP_BIT (11) - - -/* S3C_UDC_OTG_DIEPMSK/DOEPMSK device IN/OUT endpoint - common interrupt mask register */ -/* S3C_UDC_OTG_DIEPINTn/DOEPINTn device IN/OUT endpoint interrupt register */ -#define BACK2BACK_SETUP_RECEIVED (0x1<<6) -#define INTKNEPMIS (0x1<<5) -#define INTKN_TXFEMP (0x1<<4) -#define NON_ISO_IN_EP_TIMEOUT (0x1<<3) -#define CTRL_OUT_EP_SETUP_PHASE_DONE (0x1<<3) -#define AHB_ERROR (0x1<<2) -#define EPDISBLD (0x1<<1) -#define TRANSFER_DONE (0x1<<0) - -#define USB_PHY_CTRL_EN0 (0x1 << 0) - -/* OPHYPWR */ -#define PHY_0_SLEEP (0x1 << 5) -#define OTG_DISABLE_0 (0x1 << 4) -#define ANALOG_PWRDOWN (0x1 << 3) -#define FORCE_SUSPEND_0 (0x1 << 0) - -/* URSTCON */ -#define HOST_SW_RST (0x1 << 4) -#define PHY_SW_RST1 (0x1 << 3) -#define PHYLNK_SW_RST (0x1 << 2) -#define LINK_SW_RST (0x1 << 1) -#define PHY_SW_RST0 (0x1 << 0) - -/* OPHYCLK */ -#define COMMON_ON_N1 (0x1 << 7) -#define COMMON_ON_N0 (0x1 << 4) -#define ID_PULLUP0 (0x1 << 2) -#define CLK_SEL_24MHZ (0x3 << 0) -#define CLK_SEL_12MHZ (0x2 << 0) -#define CLK_SEL_48MHZ (0x0 << 0) - -#define EXYNOS4X12_ID_PULLUP0 (0x01 << 3) -#define EXYNOS4X12_COMMON_ON_N0 (0x01 << 4) -#define EXYNOS4X12_CLK_SEL_12MHZ (0x02 << 0) -#define EXYNOS4X12_CLK_SEL_24MHZ (0x05 << 0) - -/* Device Configuration Register DCFG */ -#define DEV_SPEED_HIGH_SPEED_20 (0x0 << 0) -#define DEV_SPEED_FULL_SPEED_20 (0x1 << 0) -#define DEV_SPEED_LOW_SPEED_11 (0x2 << 0) -#define DEV_SPEED_FULL_SPEED_11 (0x3 << 0) -#define EP_MISS_CNT(x) (x << 18) -#define DEVICE_ADDRESS(x) (x << 4) - -/* Core Reset Register (GRSTCTL) */ -#define TX_FIFO_FLUSH (0x1 << 5) -#define RX_FIFO_FLUSH (0x1 << 4) -#define TX_FIFO_NUMBER(x) (x << 6) -#define TX_FIFO_FLUSH_ALL TX_FIFO_NUMBER(0x10) - -/* Masks definitions */ -#define GINTMSK_INIT (INT_OUT_EP | INT_IN_EP | INT_RESUME | INT_ENUMDONE\ - | INT_RESET | INT_SUSPEND) -#define DOEPMSK_INIT (CTRL_OUT_EP_SETUP_PHASE_DONE | AHB_ERROR|TRANSFER_DONE) -#define DIEPMSK_INIT (NON_ISO_IN_EP_TIMEOUT|AHB_ERROR|TRANSFER_DONE) -#define GAHBCFG_INIT (PTXFE_HALF | NPTXFE_HALF | MODE_DMA | BURST_INCR4\ - | GBL_INT_UNMASK) - -/* Device Endpoint X Transfer Size Register (DIEPTSIZX) */ -#define DIEPT_SIZ_PKT_CNT(x) (x << 19) -#define DIEPT_SIZ_XFER_SIZE(x) (x << 0) - -/* Device OUT Endpoint X Transfer Size Register (DOEPTSIZX) */ -#define DOEPT_SIZ_PKT_CNT(x) (x << 19) -#define DOEPT_SIZ_XFER_SIZE(x) (x << 0) -#define DOEPT_SIZ_XFER_SIZE_MAX_EP0 (0x7F << 0) -#define DOEPT_SIZ_XFER_SIZE_MAX_EP (0x7FFF << 0) - -/* Device Endpoint-N Control Register (DIEPCTLn/DOEPCTLn) */ -#define DIEPCTL_TX_FIFO_NUM(x) (x << 22) -#define DIEPCTL_TX_FIFO_NUM_MASK (~DIEPCTL_TX_FIFO_NUM(0xF)) - -/* Device ALL Endpoints Interrupt Register (DAINT) */ -#define DAINT_IN_EP_INT(x) (x << 0) -#define DAINT_OUT_EP_INT(x) (x << 16) -#endif diff --git a/qemu/roms/u-boot/drivers/usb/gadget/rndis.c b/qemu/roms/u-boot/drivers/usb/gadget/rndis.c deleted file mode 100644 index 404a7b96f..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/rndis.c +++ /dev/null @@ -1,1316 +0,0 @@ -/* - * RNDIS MSG parser - * - * Authors: Benedikt Spranger, Pengutronix - * Robert Schwebel, Pengutronix - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2, as published by the Free Software Foundation. - * - * This software was originally developed in conformance with - * Microsoft's Remote NDIS Specification License Agreement. - * - * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de> - * Fixed message length bug in init_response - * - * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de> - * Fixed rndis_rm_hdr length bug. - * - * Copyright (C) 2004 by David Brownell - * updates to merge with Linux 2.6, better match RNDIS spec - */ - -#include <common.h> -#include <net.h> -#include <malloc.h> -#include <linux/types.h> -#include <linux/list.h> -#include <linux/netdevice.h> - -#include <asm/byteorder.h> -#include <asm/unaligned.h> -#include <asm/errno.h> - -#undef RNDIS_PM -#undef RNDIS_WAKEUP -#undef VERBOSE - -#include "rndis.h" - -#define ETH_ALEN 6 /* Octets in one ethernet addr */ -#define ETH_HLEN 14 /* Total octets in header. */ -#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ -#define ETH_DATA_LEN 1500 /* Max. octets in payload */ -#define ETH_FRAME_LEN PKTSIZE_ALIGN /* Max. octets in frame sans FCS */ -#define ETH_FCS_LEN 4 /* Octets in the FCS */ -#define ENOTSUPP 524 /* Operation is not supported */ - - -/* - * The driver for your USB chip needs to support ep0 OUT to work with - * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional). - * - * Windows hosts need an INF file like Documentation/usb/linux.inf - * and will be happier if you provide the host_addr module parameter. - */ - -#define RNDIS_MAX_CONFIGS 1 - -static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS]; - -/* Driver Version */ -static const __le32 rndis_driver_version = __constant_cpu_to_le32(1); - -/* Function Prototypes */ -static rndis_resp_t *rndis_add_response(int configNr, u32 length); - - -/* supported OIDs */ -static const u32 oid_supported_list[] = { - /* the general stuff */ - OID_GEN_SUPPORTED_LIST, - OID_GEN_HARDWARE_STATUS, - OID_GEN_MEDIA_SUPPORTED, - OID_GEN_MEDIA_IN_USE, - OID_GEN_MAXIMUM_FRAME_SIZE, - OID_GEN_LINK_SPEED, - OID_GEN_TRANSMIT_BLOCK_SIZE, - OID_GEN_RECEIVE_BLOCK_SIZE, - OID_GEN_VENDOR_ID, - OID_GEN_VENDOR_DESCRIPTION, - OID_GEN_VENDOR_DRIVER_VERSION, - OID_GEN_CURRENT_PACKET_FILTER, - OID_GEN_MAXIMUM_TOTAL_SIZE, - OID_GEN_MEDIA_CONNECT_STATUS, - OID_GEN_PHYSICAL_MEDIUM, -#if 0 - OID_GEN_RNDIS_CONFIG_PARAMETER, -#endif - - /* the statistical stuff */ - OID_GEN_XMIT_OK, - OID_GEN_RCV_OK, - OID_GEN_XMIT_ERROR, - OID_GEN_RCV_ERROR, - OID_GEN_RCV_NO_BUFFER, -#ifdef RNDIS_OPTIONAL_STATS - OID_GEN_DIRECTED_BYTES_XMIT, - OID_GEN_DIRECTED_FRAMES_XMIT, - OID_GEN_MULTICAST_BYTES_XMIT, - OID_GEN_MULTICAST_FRAMES_XMIT, - OID_GEN_BROADCAST_BYTES_XMIT, - OID_GEN_BROADCAST_FRAMES_XMIT, - OID_GEN_DIRECTED_BYTES_RCV, - OID_GEN_DIRECTED_FRAMES_RCV, - OID_GEN_MULTICAST_BYTES_RCV, - OID_GEN_MULTICAST_FRAMES_RCV, - OID_GEN_BROADCAST_BYTES_RCV, - OID_GEN_BROADCAST_FRAMES_RCV, - OID_GEN_RCV_CRC_ERROR, - OID_GEN_TRANSMIT_QUEUE_LENGTH, -#endif /* RNDIS_OPTIONAL_STATS */ - - /* mandatory 802.3 */ - /* the general stuff */ - OID_802_3_PERMANENT_ADDRESS, - OID_802_3_CURRENT_ADDRESS, - OID_802_3_MULTICAST_LIST, - OID_802_3_MAC_OPTIONS, - OID_802_3_MAXIMUM_LIST_SIZE, - - /* the statistical stuff */ - OID_802_3_RCV_ERROR_ALIGNMENT, - OID_802_3_XMIT_ONE_COLLISION, - OID_802_3_XMIT_MORE_COLLISIONS, -#ifdef RNDIS_OPTIONAL_STATS - OID_802_3_XMIT_DEFERRED, - OID_802_3_XMIT_MAX_COLLISIONS, - OID_802_3_RCV_OVERRUN, - OID_802_3_XMIT_UNDERRUN, - OID_802_3_XMIT_HEARTBEAT_FAILURE, - OID_802_3_XMIT_TIMES_CRS_LOST, - OID_802_3_XMIT_LATE_COLLISIONS, -#endif /* RNDIS_OPTIONAL_STATS */ - -#ifdef RNDIS_PM - /* PM and wakeup are mandatory for USB: */ - - /* power management */ - OID_PNP_CAPABILITIES, - OID_PNP_QUERY_POWER, - OID_PNP_SET_POWER, - -#ifdef RNDIS_WAKEUP - /* wake up host */ - OID_PNP_ENABLE_WAKE_UP, - OID_PNP_ADD_WAKE_UP_PATTERN, - OID_PNP_REMOVE_WAKE_UP_PATTERN, -#endif /* RNDIS_WAKEUP */ -#endif /* RNDIS_PM */ -}; - - -/* NDIS Functions */ -static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf, - unsigned buf_len, rndis_resp_t *r) -{ - int retval = -ENOTSUPP; - u32 length = 4; /* usually */ - __le32 *outbuf; - int i, count; - rndis_query_cmplt_type *resp; - rndis_params *params; - - if (!r) - return -ENOMEM; - resp = (rndis_query_cmplt_type *) r->buf; - - if (!resp) - return -ENOMEM; - -#if defined(DEBUG) && defined(DEBUG_VERBOSE) - if (buf_len) { - debug("query OID %08x value, len %d:\n", OID, buf_len); - for (i = 0; i < buf_len; i += 16) { - debug("%03d: %08x %08x %08x %08x\n", i, - get_unaligned_le32(&buf[i]), - get_unaligned_le32(&buf[i + 4]), - get_unaligned_le32(&buf[i + 8]), - get_unaligned_le32(&buf[i + 12])); - } - } -#endif - - /* response goes here, right after the header */ - outbuf = (__le32 *) &resp[1]; - resp->InformationBufferOffset = __constant_cpu_to_le32(16); - - params = &rndis_per_dev_params[configNr]; - switch (OID) { - - /* general oids (table 4-1) */ - - /* mandatory */ - case OID_GEN_SUPPORTED_LIST: - debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__); - length = sizeof(oid_supported_list); - count = length / sizeof(u32); - for (i = 0; i < count; i++) - outbuf[i] = cpu_to_le32(oid_supported_list[i]); - retval = 0; - break; - - /* mandatory */ - case OID_GEN_HARDWARE_STATUS: - debug("%s: OID_GEN_HARDWARE_STATUS\n", __func__); - /* - * Bogus question! - * Hardware must be ready to receive high level protocols. - * BTW: - * reddite ergo quae sunt Caesaris Caesari - * et quae sunt Dei Deo! - */ - *outbuf = __constant_cpu_to_le32(0); - retval = 0; - break; - - /* mandatory */ - case OID_GEN_MEDIA_SUPPORTED: - debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__); - *outbuf = cpu_to_le32(params->medium); - retval = 0; - break; - - /* mandatory */ - case OID_GEN_MEDIA_IN_USE: - debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__); - /* one medium, one transport... (maybe you do it better) */ - *outbuf = cpu_to_le32(params->medium); - retval = 0; - break; - - /* mandatory */ - case OID_GEN_MAXIMUM_FRAME_SIZE: - debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__); - if (params->dev) { - *outbuf = cpu_to_le32(params->mtu); - retval = 0; - } - break; - - /* mandatory */ - case OID_GEN_LINK_SPEED: -#if defined(DEBUG) && defined(DEBUG_VERBOSE) - debug("%s: OID_GEN_LINK_SPEED\n", __func__); -#endif - if (params->media_state == NDIS_MEDIA_STATE_DISCONNECTED) - *outbuf = __constant_cpu_to_le32(0); - else - *outbuf = cpu_to_le32(params->speed); - retval = 0; - break; - - /* mandatory */ - case OID_GEN_TRANSMIT_BLOCK_SIZE: - debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__); - if (params->dev) { - *outbuf = cpu_to_le32(params->mtu); - retval = 0; - } - break; - - /* mandatory */ - case OID_GEN_RECEIVE_BLOCK_SIZE: - debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__); - if (params->dev) { - *outbuf = cpu_to_le32(params->mtu); - retval = 0; - } - break; - - /* mandatory */ - case OID_GEN_VENDOR_ID: - debug("%s: OID_GEN_VENDOR_ID\n", __func__); - *outbuf = cpu_to_le32(params->vendorID); - retval = 0; - break; - - /* mandatory */ - case OID_GEN_VENDOR_DESCRIPTION: - debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__); - length = strlen(params->vendorDescr); - memcpy(outbuf, params->vendorDescr, length); - retval = 0; - break; - - case OID_GEN_VENDOR_DRIVER_VERSION: - debug("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__); - /* Created as LE */ - *outbuf = rndis_driver_version; - retval = 0; - break; - - /* mandatory */ - case OID_GEN_CURRENT_PACKET_FILTER: - debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__); - *outbuf = cpu_to_le32(*params->filter); - retval = 0; - break; - - /* mandatory */ - case OID_GEN_MAXIMUM_TOTAL_SIZE: - debug("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__); - *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE); - retval = 0; - break; - - /* mandatory */ - case OID_GEN_MEDIA_CONNECT_STATUS: -#if defined(DEBUG) && defined(DEBUG_VERBOSE) - debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__); -#endif - *outbuf = cpu_to_le32(params->media_state); - retval = 0; - break; - - case OID_GEN_PHYSICAL_MEDIUM: - debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__); - *outbuf = __constant_cpu_to_le32(0); - retval = 0; - break; - - /* - * The RNDIS specification is incomplete/wrong. Some versions - * of MS-Windows expect OIDs that aren't specified there. Other - * versions emit undefined RNDIS messages. DOCUMENT ALL THESE! - */ - case OID_GEN_MAC_OPTIONS: /* from WinME */ - debug("%s: OID_GEN_MAC_OPTIONS\n", __func__); - *outbuf = __constant_cpu_to_le32( - NDIS_MAC_OPTION_RECEIVE_SERIALIZED - | NDIS_MAC_OPTION_FULL_DUPLEX); - retval = 0; - break; - - /* statistics OIDs (table 4-2) */ - - /* mandatory */ - case OID_GEN_XMIT_OK: -#if defined(DEBUG) && defined(DEBUG_VERBOSE) - debug("%s: OID_GEN_XMIT_OK\n", __func__); -#endif - if (params->stats) { - *outbuf = cpu_to_le32( - params->stats->tx_packets - - params->stats->tx_errors - - params->stats->tx_dropped); - retval = 0; - } - break; - - /* mandatory */ - case OID_GEN_RCV_OK: -#if defined(DEBUG) && defined(DEBUG_VERBOSE) - debug("%s: OID_GEN_RCV_OK\n", __func__); -#endif - if (params->stats) { - *outbuf = cpu_to_le32( - params->stats->rx_packets - - params->stats->rx_errors - - params->stats->rx_dropped); - retval = 0; - } - break; - - /* mandatory */ - case OID_GEN_XMIT_ERROR: -#if defined(DEBUG) && defined(DEBUG_VERBOSE) - debug("%s: OID_GEN_XMIT_ERROR\n", __func__); -#endif - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->tx_errors); - retval = 0; - } - break; - - /* mandatory */ - case OID_GEN_RCV_ERROR: -#if defined(DEBUG) && defined(DEBUG_VERBOSE) - debug("%s: OID_GEN_RCV_ERROR\n", __func__); -#endif - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->rx_errors); - retval = 0; - } - break; - - /* mandatory */ - case OID_GEN_RCV_NO_BUFFER: - debug("%s: OID_GEN_RCV_NO_BUFFER\n", __func__); - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->rx_dropped); - retval = 0; - } - break; - -#ifdef RNDIS_OPTIONAL_STATS - case OID_GEN_DIRECTED_BYTES_XMIT: - debug("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__); - /* - * Aunt Tilly's size of shoes - * minus antarctica count of penguins - * divided by weight of Alpha Centauri - */ - if (params->stats) { - *outbuf = cpu_to_le32( - (params->stats->tx_packets - - params->stats->tx_errors - - params->stats->tx_dropped) - * 123); - retval = 0; - } - break; - - case OID_GEN_DIRECTED_FRAMES_XMIT: - debug("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__); - /* dito */ - if (params->stats) { - *outbuf = cpu_to_le32( - (params->stats->tx_packets - - params->stats->tx_errors - - params->stats->tx_dropped) - / 123); - retval = 0; - } - break; - - case OID_GEN_MULTICAST_BYTES_XMIT: - debug("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__); - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->multicast * 1234); - retval = 0; - } - break; - - case OID_GEN_MULTICAST_FRAMES_XMIT: - debug("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__); - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->multicast); - retval = 0; - } - break; - - case OID_GEN_BROADCAST_BYTES_XMIT: - debug("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__); - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->tx_packets/42*255); - retval = 0; - } - break; - - case OID_GEN_BROADCAST_FRAMES_XMIT: - debug("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__); - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->tx_packets / 42); - retval = 0; - } - break; - - case OID_GEN_DIRECTED_BYTES_RCV: - debug("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__); - *outbuf = __constant_cpu_to_le32(0); - retval = 0; - break; - - case OID_GEN_DIRECTED_FRAMES_RCV: - debug("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__); - *outbuf = __constant_cpu_to_le32(0); - retval = 0; - break; - - case OID_GEN_MULTICAST_BYTES_RCV: - debug("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__); - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->multicast * 1111); - retval = 0; - } - break; - - case OID_GEN_MULTICAST_FRAMES_RCV: - debug("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__); - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->multicast); - retval = 0; - } - break; - - case OID_GEN_BROADCAST_BYTES_RCV: - debug("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__); - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->rx_packets/42*255); - retval = 0; - } - break; - - case OID_GEN_BROADCAST_FRAMES_RCV: - debug("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__); - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->rx_packets / 42); - retval = 0; - } - break; - - case OID_GEN_RCV_CRC_ERROR: - debug("%s: OID_GEN_RCV_CRC_ERROR\n", __func__); - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->rx_crc_errors); - retval = 0; - } - break; - - case OID_GEN_TRANSMIT_QUEUE_LENGTH: - debug("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__); - *outbuf = __constant_cpu_to_le32(0); - retval = 0; - break; -#endif /* RNDIS_OPTIONAL_STATS */ - - /* ieee802.3 OIDs (table 4-3) */ - - /* mandatory */ - case OID_802_3_PERMANENT_ADDRESS: - debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__); - if (params->dev) { - length = ETH_ALEN; - memcpy(outbuf, params->host_mac, length); - retval = 0; - } - break; - - /* mandatory */ - case OID_802_3_CURRENT_ADDRESS: - debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__); - if (params->dev) { - length = ETH_ALEN; - memcpy(outbuf, params->host_mac, length); - retval = 0; - } - break; - - /* mandatory */ - case OID_802_3_MULTICAST_LIST: - debug("%s: OID_802_3_MULTICAST_LIST\n", __func__); - /* Multicast base address only */ - *outbuf = __constant_cpu_to_le32(0xE0000000); - retval = 0; - break; - - /* mandatory */ - case OID_802_3_MAXIMUM_LIST_SIZE: - debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__); - /* Multicast base address only */ - *outbuf = __constant_cpu_to_le32(1); - retval = 0; - break; - - case OID_802_3_MAC_OPTIONS: - debug("%s: OID_802_3_MAC_OPTIONS\n", __func__); - break; - - /* ieee802.3 statistics OIDs (table 4-4) */ - - /* mandatory */ - case OID_802_3_RCV_ERROR_ALIGNMENT: - debug("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__); - if (params->stats) { - *outbuf = cpu_to_le32(params->stats->rx_frame_errors); - retval = 0; - } - break; - - /* mandatory */ - case OID_802_3_XMIT_ONE_COLLISION: - debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__); - *outbuf = __constant_cpu_to_le32(0); - retval = 0; - break; - - /* mandatory */ - case OID_802_3_XMIT_MORE_COLLISIONS: - debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__); - *outbuf = __constant_cpu_to_le32(0); - retval = 0; - break; - -#ifdef RNDIS_OPTIONAL_STATS - case OID_802_3_XMIT_DEFERRED: - debug("%s: OID_802_3_XMIT_DEFERRED\n", __func__); - /* TODO */ - break; - - case OID_802_3_XMIT_MAX_COLLISIONS: - debug("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__); - /* TODO */ - break; - - case OID_802_3_RCV_OVERRUN: - debug("%s: OID_802_3_RCV_OVERRUN\n", __func__); - /* TODO */ - break; - - case OID_802_3_XMIT_UNDERRUN: - debug("%s: OID_802_3_XMIT_UNDERRUN\n", __func__); - /* TODO */ - break; - - case OID_802_3_XMIT_HEARTBEAT_FAILURE: - debug("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__); - /* TODO */ - break; - - case OID_802_3_XMIT_TIMES_CRS_LOST: - debug("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__); - /* TODO */ - break; - - case OID_802_3_XMIT_LATE_COLLISIONS: - debug("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__); - /* TODO */ - break; -#endif /* RNDIS_OPTIONAL_STATS */ - -#ifdef RNDIS_PM - /* power management OIDs (table 4-5) */ - case OID_PNP_CAPABILITIES: - debug("%s: OID_PNP_CAPABILITIES\n", __func__); - - /* for now, no wakeup capabilities */ - length = sizeof(struct NDIS_PNP_CAPABILITIES); - memset(outbuf, 0, length); - retval = 0; - break; - case OID_PNP_QUERY_POWER: - debug("%s: OID_PNP_QUERY_POWER D%d\n", __func__, - get_unaligned_le32(buf) - 1); - /* - * only suspend is a real power state, and - * it can't be entered by OID_PNP_SET_POWER... - */ - length = 0; - retval = 0; - break; -#endif - - default: - debug("%s: query unknown OID 0x%08X\n", __func__, OID); - } - if (retval < 0) - length = 0; - - resp->InformationBufferLength = cpu_to_le32(length); - r->length = length + sizeof *resp; - resp->MessageLength = cpu_to_le32(r->length); - return retval; -} - -static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len, - rndis_resp_t *r) -{ - rndis_set_cmplt_type *resp; - int retval = -ENOTSUPP; - struct rndis_params *params; -#if (defined(DEBUG) && defined(DEBUG_VERBOSE)) || defined(RNDIS_PM) - int i; -#endif - - if (!r) - return -ENOMEM; - resp = (rndis_set_cmplt_type *) r->buf; - if (!resp) - return -ENOMEM; - -#if defined(DEBUG) && defined(DEBUG_VERBOSE) - if (buf_len) { - debug("set OID %08x value, len %d:\n", OID, buf_len); - for (i = 0; i < buf_len; i += 16) { - debug("%03d: %08x %08x %08x %08x\n", i, - get_unaligned_le32(&buf[i]), - get_unaligned_le32(&buf[i + 4]), - get_unaligned_le32(&buf[i + 8]), - get_unaligned_le32(&buf[i + 12])); - } - } -#endif - - params = &rndis_per_dev_params[configNr]; - switch (OID) { - case OID_GEN_CURRENT_PACKET_FILTER: - - /* - * these NDIS_PACKET_TYPE_* bitflags are shared with - * cdc_filter; it's not RNDIS-specific - * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in: - * PROMISCUOUS, DIRECTED, - * MULTICAST, ALL_MULTICAST, BROADCAST - */ - *params->filter = (u16) get_unaligned_le32(buf); - debug("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", - __func__, *params->filter); - - /* - * this call has a significant side effect: it's - * what makes the packet flow start and stop, like - * activating the CDC Ethernet altsetting. - */ -#ifdef RNDIS_PM -update_linkstate: -#endif - retval = 0; - if (*params->filter) - params->state = RNDIS_DATA_INITIALIZED; - else - params->state = RNDIS_INITIALIZED; - break; - - case OID_802_3_MULTICAST_LIST: - /* I think we can ignore this */ - debug("%s: OID_802_3_MULTICAST_LIST\n", __func__); - retval = 0; - break; -#if 0 - case OID_GEN_RNDIS_CONFIG_PARAMETER: - { - struct rndis_config_parameter *param; - param = (struct rndis_config_parameter *) buf; - debug("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n", - __func__, - min(cpu_to_le32(param->ParameterNameLength), 80), - buf + param->ParameterNameOffset); - retval = 0; - } - break; -#endif - -#ifdef RNDIS_PM - case OID_PNP_SET_POWER: - /* - * The only real power state is USB suspend, and RNDIS requests - * can't enter it; this one isn't really about power. After - * resuming, Windows forces a reset, and then SET_POWER D0. - * FIXME ... then things go batty; Windows wedges itself. - */ - i = get_unaligned_le32(buf); - debug("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1); - switch (i) { - case NdisDeviceStateD0: - *params->filter = params->saved_filter; - goto update_linkstate; - case NdisDeviceStateD3: - case NdisDeviceStateD2: - case NdisDeviceStateD1: - params->saved_filter = *params->filter; - retval = 0; - break; - } - break; - -#ifdef RNDIS_WAKEUP - /* - * no wakeup support advertised, so wakeup OIDs always fail: - * - OID_PNP_ENABLE_WAKE_UP - * - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN - */ -#endif - -#endif /* RNDIS_PM */ - - default: - debug("%s: set unknown OID 0x%08X, size %d\n", - __func__, OID, buf_len); - } - - return retval; -} - -/* - * Response Functions - */ - -static int rndis_init_response(int configNr, rndis_init_msg_type *buf) -{ - rndis_init_cmplt_type *resp; - rndis_resp_t *r; - - if (!rndis_per_dev_params[configNr].dev) - return -ENOTSUPP; - - r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type)); - if (!r) - return -ENOMEM; - resp = (rndis_init_cmplt_type *) r->buf; - - resp->MessageType = __constant_cpu_to_le32( - REMOTE_NDIS_INITIALIZE_CMPLT); - resp->MessageLength = __constant_cpu_to_le32(52); - resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */ - resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS); - resp->MajorVersion = __constant_cpu_to_le32(RNDIS_MAJOR_VERSION); - resp->MinorVersion = __constant_cpu_to_le32(RNDIS_MINOR_VERSION); - resp->DeviceFlags = __constant_cpu_to_le32(RNDIS_DF_CONNECTIONLESS); - resp->Medium = __constant_cpu_to_le32(RNDIS_MEDIUM_802_3); - resp->MaxPacketsPerTransfer = __constant_cpu_to_le32(1); - resp->MaxTransferSize = cpu_to_le32( - rndis_per_dev_params[configNr].mtu - + ETHER_HDR_SIZE - + sizeof(struct rndis_packet_msg_type) - + 22); - resp->PacketAlignmentFactor = __constant_cpu_to_le32(0); - resp->AFListOffset = __constant_cpu_to_le32(0); - resp->AFListSize = __constant_cpu_to_le32(0); - - if (rndis_per_dev_params[configNr].ack) - rndis_per_dev_params[configNr].ack( - rndis_per_dev_params[configNr].dev); - - return 0; -} - -static int rndis_query_response(int configNr, rndis_query_msg_type *buf) -{ - rndis_query_cmplt_type *resp; - rndis_resp_t *r; - - debug("%s: OID = %08X\n", __func__, get_unaligned_le32(&buf->OID)); - if (!rndis_per_dev_params[configNr].dev) - return -ENOTSUPP; - - /* - * we need more memory: - * gen_ndis_query_resp expects enough space for - * rndis_query_cmplt_type followed by data. - * oid_supported_list is the largest data reply - */ - r = rndis_add_response(configNr, - sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type)); - if (!r) - return -ENOMEM; - resp = (rndis_query_cmplt_type *) r->buf; - - resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_QUERY_CMPLT); - resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */ - - if (gen_ndis_query_resp(configNr, get_unaligned_le32(&buf->OID), - get_unaligned_le32(&buf->InformationBufferOffset) - + 8 + (u8 *) buf, - get_unaligned_le32(&buf->InformationBufferLength), - r)) { - /* OID not supported */ - resp->Status = __constant_cpu_to_le32( - RNDIS_STATUS_NOT_SUPPORTED); - resp->MessageLength = __constant_cpu_to_le32(sizeof *resp); - resp->InformationBufferLength = __constant_cpu_to_le32(0); - resp->InformationBufferOffset = __constant_cpu_to_le32(0); - } else - resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS); - - if (rndis_per_dev_params[configNr].ack) - rndis_per_dev_params[configNr].ack( - rndis_per_dev_params[configNr].dev); - return 0; -} - -static int rndis_set_response(int configNr, rndis_set_msg_type *buf) -{ - u32 BufLength, BufOffset; - rndis_set_cmplt_type *resp; - rndis_resp_t *r; - - r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type)); - if (!r) - return -ENOMEM; - resp = (rndis_set_cmplt_type *) r->buf; - - BufLength = get_unaligned_le32(&buf->InformationBufferLength); - BufOffset = get_unaligned_le32(&buf->InformationBufferOffset); - -#ifdef VERBOSE - debug("%s: Length: %d\n", __func__, BufLength); - debug("%s: Offset: %d\n", __func__, BufOffset); - debug("%s: InfoBuffer: ", __func__); - - for (i = 0; i < BufLength; i++) - debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); - - debug("\n"); -#endif - - resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_SET_CMPLT); - resp->MessageLength = __constant_cpu_to_le32(16); - resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */ - if (gen_ndis_set_resp(configNr, get_unaligned_le32(&buf->OID), - ((u8 *) buf) + 8 + BufOffset, BufLength, r)) - resp->Status = __constant_cpu_to_le32( - RNDIS_STATUS_NOT_SUPPORTED); - else - resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS); - - if (rndis_per_dev_params[configNr].ack) - rndis_per_dev_params[configNr].ack( - rndis_per_dev_params[configNr].dev); - - return 0; -} - -static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf) -{ - rndis_reset_cmplt_type *resp; - rndis_resp_t *r; - - r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type)); - if (!r) - return -ENOMEM; - resp = (rndis_reset_cmplt_type *) r->buf; - - resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_RESET_CMPLT); - resp->MessageLength = __constant_cpu_to_le32(16); - resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS); - /* resent information */ - resp->AddressingReset = __constant_cpu_to_le32(1); - - if (rndis_per_dev_params[configNr].ack) - rndis_per_dev_params[configNr].ack( - rndis_per_dev_params[configNr].dev); - - return 0; -} - -static int rndis_keepalive_response(int configNr, - rndis_keepalive_msg_type *buf) -{ - rndis_keepalive_cmplt_type *resp; - rndis_resp_t *r; - - /* host "should" check only in RNDIS_DATA_INITIALIZED state */ - - r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type)); - if (!r) - return -ENOMEM; - resp = (rndis_keepalive_cmplt_type *) r->buf; - - resp->MessageType = __constant_cpu_to_le32( - REMOTE_NDIS_KEEPALIVE_CMPLT); - resp->MessageLength = __constant_cpu_to_le32(16); - resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */ - resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS); - - if (rndis_per_dev_params[configNr].ack) - rndis_per_dev_params[configNr].ack( - rndis_per_dev_params[configNr].dev); - - return 0; -} - - -/* - * Device to Host Comunication - */ -static int rndis_indicate_status_msg(int configNr, u32 status) -{ - rndis_indicate_status_msg_type *resp; - rndis_resp_t *r; - - if (rndis_per_dev_params[configNr].state == RNDIS_UNINITIALIZED) - return -ENOTSUPP; - - r = rndis_add_response(configNr, - sizeof(rndis_indicate_status_msg_type)); - if (!r) - return -ENOMEM; - resp = (rndis_indicate_status_msg_type *) r->buf; - - resp->MessageType = __constant_cpu_to_le32( - REMOTE_NDIS_INDICATE_STATUS_MSG); - resp->MessageLength = __constant_cpu_to_le32(20); - resp->Status = cpu_to_le32(status); - resp->StatusBufferLength = __constant_cpu_to_le32(0); - resp->StatusBufferOffset = __constant_cpu_to_le32(0); - - if (rndis_per_dev_params[configNr].ack) - rndis_per_dev_params[configNr].ack( - rndis_per_dev_params[configNr].dev); - return 0; -} - -int rndis_signal_connect(int configNr) -{ - rndis_per_dev_params[configNr].media_state - = NDIS_MEDIA_STATE_CONNECTED; - return rndis_indicate_status_msg(configNr, - RNDIS_STATUS_MEDIA_CONNECT); -} - -int rndis_signal_disconnect(int configNr) -{ - rndis_per_dev_params[configNr].media_state - = NDIS_MEDIA_STATE_DISCONNECTED; - -#ifdef RNDIS_COMPLETE_SIGNAL_DISCONNECT - return rndis_indicate_status_msg(configNr, - RNDIS_STATUS_MEDIA_DISCONNECT); -#else - return 0; -#endif -} - -void rndis_uninit(int configNr) -{ - u8 *buf; - u32 length; - - if (configNr >= RNDIS_MAX_CONFIGS) - return; - rndis_per_dev_params[configNr].used = 0; - rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED; - - /* drain the response queue */ - while ((buf = rndis_get_next_response(configNr, &length))) - rndis_free_response(configNr, buf); -} - -void rndis_set_host_mac(int configNr, const u8 *addr) -{ - rndis_per_dev_params[configNr].host_mac = addr; -} - -enum rndis_state rndis_get_state(int configNr) -{ - if (configNr >= RNDIS_MAX_CONFIGS || configNr < 0) - return -ENOTSUPP; - return rndis_per_dev_params[configNr].state; -} - -/* - * Message Parser - */ -int rndis_msg_parser(u8 configNr, u8 *buf) -{ - u32 MsgType, MsgLength; - __le32 *tmp; - struct rndis_params *params; - - debug("%s: configNr = %d, %p\n", __func__, configNr, buf); - - if (!buf) - return -ENOMEM; - - tmp = (__le32 *) buf; - MsgType = get_unaligned_le32(tmp++); - MsgLength = get_unaligned_le32(tmp++); - - if (configNr >= RNDIS_MAX_CONFIGS) - return -ENOTSUPP; - params = &rndis_per_dev_params[configNr]; - - /* - * NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for - * rx/tx statistics and link status, in addition to KEEPALIVE traffic - * and normal HC level polling to see if there's any IN traffic. - */ - - /* For USB: responses may take up to 10 seconds */ - switch (MsgType) { - case REMOTE_NDIS_INITIALIZE_MSG: - debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n", __func__); - params->state = RNDIS_INITIALIZED; - return rndis_init_response(configNr, - (rndis_init_msg_type *) buf); - - case REMOTE_NDIS_HALT_MSG: - debug("%s: REMOTE_NDIS_HALT_MSG\n", __func__); - params->state = RNDIS_UNINITIALIZED; - return 0; - - case REMOTE_NDIS_QUERY_MSG: - return rndis_query_response(configNr, - (rndis_query_msg_type *) buf); - - case REMOTE_NDIS_SET_MSG: - return rndis_set_response(configNr, - (rndis_set_msg_type *) buf); - - case REMOTE_NDIS_RESET_MSG: - debug("%s: REMOTE_NDIS_RESET_MSG\n", __func__); - return rndis_reset_response(configNr, - (rndis_reset_msg_type *) buf); - - case REMOTE_NDIS_KEEPALIVE_MSG: - /* For USB: host does this every 5 seconds */ -#if defined(DEBUG) && defined(DEBUG_VERBOSE) - debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", __func__); -#endif - return rndis_keepalive_response(configNr, - (rndis_keepalive_msg_type *) buf); - - default: - /* - * At least Windows XP emits some undefined RNDIS messages. - * In one case those messages seemed to relate to the host - * suspending itself. - */ - debug("%s: unknown RNDIS message 0x%08X len %d\n", - __func__ , MsgType, MsgLength); - { - unsigned i; - for (i = 0; i < MsgLength; i += 16) { - debug("%03d: " - " %02x %02x %02x %02x" - " %02x %02x %02x %02x" - " %02x %02x %02x %02x" - " %02x %02x %02x %02x" - "\n", - i, - buf[i], buf[i+1], - buf[i+2], buf[i+3], - buf[i+4], buf[i+5], - buf[i+6], buf[i+7], - buf[i+8], buf[i+9], - buf[i+10], buf[i+11], - buf[i+12], buf[i+13], - buf[i+14], buf[i+15]); - } - } - break; - } - - return -ENOTSUPP; -} - -int rndis_register(int (*rndis_control_ack)(struct eth_device *)) -{ - u8 i; - - for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { - if (!rndis_per_dev_params[i].used) { - rndis_per_dev_params[i].used = 1; - rndis_per_dev_params[i].ack = rndis_control_ack; - debug("%s: configNr = %d\n", __func__, i); - return i; - } - } - debug("%s failed\n", __func__); - - return -1; -} - -void rndis_deregister(int configNr) -{ - debug("%s: configNr = %d\n", __func__, configNr); - - if (configNr >= RNDIS_MAX_CONFIGS) - return; - rndis_per_dev_params[configNr].used = 0; - - return; -} - -int rndis_set_param_dev(u8 configNr, struct eth_device *dev, int mtu, - struct net_device_stats *stats, u16 *cdc_filter) -{ - debug("%s: configNr = %d\n", __func__, configNr); - if (!dev || !stats) - return -1; - if (configNr >= RNDIS_MAX_CONFIGS) - return -1; - - rndis_per_dev_params[configNr].dev = dev; - rndis_per_dev_params[configNr].stats = stats; - rndis_per_dev_params[configNr].mtu = mtu; - rndis_per_dev_params[configNr].filter = cdc_filter; - - return 0; -} - -int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr) -{ - debug("%s: configNr = %d\n", __func__, configNr); - if (!vendorDescr) - return -1; - if (configNr >= RNDIS_MAX_CONFIGS) - return -1; - - rndis_per_dev_params[configNr].vendorID = vendorID; - rndis_per_dev_params[configNr].vendorDescr = vendorDescr; - - return 0; -} - -int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed) -{ - debug("%s: configNr = %d, %u %u\n", __func__, configNr, medium, speed); - if (configNr >= RNDIS_MAX_CONFIGS) - return -1; - - rndis_per_dev_params[configNr].medium = medium; - rndis_per_dev_params[configNr].speed = speed; - - return 0; -} - -void rndis_add_hdr(void *buf, int length) -{ - struct rndis_packet_msg_type *header; - - header = buf; - memset(header, 0, sizeof *header); - header->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG); - header->MessageLength = cpu_to_le32(length + sizeof *header); - header->DataOffset = __constant_cpu_to_le32(36); - header->DataLength = cpu_to_le32(length); -} - -void rndis_free_response(int configNr, u8 *buf) -{ - rndis_resp_t *r; - struct list_head *act, *tmp; - - list_for_each_safe(act, tmp, - &(rndis_per_dev_params[configNr].resp_queue)) - { - r = list_entry(act, rndis_resp_t, list); - if (r && r->buf == buf) { - list_del(&r->list); - free(r); - } - } -} - -u8 *rndis_get_next_response(int configNr, u32 *length) -{ - rndis_resp_t *r; - struct list_head *act, *tmp; - - if (!length) - return NULL; - - list_for_each_safe(act, tmp, - &(rndis_per_dev_params[configNr].resp_queue)) - { - r = list_entry(act, rndis_resp_t, list); - if (!r->send) { - r->send = 1; - *length = r->length; - return r->buf; - } - } - - return NULL; -} - -static rndis_resp_t *rndis_add_response(int configNr, u32 length) -{ - rndis_resp_t *r; - - /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */ - r = malloc(sizeof(rndis_resp_t) + length); - if (!r) - return NULL; - - r->buf = (u8 *) (r + 1); - r->length = length; - r->send = 0; - - list_add_tail(&r->list, - &(rndis_per_dev_params[configNr].resp_queue)); - return r; -} - -int rndis_rm_hdr(void *buf, int length) -{ - /* tmp points to a struct rndis_packet_msg_type */ - __le32 *tmp = buf; - int offs, len; - - /* MessageType, MessageLength */ - if (__constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG) - != get_unaligned(tmp++)) - return -EINVAL; - tmp++; - - /* DataOffset, DataLength */ - offs = get_unaligned_le32(tmp++) + 8 /* offset of DataOffset */; - if (offs != sizeof(struct rndis_packet_msg_type)) - debug("%s: unexpected DataOffset: %d\n", __func__, offs); - if (offs >= length) - return -EOVERFLOW; - - len = get_unaligned_le32(tmp++); - if (len + sizeof(struct rndis_packet_msg_type) != length) - debug("%s: unexpected DataLength: %d, packet length=%d\n", - __func__, len, length); - - memmove(buf, buf + offs, len); - - return offs; -} - -int rndis_init(void) -{ - u8 i; - - for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { - rndis_per_dev_params[i].confignr = i; - rndis_per_dev_params[i].used = 0; - rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED; - rndis_per_dev_params[i].media_state - = NDIS_MEDIA_STATE_DISCONNECTED; - INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue)); - } - - return 0; -} - -void rndis_exit(void) -{ - /* Nothing to do */ -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/rndis.h b/qemu/roms/u-boot/drivers/usb/gadget/rndis.h deleted file mode 100644 index d9e3a7528..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/rndis.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * RNDIS Definitions for Remote NDIS - * - * Authors: Benedikt Spranger, Pengutronix - * Robert Schwebel, Pengutronix - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2, as published by the Free Software Foundation. - * - * This software was originally developed in conformance with - * Microsoft's Remote NDIS Specification License Agreement. - */ - -#ifndef _USBGADGET_RNDIS_H -#define _USBGADGET_RNDIS_H - -#include "ndis.h" - -/* - * By default rndis_signal_disconnect does not send status message about - * RNDIS disconnection to USB host (indicated as cable disconnected). - * Define RNDIS_COMPLETE_SIGNAL_DISCONNECT to send it. - * However, this will cause 1 sec delay on Ethernet device halt. - * Usually you do not need to define it. Mostly usable for debugging. - */ - -#define RNDIS_MAXIMUM_FRAME_SIZE 1518 -#define RNDIS_MAX_TOTAL_SIZE 1558 - -/* Remote NDIS Versions */ -#define RNDIS_MAJOR_VERSION 1 -#define RNDIS_MINOR_VERSION 0 - -/* Status Values */ -#define RNDIS_STATUS_SUCCESS 0x00000000U /* Success */ -#define RNDIS_STATUS_FAILURE 0xC0000001U /* Unspecified error */ -#define RNDIS_STATUS_INVALID_DATA 0xC0010015U /* Invalid data */ -#define RNDIS_STATUS_NOT_SUPPORTED 0xC00000BBU /* Unsupported request */ -#define RNDIS_STATUS_MEDIA_CONNECT 0x4001000BU /* Device connected */ -#define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000CU /* Device disconnected */ -/* - * For all not specified status messages: - * RNDIS_STATUS_Xxx -> NDIS_STATUS_Xxx - */ - -/* Message Set for Connectionless (802.3) Devices */ -#define REMOTE_NDIS_PACKET_MSG 0x00000001U -#define REMOTE_NDIS_INITIALIZE_MSG 0x00000002U /* Initialize device */ -#define REMOTE_NDIS_HALT_MSG 0x00000003U -#define REMOTE_NDIS_QUERY_MSG 0x00000004U -#define REMOTE_NDIS_SET_MSG 0x00000005U -#define REMOTE_NDIS_RESET_MSG 0x00000006U -#define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007U -#define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008U - -/* Message completion */ -#define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002U -#define REMOTE_NDIS_QUERY_CMPLT 0x80000004U -#define REMOTE_NDIS_SET_CMPLT 0x80000005U -#define REMOTE_NDIS_RESET_CMPLT 0x80000006U -#define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008U - -/* Device Flags */ -#define RNDIS_DF_CONNECTIONLESS 0x00000001U -#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002U - -#define RNDIS_MEDIUM_802_3 0x00000000U - -/* from drivers/net/sk98lin/h/skgepnmi.h */ -#define OID_PNP_CAPABILITIES 0xFD010100 -#define OID_PNP_SET_POWER 0xFD010101 -#define OID_PNP_QUERY_POWER 0xFD010102 -#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 -#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 -#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 - - -typedef struct rndis_init_msg_type { - __le32 MessageType; - __le32 MessageLength; - __le32 RequestID; - __le32 MajorVersion; - __le32 MinorVersion; - __le32 MaxTransferSize; -} rndis_init_msg_type; - -typedef struct rndis_init_cmplt_type { - __le32 MessageType; - __le32 MessageLength; - __le32 RequestID; - __le32 Status; - __le32 MajorVersion; - __le32 MinorVersion; - __le32 DeviceFlags; - __le32 Medium; - __le32 MaxPacketsPerTransfer; - __le32 MaxTransferSize; - __le32 PacketAlignmentFactor; - __le32 AFListOffset; - __le32 AFListSize; -} rndis_init_cmplt_type; - -typedef struct rndis_halt_msg_type { - __le32 MessageType; - __le32 MessageLength; - __le32 RequestID; -} rndis_halt_msg_type; - -typedef struct rndis_query_msg_type { - __le32 MessageType; - __le32 MessageLength; - __le32 RequestID; - __le32 OID; - __le32 InformationBufferLength; - __le32 InformationBufferOffset; - __le32 DeviceVcHandle; -} rndis_query_msg_type; - -typedef struct rndis_query_cmplt_type { - __le32 MessageType; - __le32 MessageLength; - __le32 RequestID; - __le32 Status; - __le32 InformationBufferLength; - __le32 InformationBufferOffset; -} rndis_query_cmplt_type; - -typedef struct rndis_set_msg_type { - __le32 MessageType; - __le32 MessageLength; - __le32 RequestID; - __le32 OID; - __le32 InformationBufferLength; - __le32 InformationBufferOffset; - __le32 DeviceVcHandle; -} rndis_set_msg_type; - -typedef struct rndis_set_cmplt_type { - __le32 MessageType; - __le32 MessageLength; - __le32 RequestID; - __le32 Status; -} rndis_set_cmplt_type; - -typedef struct rndis_reset_msg_type { - __le32 MessageType; - __le32 MessageLength; - __le32 Reserved; -} rndis_reset_msg_type; - -typedef struct rndis_reset_cmplt_type { - __le32 MessageType; - __le32 MessageLength; - __le32 Status; - __le32 AddressingReset; -} rndis_reset_cmplt_type; - -typedef struct rndis_indicate_status_msg_type { - __le32 MessageType; - __le32 MessageLength; - __le32 Status; - __le32 StatusBufferLength; - __le32 StatusBufferOffset; -} rndis_indicate_status_msg_type; - -typedef struct rndis_keepalive_msg_type { - __le32 MessageType; - __le32 MessageLength; - __le32 RequestID; -} rndis_keepalive_msg_type; - -typedef struct rndis_keepalive_cmplt_type { - __le32 MessageType; - __le32 MessageLength; - __le32 RequestID; - __le32 Status; -} rndis_keepalive_cmplt_type; - -struct rndis_packet_msg_type { - __le32 MessageType; - __le32 MessageLength; - __le32 DataOffset; - __le32 DataLength; - __le32 OOBDataOffset; - __le32 OOBDataLength; - __le32 NumOOBDataElements; - __le32 PerPacketInfoOffset; - __le32 PerPacketInfoLength; - __le32 VcHandle; - __le32 Reserved; -} __attribute__ ((packed)); - -struct rndis_config_parameter { - __le32 ParameterNameOffset; - __le32 ParameterNameLength; - __le32 ParameterType; - __le32 ParameterValueOffset; - __le32 ParameterValueLength; -}; - -/* implementation specific */ -enum rndis_state { - RNDIS_UNINITIALIZED, - RNDIS_INITIALIZED, - RNDIS_DATA_INITIALIZED, -}; - -typedef struct rndis_resp_t { - struct list_head list; - u8 *buf; - u32 length; - int send; -} rndis_resp_t; - -typedef struct rndis_params { - u8 confignr; - u8 used; - u16 saved_filter; - enum rndis_state state; - u32 medium; - u32 speed; - u32 media_state; - - const u8 *host_mac; - u16 *filter; - struct eth_device *dev; - struct net_device_stats *stats; - int mtu; - - u32 vendorID; - const char *vendorDescr; - int (*ack)(struct eth_device *); - struct list_head resp_queue; -} rndis_params; - -/* RNDIS Message parser and other useless functions */ -int rndis_msg_parser(u8 configNr, u8 *buf); -enum rndis_state rndis_get_state(int configNr); -int rndis_register(int (*rndis_control_ack)(struct eth_device *)); -void rndis_deregister(int configNr); -int rndis_set_param_dev(u8 configNr, struct eth_device *dev, int mtu, - struct net_device_stats *stats, u16 *cdc_filter); -int rndis_set_param_vendor(u8 configNr, u32 vendorID, - const char *vendorDescr); -int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed); -void rndis_add_hdr(void *bug, int length); -int rndis_rm_hdr(void *bug, int length); -u8 *rndis_get_next_response(int configNr, u32 *length); -void rndis_free_response(int configNr, u8 *buf); - -void rndis_uninit(int configNr); -int rndis_signal_connect(int configNr); -int rndis_signal_disconnect(int configNr); -extern void rndis_set_host_mac(int configNr, const u8 *addr); - -int rndis_init(void); -void rndis_exit(void); - -#endif /* _USBGADGET_RNDIS_H */ diff --git a/qemu/roms/u-boot/drivers/usb/gadget/s3c_udc_otg.c b/qemu/roms/u-boot/drivers/usb/gadget/s3c_udc_otg.c deleted file mode 100644 index 63d4487a9..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/s3c_udc_otg.c +++ /dev/null @@ -1,890 +0,0 @@ -/* - * drivers/usb/gadget/s3c_udc_otg.c - * Samsung S3C on-chip full/high speed USB OTG 2.0 device controllers - * - * Copyright (C) 2008 for Samsung Electronics - * - * BSP Support for Samsung's UDC driver - * available at: - * git://git.kernel.org/pub/scm/linux/kernel/git/kki_ap/linux-2.6-samsung.git - * - * State machine bugfixes: - * Marek Szyprowski <m.szyprowski@samsung.com> - * - * Ported to u-boot: - * Marek Szyprowski <m.szyprowski@samsung.com> - * Lukasz Majewski <l.majewski@samsumg.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#undef DEBUG -#include <common.h> -#include <asm/errno.h> -#include <linux/list.h> -#include <malloc.h> - -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> - -#include <asm/byteorder.h> -#include <asm/unaligned.h> -#include <asm/io.h> - -#include <asm/mach-types.h> -#include <asm/arch/gpio.h> - -#include "regs-otg.h" -#include <usb/lin_gadget_compat.h> - -/***********************************************************/ - -#define OTG_DMA_MODE 1 - -#define DEBUG_SETUP 0 -#define DEBUG_EP0 0 -#define DEBUG_ISR 0 -#define DEBUG_OUT_EP 0 -#define DEBUG_IN_EP 0 - -#include <usb/s3c_udc.h> - -#define EP0_CON 0 -#define EP_MASK 0xF - -static char *state_names[] = { - "WAIT_FOR_SETUP", - "DATA_STATE_XMIT", - "DATA_STATE_NEED_ZLP", - "WAIT_FOR_OUT_STATUS", - "DATA_STATE_RECV", - "WAIT_FOR_COMPLETE", - "WAIT_FOR_OUT_COMPLETE", - "WAIT_FOR_IN_COMPLETE", - "WAIT_FOR_NULL_COMPLETE", -}; - -#define DRIVER_DESC "S3C HS USB OTG Device Driver, (c) Samsung Electronics" -#define DRIVER_VERSION "15 March 2009" - -struct s3c_udc *the_controller; - -static const char driver_name[] = "s3c-udc"; -static const char driver_desc[] = DRIVER_DESC; -static const char ep0name[] = "ep0-control"; - -/* Max packet size*/ -static unsigned int ep0_fifo_size = 64; -static unsigned int ep_fifo_size = 512; -static unsigned int ep_fifo_size2 = 1024; -static int reset_available = 1; - -static struct usb_ctrlrequest *usb_ctrl; -static dma_addr_t usb_ctrl_dma_addr; - -/* - Local declarations. -*/ -static int s3c_ep_enable(struct usb_ep *ep, - const struct usb_endpoint_descriptor *); -static int s3c_ep_disable(struct usb_ep *ep); -static struct usb_request *s3c_alloc_request(struct usb_ep *ep, - gfp_t gfp_flags); -static void s3c_free_request(struct usb_ep *ep, struct usb_request *); - -static int s3c_queue(struct usb_ep *ep, struct usb_request *, gfp_t gfp_flags); -static int s3c_dequeue(struct usb_ep *ep, struct usb_request *); -static int s3c_fifo_status(struct usb_ep *ep); -static void s3c_fifo_flush(struct usb_ep *ep); -static void s3c_ep0_read(struct s3c_udc *dev); -static void s3c_ep0_kick(struct s3c_udc *dev, struct s3c_ep *ep); -static void s3c_handle_ep0(struct s3c_udc *dev); -static int s3c_ep0_write(struct s3c_udc *dev); -static int write_fifo_ep0(struct s3c_ep *ep, struct s3c_request *req); -static void done(struct s3c_ep *ep, struct s3c_request *req, int status); -static void stop_activity(struct s3c_udc *dev, - struct usb_gadget_driver *driver); -static int udc_enable(struct s3c_udc *dev); -static void udc_set_address(struct s3c_udc *dev, unsigned char address); -static void reconfig_usbd(void); -static void set_max_pktsize(struct s3c_udc *dev, enum usb_device_speed speed); -static void nuke(struct s3c_ep *ep, int status); -static int s3c_udc_set_halt(struct usb_ep *_ep, int value); -static void s3c_udc_set_nak(struct s3c_ep *ep); - -void set_udc_gadget_private_data(void *p) -{ - debug_cond(DEBUG_SETUP != 0, - "%s: the_controller: 0x%p, p: 0x%p\n", __func__, - the_controller, p); - the_controller->gadget.dev.device_data = p; -} - -void *get_udc_gadget_private_data(struct usb_gadget *gadget) -{ - return gadget->dev.device_data; -} - -static struct usb_ep_ops s3c_ep_ops = { - .enable = s3c_ep_enable, - .disable = s3c_ep_disable, - - .alloc_request = s3c_alloc_request, - .free_request = s3c_free_request, - - .queue = s3c_queue, - .dequeue = s3c_dequeue, - - .set_halt = s3c_udc_set_halt, - .fifo_status = s3c_fifo_status, - .fifo_flush = s3c_fifo_flush, -}; - -#define create_proc_files() do {} while (0) -#define remove_proc_files() do {} while (0) - -/***********************************************************/ - -void __iomem *regs_otg; -struct s3c_usbotg_reg *reg; -struct s3c_usbotg_phy *phy; -static unsigned int usb_phy_ctrl; - -void otg_phy_init(struct s3c_udc *dev) -{ - dev->pdata->phy_control(1); - - /*USB PHY0 Enable */ - printf("USB PHY0 Enable\n"); - - /* Enable PHY */ - writel(readl(usb_phy_ctrl) | USB_PHY_CTRL_EN0, usb_phy_ctrl); - - if (dev->pdata->usb_flags == PHY0_SLEEP) /* C210 Universal */ - writel((readl(&phy->phypwr) - &~(PHY_0_SLEEP | OTG_DISABLE_0 | ANALOG_PWRDOWN) - &~FORCE_SUSPEND_0), &phy->phypwr); - else /* C110 GONI */ - writel((readl(&phy->phypwr) &~(OTG_DISABLE_0 | ANALOG_PWRDOWN) - &~FORCE_SUSPEND_0), &phy->phypwr); - - if (s5p_cpu_id == 0x4412) - writel((readl(&phy->phyclk) & ~(EXYNOS4X12_ID_PULLUP0 | - EXYNOS4X12_COMMON_ON_N0)) | EXYNOS4X12_CLK_SEL_24MHZ, - &phy->phyclk); /* PLL 24Mhz */ - else - writel((readl(&phy->phyclk) & ~(ID_PULLUP0 | COMMON_ON_N0)) | - CLK_SEL_24MHZ, &phy->phyclk); /* PLL 24Mhz */ - - writel((readl(&phy->rstcon) &~(LINK_SW_RST | PHYLNK_SW_RST)) - | PHY_SW_RST0, &phy->rstcon); - udelay(10); - writel(readl(&phy->rstcon) - &~(PHY_SW_RST0 | LINK_SW_RST | PHYLNK_SW_RST), &phy->rstcon); - udelay(10); -} - -void otg_phy_off(struct s3c_udc *dev) -{ - /* reset controller just in case */ - writel(PHY_SW_RST0, &phy->rstcon); - udelay(20); - writel(readl(&phy->phypwr) &~PHY_SW_RST0, &phy->rstcon); - udelay(20); - - writel(readl(&phy->phypwr) | OTG_DISABLE_0 | ANALOG_PWRDOWN - | FORCE_SUSPEND_0, &phy->phypwr); - - writel(readl(usb_phy_ctrl) &~USB_PHY_CTRL_EN0, usb_phy_ctrl); - - writel((readl(&phy->phyclk) & ~(ID_PULLUP0 | COMMON_ON_N0)), - &phy->phyclk); - - udelay(10000); - - dev->pdata->phy_control(0); -} - -/***********************************************************/ - -#include "s3c_udc_otg_xfer_dma.c" - -/* - * udc_disable - disable USB device controller - */ -static void udc_disable(struct s3c_udc *dev) -{ - debug_cond(DEBUG_SETUP != 0, "%s: %p\n", __func__, dev); - - udc_set_address(dev, 0); - - dev->ep0state = WAIT_FOR_SETUP; - dev->gadget.speed = USB_SPEED_UNKNOWN; - dev->usb_address = 0; - - otg_phy_off(dev); -} - -/* - * udc_reinit - initialize software state - */ -static void udc_reinit(struct s3c_udc *dev) -{ - unsigned int i; - - debug_cond(DEBUG_SETUP != 0, "%s: %p\n", __func__, dev); - - /* device/ep0 records init */ - INIT_LIST_HEAD(&dev->gadget.ep_list); - INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); - dev->ep0state = WAIT_FOR_SETUP; - - /* basic endpoint records init */ - for (i = 0; i < S3C_MAX_ENDPOINTS; i++) { - struct s3c_ep *ep = &dev->ep[i]; - - if (i != 0) - list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); - - ep->desc = 0; - ep->stopped = 0; - INIT_LIST_HEAD(&ep->queue); - ep->pio_irqs = 0; - } - - /* the rest was statically initialized, and is read-only */ -} - -#define BYTES2MAXP(x) (x / 8) -#define MAXP2BYTES(x) (x * 8) - -/* until it's enabled, this UDC should be completely invisible - * to any USB host. - */ -static int udc_enable(struct s3c_udc *dev) -{ - debug_cond(DEBUG_SETUP != 0, "%s: %p\n", __func__, dev); - - otg_phy_init(dev); - reconfig_usbd(); - - debug_cond(DEBUG_SETUP != 0, - "S3C USB 2.0 OTG Controller Core Initialized : 0x%x\n", - readl(®->gintmsk)); - - dev->gadget.speed = USB_SPEED_UNKNOWN; - - return 0; -} - -/* - Register entry point for the peripheral controller driver. -*/ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) -{ - struct s3c_udc *dev = the_controller; - int retval = 0; - unsigned long flags; - - debug_cond(DEBUG_SETUP != 0, "%s: %s\n", __func__, "no name"); - - if (!driver - || (driver->speed != USB_SPEED_FULL - && driver->speed != USB_SPEED_HIGH) - || !driver->bind || !driver->disconnect || !driver->setup) - return -EINVAL; - if (!dev) - return -ENODEV; - if (dev->driver) - return -EBUSY; - - spin_lock_irqsave(&dev->lock, flags); - /* first hook up the driver ... */ - dev->driver = driver; - spin_unlock_irqrestore(&dev->lock, flags); - - if (retval) { /* TODO */ - printf("target device_add failed, error %d\n", retval); - return retval; - } - - retval = driver->bind(&dev->gadget); - if (retval) { - debug_cond(DEBUG_SETUP != 0, - "%s: bind to driver --> error %d\n", - dev->gadget.name, retval); - dev->driver = 0; - return retval; - } - - enable_irq(IRQ_OTG); - - debug_cond(DEBUG_SETUP != 0, - "Registered gadget driver %s\n", dev->gadget.name); - udc_enable(dev); - - return 0; -} - -/* - * Unregister entry point for the peripheral controller driver. - */ -int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -{ - struct s3c_udc *dev = the_controller; - unsigned long flags; - - if (!dev) - return -ENODEV; - if (!driver || driver != dev->driver) - return -EINVAL; - - spin_lock_irqsave(&dev->lock, flags); - dev->driver = 0; - stop_activity(dev, driver); - spin_unlock_irqrestore(&dev->lock, flags); - - driver->unbind(&dev->gadget); - - disable_irq(IRQ_OTG); - - udc_disable(dev); - return 0; -} - -/* - * done - retire a request; caller blocked irqs - */ -static void done(struct s3c_ep *ep, struct s3c_request *req, int status) -{ - unsigned int stopped = ep->stopped; - - debug("%s: %s %p, req = %p, stopped = %d\n", - __func__, ep->ep.name, ep, &req->req, stopped); - - list_del_init(&req->queue); - - if (likely(req->req.status == -EINPROGRESS)) - req->req.status = status; - else - status = req->req.status; - - if (status && status != -ESHUTDOWN) { - debug("complete %s req %p stat %d len %u/%u\n", - ep->ep.name, &req->req, status, - req->req.actual, req->req.length); - } - - /* don't modify queue heads during completion callback */ - ep->stopped = 1; - -#ifdef DEBUG - printf("calling complete callback\n"); - { - int i, len = req->req.length; - - printf("pkt[%d] = ", req->req.length); - if (len > 64) - len = 64; - for (i = 0; i < len; i++) { - printf("%02x", ((u8 *)req->req.buf)[i]); - if ((i & 7) == 7) - printf(" "); - } - printf("\n"); - } -#endif - spin_unlock(&ep->dev->lock); - req->req.complete(&ep->ep, &req->req); - spin_lock(&ep->dev->lock); - - debug("callback completed\n"); - - ep->stopped = stopped; -} - -/* - * nuke - dequeue ALL requests - */ -static void nuke(struct s3c_ep *ep, int status) -{ - struct s3c_request *req; - - debug("%s: %s %p\n", __func__, ep->ep.name, ep); - - /* called with irqs blocked */ - while (!list_empty(&ep->queue)) { - req = list_entry(ep->queue.next, struct s3c_request, queue); - done(ep, req, status); - } -} - -static void stop_activity(struct s3c_udc *dev, - struct usb_gadget_driver *driver) -{ - int i; - - /* don't disconnect drivers more than once */ - if (dev->gadget.speed == USB_SPEED_UNKNOWN) - driver = 0; - dev->gadget.speed = USB_SPEED_UNKNOWN; - - /* prevent new request submissions, kill any outstanding requests */ - for (i = 0; i < S3C_MAX_ENDPOINTS; i++) { - struct s3c_ep *ep = &dev->ep[i]; - ep->stopped = 1; - nuke(ep, -ESHUTDOWN); - } - - /* report disconnect; the driver is already quiesced */ - if (driver) { - spin_unlock(&dev->lock); - driver->disconnect(&dev->gadget); - spin_lock(&dev->lock); - } - - /* re-init driver-visible data structures */ - udc_reinit(dev); -} - -static void reconfig_usbd(void) -{ - /* 2. Soft-reset OTG Core and then unreset again. */ - int i; - unsigned int uTemp = writel(CORE_SOFT_RESET, ®->grstctl); - - debug("Reseting OTG controller\n"); - - writel(0<<15 /* PHY Low Power Clock sel*/ - |1<<14 /* Non-Periodic TxFIFO Rewind Enable*/ - |0x5<<10 /* Turnaround time*/ - |0<<9 | 0<<8 /* [0:HNP disable,1:HNP enable][ 0:SRP disable*/ - /* 1:SRP enable] H1= 1,1*/ - |0<<7 /* Ulpi DDR sel*/ - |0<<6 /* 0: high speed utmi+, 1: full speed serial*/ - |0<<4 /* 0: utmi+, 1:ulpi*/ - |1<<3 /* phy i/f 0:8bit, 1:16bit*/ - |0x7<<0, /* HS/FS Timeout**/ - ®->gusbcfg); - - /* 3. Put the OTG device core in the disconnected state.*/ - uTemp = readl(®->dctl); - uTemp |= SOFT_DISCONNECT; - writel(uTemp, ®->dctl); - - udelay(20); - - /* 4. Make the OTG device core exit from the disconnected state.*/ - uTemp = readl(®->dctl); - uTemp = uTemp & ~SOFT_DISCONNECT; - writel(uTemp, ®->dctl); - - /* 5. Configure OTG Core to initial settings of device mode.*/ - /* [][1: full speed(30Mhz) 0:high speed]*/ - writel(EP_MISS_CNT(1) | DEV_SPEED_HIGH_SPEED_20, ®->dcfg); - - mdelay(1); - - /* 6. Unmask the core interrupts*/ - writel(GINTMSK_INIT, ®->gintmsk); - - /* 7. Set NAK bit of EP0, EP1, EP2*/ - writel(DEPCTL_EPDIS|DEPCTL_SNAK, ®->out_endp[EP0_CON].doepctl); - writel(DEPCTL_EPDIS|DEPCTL_SNAK, ®->in_endp[EP0_CON].diepctl); - - for (i = 1; i < S3C_MAX_ENDPOINTS; i++) { - writel(DEPCTL_EPDIS|DEPCTL_SNAK, ®->out_endp[i].doepctl); - writel(DEPCTL_EPDIS|DEPCTL_SNAK, ®->in_endp[i].diepctl); - } - - /* 8. Unmask EPO interrupts*/ - writel(((1 << EP0_CON) << DAINT_OUT_BIT) - | (1 << EP0_CON), ®->daintmsk); - - /* 9. Unmask device OUT EP common interrupts*/ - writel(DOEPMSK_INIT, ®->doepmsk); - - /* 10. Unmask device IN EP common interrupts*/ - writel(DIEPMSK_INIT, ®->diepmsk); - - /* 11. Set Rx FIFO Size (in 32-bit words) */ - writel(RX_FIFO_SIZE >> 2, ®->grxfsiz); - - /* 12. Set Non Periodic Tx FIFO Size */ - writel((NPTX_FIFO_SIZE >> 2) << 16 | ((RX_FIFO_SIZE >> 2)) << 0, - ®->gnptxfsiz); - - for (i = 1; i < S3C_MAX_HW_ENDPOINTS; i++) - writel((PTX_FIFO_SIZE >> 2) << 16 | - ((RX_FIFO_SIZE + NPTX_FIFO_SIZE + - PTX_FIFO_SIZE*(i-1)) >> 2) << 0, - ®->dieptxf[i-1]); - - /* Flush the RX FIFO */ - writel(RX_FIFO_FLUSH, ®->grstctl); - while (readl(®->grstctl) & RX_FIFO_FLUSH) - debug("%s: waiting for S3C_UDC_OTG_GRSTCTL\n", __func__); - - /* Flush all the Tx FIFO's */ - writel(TX_FIFO_FLUSH_ALL, ®->grstctl); - writel(TX_FIFO_FLUSH_ALL | TX_FIFO_FLUSH, ®->grstctl); - while (readl(®->grstctl) & TX_FIFO_FLUSH) - debug("%s: waiting for S3C_UDC_OTG_GRSTCTL\n", __func__); - - /* 13. Clear NAK bit of EP0, EP1, EP2*/ - /* For Slave mode*/ - /* EP0: Control OUT */ - writel(DEPCTL_EPDIS | DEPCTL_CNAK, - ®->out_endp[EP0_CON].doepctl); - - /* 14. Initialize OTG Link Core.*/ - writel(GAHBCFG_INIT, ®->gahbcfg); -} - -static void set_max_pktsize(struct s3c_udc *dev, enum usb_device_speed speed) -{ - unsigned int ep_ctrl; - int i; - - if (speed == USB_SPEED_HIGH) { - ep0_fifo_size = 64; - ep_fifo_size = 512; - ep_fifo_size2 = 1024; - dev->gadget.speed = USB_SPEED_HIGH; - } else { - ep0_fifo_size = 64; - ep_fifo_size = 64; - ep_fifo_size2 = 64; - dev->gadget.speed = USB_SPEED_FULL; - } - - dev->ep[0].ep.maxpacket = ep0_fifo_size; - for (i = 1; i < S3C_MAX_ENDPOINTS; i++) - dev->ep[i].ep.maxpacket = ep_fifo_size; - - /* EP0 - Control IN (64 bytes)*/ - ep_ctrl = readl(®->in_endp[EP0_CON].diepctl); - writel(ep_ctrl|(0<<0), ®->in_endp[EP0_CON].diepctl); - - /* EP0 - Control OUT (64 bytes)*/ - ep_ctrl = readl(®->out_endp[EP0_CON].doepctl); - writel(ep_ctrl|(0<<0), ®->out_endp[EP0_CON].doepctl); -} - -static int s3c_ep_enable(struct usb_ep *_ep, - const struct usb_endpoint_descriptor *desc) -{ - struct s3c_ep *ep; - struct s3c_udc *dev; - unsigned long flags; - - debug("%s: %p\n", __func__, _ep); - - ep = container_of(_ep, struct s3c_ep, ep); - if (!_ep || !desc || ep->desc || _ep->name == ep0name - || desc->bDescriptorType != USB_DT_ENDPOINT - || ep->bEndpointAddress != desc->bEndpointAddress - || ep_maxpacket(ep) < - le16_to_cpu(get_unaligned(&desc->wMaxPacketSize))) { - - debug("%s: bad ep or descriptor\n", __func__); - return -EINVAL; - } - - /* xfer types must match, except that interrupt ~= bulk */ - if (ep->bmAttributes != desc->bmAttributes - && ep->bmAttributes != USB_ENDPOINT_XFER_BULK - && desc->bmAttributes != USB_ENDPOINT_XFER_INT) { - - debug("%s: %s type mismatch\n", __func__, _ep->name); - return -EINVAL; - } - - /* hardware _could_ do smaller, but driver doesn't */ - if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK - && le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)) != - ep_maxpacket(ep)) || !get_unaligned(&desc->wMaxPacketSize)) { - - debug("%s: bad %s maxpacket\n", __func__, _ep->name); - return -ERANGE; - } - - dev = ep->dev; - if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { - - debug("%s: bogus device state\n", __func__); - return -ESHUTDOWN; - } - - ep->stopped = 0; - ep->desc = desc; - ep->pio_irqs = 0; - ep->ep.maxpacket = le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)); - - /* Reset halt state */ - s3c_udc_set_nak(ep); - s3c_udc_set_halt(_ep, 0); - - spin_lock_irqsave(&ep->dev->lock, flags); - s3c_udc_ep_activate(ep); - spin_unlock_irqrestore(&ep->dev->lock, flags); - - debug("%s: enabled %s, stopped = %d, maxpacket = %d\n", - __func__, _ep->name, ep->stopped, ep->ep.maxpacket); - return 0; -} - -/* - * Disable EP - */ -static int s3c_ep_disable(struct usb_ep *_ep) -{ - struct s3c_ep *ep; - unsigned long flags; - - debug("%s: %p\n", __func__, _ep); - - ep = container_of(_ep, struct s3c_ep, ep); - if (!_ep || !ep->desc) { - debug("%s: %s not enabled\n", __func__, - _ep ? ep->ep.name : NULL); - return -EINVAL; - } - - spin_lock_irqsave(&ep->dev->lock, flags); - - /* Nuke all pending requests */ - nuke(ep, -ESHUTDOWN); - - ep->desc = 0; - ep->stopped = 1; - - spin_unlock_irqrestore(&ep->dev->lock, flags); - - debug("%s: disabled %s\n", __func__, _ep->name); - return 0; -} - -static struct usb_request *s3c_alloc_request(struct usb_ep *ep, - gfp_t gfp_flags) -{ - struct s3c_request *req; - - debug("%s: %s %p\n", __func__, ep->name, ep); - - req = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*req)); - if (!req) - return 0; - - memset(req, 0, sizeof *req); - INIT_LIST_HEAD(&req->queue); - - return &req->req; -} - -static void s3c_free_request(struct usb_ep *ep, struct usb_request *_req) -{ - struct s3c_request *req; - - debug("%s: %p\n", __func__, ep); - - req = container_of(_req, struct s3c_request, req); - WARN_ON(!list_empty(&req->queue)); - kfree(req); -} - -/* dequeue JUST ONE request */ -static int s3c_dequeue(struct usb_ep *_ep, struct usb_request *_req) -{ - struct s3c_ep *ep; - struct s3c_request *req; - unsigned long flags; - - debug("%s: %p\n", __func__, _ep); - - ep = container_of(_ep, struct s3c_ep, ep); - if (!_ep || ep->ep.name == ep0name) - return -EINVAL; - - spin_lock_irqsave(&ep->dev->lock, flags); - - /* make sure it's actually queued on this endpoint */ - list_for_each_entry(req, &ep->queue, queue) { - if (&req->req == _req) - break; - } - if (&req->req != _req) { - spin_unlock_irqrestore(&ep->dev->lock, flags); - return -EINVAL; - } - - done(ep, req, -ECONNRESET); - - spin_unlock_irqrestore(&ep->dev->lock, flags); - return 0; -} - -/* - * Return bytes in EP FIFO - */ -static int s3c_fifo_status(struct usb_ep *_ep) -{ - int count = 0; - struct s3c_ep *ep; - - ep = container_of(_ep, struct s3c_ep, ep); - if (!_ep) { - debug("%s: bad ep\n", __func__); - return -ENODEV; - } - - debug("%s: %d\n", __func__, ep_index(ep)); - - /* LPD can't report unclaimed bytes from IN fifos */ - if (ep_is_in(ep)) - return -EOPNOTSUPP; - - return count; -} - -/* - * Flush EP FIFO - */ -static void s3c_fifo_flush(struct usb_ep *_ep) -{ - struct s3c_ep *ep; - - ep = container_of(_ep, struct s3c_ep, ep); - if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { - debug("%s: bad ep\n", __func__); - return; - } - - debug("%s: %d\n", __func__, ep_index(ep)); -} - -static const struct usb_gadget_ops s3c_udc_ops = { - /* current versions must always be self-powered */ -}; - -static struct s3c_udc memory = { - .usb_address = 0, - .gadget = { - .ops = &s3c_udc_ops, - .ep0 = &memory.ep[0].ep, - .name = driver_name, - }, - - /* control endpoint */ - .ep[0] = { - .ep = { - .name = ep0name, - .ops = &s3c_ep_ops, - .maxpacket = EP0_FIFO_SIZE, - }, - .dev = &memory, - - .bEndpointAddress = 0, - .bmAttributes = 0, - - .ep_type = ep_control, - }, - - /* first group of endpoints */ - .ep[1] = { - .ep = { - .name = "ep1in-bulk", - .ops = &s3c_ep_ops, - .maxpacket = EP_FIFO_SIZE, - }, - .dev = &memory, - - .bEndpointAddress = USB_DIR_IN | 1, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - - .ep_type = ep_bulk_out, - .fifo_num = 1, - }, - - .ep[2] = { - .ep = { - .name = "ep2out-bulk", - .ops = &s3c_ep_ops, - .maxpacket = EP_FIFO_SIZE, - }, - .dev = &memory, - - .bEndpointAddress = USB_DIR_OUT | 2, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - - .ep_type = ep_bulk_in, - .fifo_num = 2, - }, - - .ep[3] = { - .ep = { - .name = "ep3in-int", - .ops = &s3c_ep_ops, - .maxpacket = EP_FIFO_SIZE, - }, - .dev = &memory, - - .bEndpointAddress = USB_DIR_IN | 3, - .bmAttributes = USB_ENDPOINT_XFER_INT, - - .ep_type = ep_interrupt, - .fifo_num = 3, - }, -}; - -/* - * probe - binds to the platform device - */ - -int s3c_udc_probe(struct s3c_plat_otg_data *pdata) -{ - struct s3c_udc *dev = &memory; - int retval = 0; - - debug("%s: %p\n", __func__, pdata); - - dev->pdata = pdata; - - phy = (struct s3c_usbotg_phy *)pdata->regs_phy; - reg = (struct s3c_usbotg_reg *)pdata->regs_otg; - usb_phy_ctrl = pdata->usb_phy_ctrl; - - /* regs_otg = (void *)pdata->regs_otg; */ - - dev->gadget.is_dualspeed = 1; /* Hack only*/ - dev->gadget.is_otg = 0; - dev->gadget.is_a_peripheral = 0; - dev->gadget.b_hnp_enable = 0; - dev->gadget.a_hnp_support = 0; - dev->gadget.a_alt_hnp_support = 0; - - the_controller = dev; - - usb_ctrl = memalign(CONFIG_SYS_CACHELINE_SIZE, - ROUND(sizeof(struct usb_ctrlrequest), - CONFIG_SYS_CACHELINE_SIZE)); - if (!usb_ctrl) { - error("No memory available for UDC!\n"); - return -ENOMEM; - } - - usb_ctrl_dma_addr = (dma_addr_t) usb_ctrl; - - udc_reinit(dev); - - return retval; -} - -int usb_gadget_handle_interrupts() -{ - u32 intr_status = readl(®->gintsts); - u32 gintmsk = readl(®->gintmsk); - - if (intr_status & gintmsk) - return s3c_udc_irq(1, (void *)the_controller); - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c b/qemu/roms/u-boot/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c deleted file mode 100644 index 06dfeed90..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c +++ /dev/null @@ -1,1480 +0,0 @@ -/* - * drivers/usb/gadget/s3c_udc_otg_xfer_dma.c - * Samsung S3C on-chip full/high speed USB OTG 2.0 device controllers - * - * Copyright (C) 2009 for Samsung Electronics - * - * BSP Support for Samsung's UDC driver - * available at: - * git://git.kernel.org/pub/scm/linux/kernel/git/kki_ap/linux-2.6-samsung.git - * - * State machine bugfixes: - * Marek Szyprowski <m.szyprowski@samsung.com> - * - * Ported to u-boot: - * Marek Szyprowski <m.szyprowski@samsung.com> - * Lukasz Majewski <l.majewski@samsumg.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -static u8 clear_feature_num; -int clear_feature_flag; - -/* Bulk-Only Mass Storage Reset (class-specific request) */ -#define GET_MAX_LUN_REQUEST 0xFE -#define BOT_RESET_REQUEST 0xFF - -static inline void s3c_udc_ep0_zlp(struct s3c_udc *dev) -{ - u32 ep_ctrl; - - writel(usb_ctrl_dma_addr, ®->in_endp[EP0_CON].diepdma); - writel(DIEPT_SIZ_PKT_CNT(1), ®->in_endp[EP0_CON].dieptsiz); - - ep_ctrl = readl(®->in_endp[EP0_CON].diepctl); - writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, - ®->in_endp[EP0_CON].diepctl); - - debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n", - __func__, readl(®->in_endp[EP0_CON].diepctl)); - dev->ep0state = WAIT_FOR_IN_COMPLETE; -} - -void s3c_udc_pre_setup(void) -{ - u32 ep_ctrl; - - debug_cond(DEBUG_IN_EP, - "%s : Prepare Setup packets.\n", __func__); - - writel(DOEPT_SIZ_PKT_CNT(1) | sizeof(struct usb_ctrlrequest), - ®->out_endp[EP0_CON].doeptsiz); - writel(usb_ctrl_dma_addr, ®->out_endp[EP0_CON].doepdma); - - ep_ctrl = readl(®->out_endp[EP0_CON].doepctl); - writel(ep_ctrl|DEPCTL_EPENA, ®->out_endp[EP0_CON].doepctl); - - debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n", - __func__, readl(®->in_endp[EP0_CON].diepctl)); - debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n", - __func__, readl(®->out_endp[EP0_CON].doepctl)); - -} - -static inline void s3c_ep0_complete_out(void) -{ - u32 ep_ctrl; - - debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n", - __func__, readl(®->in_endp[EP0_CON].diepctl)); - debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n", - __func__, readl(®->out_endp[EP0_CON].doepctl)); - - debug_cond(DEBUG_IN_EP, - "%s : Prepare Complete Out packet.\n", __func__); - - writel(DOEPT_SIZ_PKT_CNT(1) | sizeof(struct usb_ctrlrequest), - ®->out_endp[EP0_CON].doeptsiz); - writel(usb_ctrl_dma_addr, ®->out_endp[EP0_CON].doepdma); - - ep_ctrl = readl(®->out_endp[EP0_CON].doepctl); - writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, - ®->out_endp[EP0_CON].doepctl); - - debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n", - __func__, readl(®->in_endp[EP0_CON].diepctl)); - debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n", - __func__, readl(®->out_endp[EP0_CON].doepctl)); - -} - - -static int setdma_rx(struct s3c_ep *ep, struct s3c_request *req) -{ - u32 *buf, ctrl; - u32 length, pktcnt; - u32 ep_num = ep_index(ep); - - buf = req->req.buf + req->req.actual; - length = min(req->req.length - req->req.actual, - ep_num ? DMA_BUFFER_SIZE : ep->ep.maxpacket); - - ep->len = length; - ep->dma_buf = buf; - - if (ep_num == EP0_CON || length == 0) - pktcnt = 1; - else - pktcnt = (length - 1)/(ep->ep.maxpacket) + 1; - - ctrl = readl(®->out_endp[ep_num].doepctl); - - writel((unsigned int) ep->dma_buf, ®->out_endp[ep_num].doepdma); - writel(DOEPT_SIZ_PKT_CNT(pktcnt) | DOEPT_SIZ_XFER_SIZE(length), - ®->out_endp[ep_num].doeptsiz); - writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, ®->out_endp[ep_num].doepctl); - - debug_cond(DEBUG_OUT_EP != 0, - "%s: EP%d RX DMA start : DOEPDMA = 0x%x," - "DOEPTSIZ = 0x%x, DOEPCTL = 0x%x\n" - "\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n", - __func__, ep_num, - readl(®->out_endp[ep_num].doepdma), - readl(®->out_endp[ep_num].doeptsiz), - readl(®->out_endp[ep_num].doepctl), - buf, pktcnt, length); - return 0; - -} - -int setdma_tx(struct s3c_ep *ep, struct s3c_request *req) -{ - u32 *buf, ctrl = 0; - u32 length, pktcnt; - u32 ep_num = ep_index(ep); - - buf = req->req.buf + req->req.actual; - length = req->req.length - req->req.actual; - - if (ep_num == EP0_CON) - length = min(length, (u32)ep_maxpacket(ep)); - - ep->len = length; - ep->dma_buf = buf; - - flush_dcache_range((unsigned long) ep->dma_buf, - (unsigned long) ep->dma_buf + - ROUND(ep->len, CONFIG_SYS_CACHELINE_SIZE)); - - if (length == 0) - pktcnt = 1; - else - pktcnt = (length - 1)/(ep->ep.maxpacket) + 1; - - /* Flush the endpoint's Tx FIFO */ - writel(TX_FIFO_NUMBER(ep->fifo_num), ®->grstctl); - writel(TX_FIFO_NUMBER(ep->fifo_num) | TX_FIFO_FLUSH, ®->grstctl); - while (readl(®->grstctl) & TX_FIFO_FLUSH) - ; - - writel((unsigned long) ep->dma_buf, ®->in_endp[ep_num].diepdma); - writel(DIEPT_SIZ_PKT_CNT(pktcnt) | DIEPT_SIZ_XFER_SIZE(length), - ®->in_endp[ep_num].dieptsiz); - - ctrl = readl(®->in_endp[ep_num].diepctl); - - /* Write the FIFO number to be used for this endpoint */ - ctrl &= DIEPCTL_TX_FIFO_NUM_MASK; - ctrl |= DIEPCTL_TX_FIFO_NUM(ep->fifo_num); - - /* Clear reserved (Next EP) bits */ - ctrl = (ctrl&~(EP_MASK<<DEPCTL_NEXT_EP_BIT)); - - writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, ®->in_endp[ep_num].diepctl); - - debug_cond(DEBUG_IN_EP, - "%s:EP%d TX DMA start : DIEPDMA0 = 0x%x," - "DIEPTSIZ0 = 0x%x, DIEPCTL0 = 0x%x\n" - "\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n", - __func__, ep_num, - readl(®->in_endp[ep_num].diepdma), - readl(®->in_endp[ep_num].dieptsiz), - readl(®->in_endp[ep_num].diepctl), - buf, pktcnt, length); - - return length; -} - -static void complete_rx(struct s3c_udc *dev, u8 ep_num) -{ - struct s3c_ep *ep = &dev->ep[ep_num]; - struct s3c_request *req = NULL; - u32 ep_tsr = 0, xfer_size = 0, is_short = 0; - - if (list_empty(&ep->queue)) { - debug_cond(DEBUG_OUT_EP != 0, - "%s: RX DMA done : NULL REQ on OUT EP-%d\n", - __func__, ep_num); - return; - - } - - req = list_entry(ep->queue.next, struct s3c_request, queue); - ep_tsr = readl(®->out_endp[ep_num].doeptsiz); - - if (ep_num == EP0_CON) - xfer_size = (ep_tsr & DOEPT_SIZ_XFER_SIZE_MAX_EP0); - else - xfer_size = (ep_tsr & DOEPT_SIZ_XFER_SIZE_MAX_EP); - - xfer_size = ep->len - xfer_size; - - /* - * NOTE: - * - * Please be careful with proper buffer allocation for USB request, - * which needs to be aligned to CONFIG_SYS_CACHELINE_SIZE, not only - * with starting address, but also its size shall be a cache line - * multiplication. - * - * This will prevent from corruption of data allocated immediatelly - * before or after the buffer. - * - * For armv7, the cache_v7.c provides proper code to emit "ERROR" - * message to warn users. - */ - invalidate_dcache_range((unsigned long) ep->dma_buf, - (unsigned long) ep->dma_buf + - ROUND(xfer_size, CONFIG_SYS_CACHELINE_SIZE)); - - req->req.actual += min(xfer_size, req->req.length - req->req.actual); - is_short = (xfer_size < ep->ep.maxpacket); - - debug_cond(DEBUG_OUT_EP != 0, - "%s: RX DMA done : ep = %d, rx bytes = %d/%d, " - "is_short = %d, DOEPTSIZ = 0x%x, remained bytes = %d\n", - __func__, ep_num, req->req.actual, req->req.length, - is_short, ep_tsr, xfer_size); - - if (is_short || req->req.actual == req->req.length) { - if (ep_num == EP0_CON && dev->ep0state == DATA_STATE_RECV) { - debug_cond(DEBUG_OUT_EP != 0, " => Send ZLP\n"); - s3c_udc_ep0_zlp(dev); - /* packet will be completed in complete_tx() */ - dev->ep0state = WAIT_FOR_IN_COMPLETE; - } else { - done(ep, req, 0); - - if (!list_empty(&ep->queue)) { - req = list_entry(ep->queue.next, - struct s3c_request, queue); - debug_cond(DEBUG_OUT_EP != 0, - "%s: Next Rx request start...\n", - __func__); - setdma_rx(ep, req); - } - } - } else - setdma_rx(ep, req); -} - -static void complete_tx(struct s3c_udc *dev, u8 ep_num) -{ - struct s3c_ep *ep = &dev->ep[ep_num]; - struct s3c_request *req; - u32 ep_tsr = 0, xfer_size = 0, is_short = 0; - u32 last; - - if (dev->ep0state == WAIT_FOR_NULL_COMPLETE) { - dev->ep0state = WAIT_FOR_OUT_COMPLETE; - s3c_ep0_complete_out(); - return; - } - - if (list_empty(&ep->queue)) { - debug_cond(DEBUG_IN_EP, - "%s: TX DMA done : NULL REQ on IN EP-%d\n", - __func__, ep_num); - return; - - } - - req = list_entry(ep->queue.next, struct s3c_request, queue); - - ep_tsr = readl(®->in_endp[ep_num].dieptsiz); - - xfer_size = ep->len; - is_short = (xfer_size < ep->ep.maxpacket); - req->req.actual += min(xfer_size, req->req.length - req->req.actual); - - debug_cond(DEBUG_IN_EP, - "%s: TX DMA done : ep = %d, tx bytes = %d/%d, " - "is_short = %d, DIEPTSIZ = 0x%x, remained bytes = %d\n", - __func__, ep_num, req->req.actual, req->req.length, - is_short, ep_tsr, xfer_size); - - if (ep_num == 0) { - if (dev->ep0state == DATA_STATE_XMIT) { - debug_cond(DEBUG_IN_EP, - "%s: ep_num = %d, ep0stat ==" - "DATA_STATE_XMIT\n", - __func__, ep_num); - last = write_fifo_ep0(ep, req); - if (last) - dev->ep0state = WAIT_FOR_COMPLETE; - } else if (dev->ep0state == WAIT_FOR_IN_COMPLETE) { - debug_cond(DEBUG_IN_EP, - "%s: ep_num = %d, completing request\n", - __func__, ep_num); - done(ep, req, 0); - dev->ep0state = WAIT_FOR_SETUP; - } else if (dev->ep0state == WAIT_FOR_COMPLETE) { - debug_cond(DEBUG_IN_EP, - "%s: ep_num = %d, completing request\n", - __func__, ep_num); - done(ep, req, 0); - dev->ep0state = WAIT_FOR_OUT_COMPLETE; - s3c_ep0_complete_out(); - } else { - debug_cond(DEBUG_IN_EP, - "%s: ep_num = %d, invalid ep state\n", - __func__, ep_num); - } - return; - } - - if (req->req.actual == req->req.length) - done(ep, req, 0); - - if (!list_empty(&ep->queue)) { - req = list_entry(ep->queue.next, struct s3c_request, queue); - debug_cond(DEBUG_IN_EP, - "%s: Next Tx request start...\n", __func__); - setdma_tx(ep, req); - } -} - -static inline void s3c_udc_check_tx_queue(struct s3c_udc *dev, u8 ep_num) -{ - struct s3c_ep *ep = &dev->ep[ep_num]; - struct s3c_request *req; - - debug_cond(DEBUG_IN_EP, - "%s: Check queue, ep_num = %d\n", __func__, ep_num); - - if (!list_empty(&ep->queue)) { - req = list_entry(ep->queue.next, struct s3c_request, queue); - debug_cond(DEBUG_IN_EP, - "%s: Next Tx request(0x%p) start...\n", - __func__, req); - - if (ep_is_in(ep)) - setdma_tx(ep, req); - else - setdma_rx(ep, req); - } else { - debug_cond(DEBUG_IN_EP, - "%s: NULL REQ on IN EP-%d\n", __func__, ep_num); - - return; - } - -} - -static void process_ep_in_intr(struct s3c_udc *dev) -{ - u32 ep_intr, ep_intr_status; - u8 ep_num = 0; - - ep_intr = readl(®->daint); - debug_cond(DEBUG_IN_EP, - "*** %s: EP In interrupt : DAINT = 0x%x\n", __func__, ep_intr); - - ep_intr &= DAINT_MASK; - - while (ep_intr) { - if (ep_intr & DAINT_IN_EP_INT(1)) { - ep_intr_status = readl(®->in_endp[ep_num].diepint); - debug_cond(DEBUG_IN_EP, - "\tEP%d-IN : DIEPINT = 0x%x\n", - ep_num, ep_intr_status); - - /* Interrupt Clear */ - writel(ep_intr_status, ®->in_endp[ep_num].diepint); - - if (ep_intr_status & TRANSFER_DONE) { - complete_tx(dev, ep_num); - - if (ep_num == 0) { - if (dev->ep0state == - WAIT_FOR_IN_COMPLETE) - dev->ep0state = WAIT_FOR_SETUP; - - if (dev->ep0state == WAIT_FOR_SETUP) - s3c_udc_pre_setup(); - - /* continue transfer after - set_clear_halt for DMA mode */ - if (clear_feature_flag == 1) { - s3c_udc_check_tx_queue(dev, - clear_feature_num); - clear_feature_flag = 0; - } - } - } - } - ep_num++; - ep_intr >>= 1; - } -} - -static void process_ep_out_intr(struct s3c_udc *dev) -{ - u32 ep_intr, ep_intr_status; - u8 ep_num = 0; - - ep_intr = readl(®->daint); - debug_cond(DEBUG_OUT_EP != 0, - "*** %s: EP OUT interrupt : DAINT = 0x%x\n", - __func__, ep_intr); - - ep_intr = (ep_intr >> DAINT_OUT_BIT) & DAINT_MASK; - - while (ep_intr) { - if (ep_intr & 0x1) { - ep_intr_status = readl(®->out_endp[ep_num].doepint); - debug_cond(DEBUG_OUT_EP != 0, - "\tEP%d-OUT : DOEPINT = 0x%x\n", - ep_num, ep_intr_status); - - /* Interrupt Clear */ - writel(ep_intr_status, ®->out_endp[ep_num].doepint); - - if (ep_num == 0) { - if (ep_intr_status & TRANSFER_DONE) { - if (dev->ep0state != - WAIT_FOR_OUT_COMPLETE) - complete_rx(dev, ep_num); - else { - dev->ep0state = WAIT_FOR_SETUP; - s3c_udc_pre_setup(); - } - } - - if (ep_intr_status & - CTRL_OUT_EP_SETUP_PHASE_DONE) { - debug_cond(DEBUG_OUT_EP != 0, - "SETUP packet arrived\n"); - s3c_handle_ep0(dev); - } - } else { - if (ep_intr_status & TRANSFER_DONE) - complete_rx(dev, ep_num); - } - } - ep_num++; - ep_intr >>= 1; - } -} - -/* - * usb client interrupt handler. - */ -static int s3c_udc_irq(int irq, void *_dev) -{ - struct s3c_udc *dev = _dev; - u32 intr_status; - u32 usb_status, gintmsk; - unsigned long flags; - - spin_lock_irqsave(&dev->lock, flags); - - intr_status = readl(®->gintsts); - gintmsk = readl(®->gintmsk); - - debug_cond(DEBUG_ISR, - "\n*** %s : GINTSTS=0x%x(on state %s), GINTMSK : 0x%x," - "DAINT : 0x%x, DAINTMSK : 0x%x\n", - __func__, intr_status, state_names[dev->ep0state], gintmsk, - readl(®->daint), readl(®->daintmsk)); - - if (!intr_status) { - spin_unlock_irqrestore(&dev->lock, flags); - return IRQ_HANDLED; - } - - if (intr_status & INT_ENUMDONE) { - debug_cond(DEBUG_ISR, "\tSpeed Detection interrupt\n"); - - writel(INT_ENUMDONE, ®->gintsts); - usb_status = (readl(®->dsts) & 0x6); - - if (usb_status & (USB_FULL_30_60MHZ | USB_FULL_48MHZ)) { - debug_cond(DEBUG_ISR, - "\t\tFull Speed Detection\n"); - set_max_pktsize(dev, USB_SPEED_FULL); - - } else { - debug_cond(DEBUG_ISR, - "\t\tHigh Speed Detection : 0x%x\n", - usb_status); - set_max_pktsize(dev, USB_SPEED_HIGH); - } - } - - if (intr_status & INT_EARLY_SUSPEND) { - debug_cond(DEBUG_ISR, "\tEarly suspend interrupt\n"); - writel(INT_EARLY_SUSPEND, ®->gintsts); - } - - if (intr_status & INT_SUSPEND) { - usb_status = readl(®->dsts); - debug_cond(DEBUG_ISR, - "\tSuspend interrupt :(DSTS):0x%x\n", usb_status); - writel(INT_SUSPEND, ®->gintsts); - - if (dev->gadget.speed != USB_SPEED_UNKNOWN - && dev->driver) { - if (dev->driver->suspend) - dev->driver->suspend(&dev->gadget); - - /* HACK to let gadget detect disconnected state */ - if (dev->driver->disconnect) { - spin_unlock_irqrestore(&dev->lock, flags); - dev->driver->disconnect(&dev->gadget); - spin_lock_irqsave(&dev->lock, flags); - } - } - } - - if (intr_status & INT_RESUME) { - debug_cond(DEBUG_ISR, "\tResume interrupt\n"); - writel(INT_RESUME, ®->gintsts); - - if (dev->gadget.speed != USB_SPEED_UNKNOWN - && dev->driver - && dev->driver->resume) { - - dev->driver->resume(&dev->gadget); - } - } - - if (intr_status & INT_RESET) { - usb_status = readl(®->gotgctl); - debug_cond(DEBUG_ISR, - "\tReset interrupt - (GOTGCTL):0x%x\n", usb_status); - writel(INT_RESET, ®->gintsts); - - if ((usb_status & 0xc0000) == (0x3 << 18)) { - if (reset_available) { - debug_cond(DEBUG_ISR, - "\t\tOTG core got reset (%d)!!\n", - reset_available); - reconfig_usbd(); - dev->ep0state = WAIT_FOR_SETUP; - reset_available = 0; - s3c_udc_pre_setup(); - } else - reset_available = 1; - - } else { - reset_available = 1; - debug_cond(DEBUG_ISR, - "\t\tRESET handling skipped\n"); - } - } - - if (intr_status & INT_IN_EP) - process_ep_in_intr(dev); - - if (intr_status & INT_OUT_EP) - process_ep_out_intr(dev); - - spin_unlock_irqrestore(&dev->lock, flags); - - return IRQ_HANDLED; -} - -/** Queue one request - * Kickstart transfer if needed - */ -static int s3c_queue(struct usb_ep *_ep, struct usb_request *_req, - gfp_t gfp_flags) -{ - struct s3c_request *req; - struct s3c_ep *ep; - struct s3c_udc *dev; - unsigned long flags; - u32 ep_num, gintsts; - - req = container_of(_req, struct s3c_request, req); - if (unlikely(!_req || !_req->complete || !_req->buf - || !list_empty(&req->queue))) { - - debug("%s: bad params\n", __func__); - return -EINVAL; - } - - ep = container_of(_ep, struct s3c_ep, ep); - - if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { - - debug("%s: bad ep: %s, %d, %p\n", __func__, - ep->ep.name, !ep->desc, _ep); - return -EINVAL; - } - - ep_num = ep_index(ep); - dev = ep->dev; - if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) { - - debug("%s: bogus device state %p\n", __func__, dev->driver); - return -ESHUTDOWN; - } - - spin_lock_irqsave(&dev->lock, flags); - - _req->status = -EINPROGRESS; - _req->actual = 0; - - /* kickstart this i/o queue? */ - debug("\n*** %s: %s-%s req = %p, len = %d, buf = %p" - "Q empty = %d, stopped = %d\n", - __func__, _ep->name, ep_is_in(ep) ? "in" : "out", - _req, _req->length, _req->buf, - list_empty(&ep->queue), ep->stopped); - -#ifdef DEBUG - { - int i, len = _req->length; - - printf("pkt = "); - if (len > 64) - len = 64; - for (i = 0; i < len; i++) { - printf("%02x", ((u8 *)_req->buf)[i]); - if ((i & 7) == 7) - printf(" "); - } - printf("\n"); - } -#endif - - if (list_empty(&ep->queue) && !ep->stopped) { - - if (ep_num == 0) { - /* EP0 */ - list_add_tail(&req->queue, &ep->queue); - s3c_ep0_kick(dev, ep); - req = 0; - - } else if (ep_is_in(ep)) { - gintsts = readl(®->gintsts); - debug_cond(DEBUG_IN_EP, - "%s: ep_is_in, S3C_UDC_OTG_GINTSTS=0x%x\n", - __func__, gintsts); - - setdma_tx(ep, req); - } else { - gintsts = readl(®->gintsts); - debug_cond(DEBUG_OUT_EP != 0, - "%s:ep_is_out, S3C_UDC_OTG_GINTSTS=0x%x\n", - __func__, gintsts); - - setdma_rx(ep, req); - } - } - - /* pio or dma irq handler advances the queue. */ - if (likely(req != 0)) - list_add_tail(&req->queue, &ep->queue); - - spin_unlock_irqrestore(&dev->lock, flags); - - return 0; -} - -/****************************************************************/ -/* End Point 0 related functions */ -/****************************************************************/ - -/* return: 0 = still running, 1 = completed, negative = errno */ -static int write_fifo_ep0(struct s3c_ep *ep, struct s3c_request *req) -{ - u32 max; - unsigned count; - int is_last; - - max = ep_maxpacket(ep); - - debug_cond(DEBUG_EP0 != 0, "%s: max = %d\n", __func__, max); - - count = setdma_tx(ep, req); - - /* last packet is usually short (or a zlp) */ - if (likely(count != max)) - is_last = 1; - else { - if (likely(req->req.length != req->req.actual + count) - || req->req.zero) - is_last = 0; - else - is_last = 1; - } - - debug_cond(DEBUG_EP0 != 0, - "%s: wrote %s %d bytes%s %d left %p\n", __func__, - ep->ep.name, count, - is_last ? "/L" : "", - req->req.length - req->req.actual - count, req); - - /* requests complete when all IN data is in the FIFO */ - if (is_last) { - ep->dev->ep0state = WAIT_FOR_SETUP; - return 1; - } - - return 0; -} - -int s3c_fifo_read(struct s3c_ep *ep, u32 *cp, int max) -{ - invalidate_dcache_range((unsigned long)cp, (unsigned long)cp + - ROUND(max, CONFIG_SYS_CACHELINE_SIZE)); - - debug_cond(DEBUG_EP0 != 0, - "%s: bytes=%d, ep_index=%d 0x%p\n", __func__, - max, ep_index(ep), cp); - - return max; -} - -/** - * udc_set_address - set the USB address for this device - * @address: - * - * Called from control endpoint function - * after it decodes a set address setup packet. - */ -static void udc_set_address(struct s3c_udc *dev, unsigned char address) -{ - u32 ctrl = readl(®->dcfg); - writel(DEVICE_ADDRESS(address) | ctrl, ®->dcfg); - - s3c_udc_ep0_zlp(dev); - - debug_cond(DEBUG_EP0 != 0, - "%s: USB OTG 2.0 Device address=%d, DCFG=0x%x\n", - __func__, address, readl(®->dcfg)); - - dev->usb_address = address; -} - -static inline void s3c_udc_ep0_set_stall(struct s3c_ep *ep) -{ - struct s3c_udc *dev; - u32 ep_ctrl = 0; - - dev = ep->dev; - ep_ctrl = readl(®->in_endp[EP0_CON].diepctl); - - /* set the disable and stall bits */ - if (ep_ctrl & DEPCTL_EPENA) - ep_ctrl |= DEPCTL_EPDIS; - - ep_ctrl |= DEPCTL_STALL; - - writel(ep_ctrl, ®->in_endp[EP0_CON].diepctl); - - debug_cond(DEBUG_EP0 != 0, - "%s: set ep%d stall, DIEPCTL0 = 0x%p\n", - __func__, ep_index(ep), ®->in_endp[EP0_CON].diepctl); - /* - * The application can only set this bit, and the core clears it, - * when a SETUP token is received for this endpoint - */ - dev->ep0state = WAIT_FOR_SETUP; - - s3c_udc_pre_setup(); -} - -static void s3c_ep0_read(struct s3c_udc *dev) -{ - struct s3c_request *req; - struct s3c_ep *ep = &dev->ep[0]; - - if (!list_empty(&ep->queue)) { - req = list_entry(ep->queue.next, struct s3c_request, queue); - - } else { - debug("%s: ---> BUG\n", __func__); - BUG(); - return; - } - - debug_cond(DEBUG_EP0 != 0, - "%s: req = %p, req.length = 0x%x, req.actual = 0x%x\n", - __func__, req, req->req.length, req->req.actual); - - if (req->req.length == 0) { - /* zlp for Set_configuration, Set_interface, - * or Bulk-Only mass storge reset */ - - ep->len = 0; - s3c_udc_ep0_zlp(dev); - - debug_cond(DEBUG_EP0 != 0, - "%s: req.length = 0, bRequest = %d\n", - __func__, usb_ctrl->bRequest); - return; - } - - setdma_rx(ep, req); -} - -/* - * DATA_STATE_XMIT - */ -static int s3c_ep0_write(struct s3c_udc *dev) -{ - struct s3c_request *req; - struct s3c_ep *ep = &dev->ep[0]; - int ret, need_zlp = 0; - - if (list_empty(&ep->queue)) - req = 0; - else - req = list_entry(ep->queue.next, struct s3c_request, queue); - - if (!req) { - debug_cond(DEBUG_EP0 != 0, "%s: NULL REQ\n", __func__); - return 0; - } - - debug_cond(DEBUG_EP0 != 0, - "%s: req = %p, req.length = 0x%x, req.actual = 0x%x\n", - __func__, req, req->req.length, req->req.actual); - - if (req->req.length - req->req.actual == ep0_fifo_size) { - /* Next write will end with the packet size, */ - /* so we need Zero-length-packet */ - need_zlp = 1; - } - - ret = write_fifo_ep0(ep, req); - - if ((ret == 1) && !need_zlp) { - /* Last packet */ - dev->ep0state = WAIT_FOR_COMPLETE; - debug_cond(DEBUG_EP0 != 0, - "%s: finished, waiting for status\n", __func__); - - } else { - dev->ep0state = DATA_STATE_XMIT; - debug_cond(DEBUG_EP0 != 0, - "%s: not finished\n", __func__); - } - - return 1; -} - -int s3c_udc_get_status(struct s3c_udc *dev, - struct usb_ctrlrequest *crq) -{ - u8 ep_num = crq->wIndex & 0x7F; - u16 g_status = 0; - u32 ep_ctrl; - - debug_cond(DEBUG_SETUP != 0, - "%s: *** USB_REQ_GET_STATUS\n", __func__); - printf("crq->brequest:0x%x\n", crq->bRequestType & USB_RECIP_MASK); - switch (crq->bRequestType & USB_RECIP_MASK) { - case USB_RECIP_INTERFACE: - g_status = 0; - debug_cond(DEBUG_SETUP != 0, - "\tGET_STATUS:USB_RECIP_INTERFACE, g_stauts = %d\n", - g_status); - break; - - case USB_RECIP_DEVICE: - g_status = 0x1; /* Self powered */ - debug_cond(DEBUG_SETUP != 0, - "\tGET_STATUS: USB_RECIP_DEVICE, g_stauts = %d\n", - g_status); - break; - - case USB_RECIP_ENDPOINT: - if (crq->wLength > 2) { - debug_cond(DEBUG_SETUP != 0, - "\tGET_STATUS:Not support EP or wLength\n"); - return 1; - } - - g_status = dev->ep[ep_num].stopped; - debug_cond(DEBUG_SETUP != 0, - "\tGET_STATUS: USB_RECIP_ENDPOINT, g_stauts = %d\n", - g_status); - - break; - - default: - return 1; - } - - memcpy(usb_ctrl, &g_status, sizeof(g_status)); - - flush_dcache_range((unsigned long) usb_ctrl, - (unsigned long) usb_ctrl + - ROUND(sizeof(g_status), CONFIG_SYS_CACHELINE_SIZE)); - - writel(usb_ctrl_dma_addr, ®->in_endp[EP0_CON].diepdma); - writel(DIEPT_SIZ_PKT_CNT(1) | DIEPT_SIZ_XFER_SIZE(2), - ®->in_endp[EP0_CON].dieptsiz); - - ep_ctrl = readl(®->in_endp[EP0_CON].diepctl); - writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, - ®->in_endp[EP0_CON].diepctl); - dev->ep0state = WAIT_FOR_NULL_COMPLETE; - - return 0; -} - -static void s3c_udc_set_nak(struct s3c_ep *ep) -{ - u8 ep_num; - u32 ep_ctrl = 0; - - ep_num = ep_index(ep); - debug("%s: ep_num = %d, ep_type = %d\n", __func__, ep_num, ep->ep_type); - - if (ep_is_in(ep)) { - ep_ctrl = readl(®->in_endp[ep_num].diepctl); - ep_ctrl |= DEPCTL_SNAK; - writel(ep_ctrl, ®->in_endp[ep_num].diepctl); - debug("%s: set NAK, DIEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->in_endp[ep_num].diepctl)); - } else { - ep_ctrl = readl(®->out_endp[ep_num].doepctl); - ep_ctrl |= DEPCTL_SNAK; - writel(ep_ctrl, ®->out_endp[ep_num].doepctl); - debug("%s: set NAK, DOEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->out_endp[ep_num].doepctl)); - } - - return; -} - - -void s3c_udc_ep_set_stall(struct s3c_ep *ep) -{ - u8 ep_num; - u32 ep_ctrl = 0; - - ep_num = ep_index(ep); - debug("%s: ep_num = %d, ep_type = %d\n", __func__, ep_num, ep->ep_type); - - if (ep_is_in(ep)) { - ep_ctrl = readl(®->in_endp[ep_num].diepctl); - - /* set the disable and stall bits */ - if (ep_ctrl & DEPCTL_EPENA) - ep_ctrl |= DEPCTL_EPDIS; - - ep_ctrl |= DEPCTL_STALL; - - writel(ep_ctrl, ®->in_endp[ep_num].diepctl); - debug("%s: set stall, DIEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->in_endp[ep_num].diepctl)); - - } else { - ep_ctrl = readl(®->out_endp[ep_num].doepctl); - - /* set the stall bit */ - ep_ctrl |= DEPCTL_STALL; - - writel(ep_ctrl, ®->out_endp[ep_num].doepctl); - debug("%s: set stall, DOEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->out_endp[ep_num].doepctl)); - } - - return; -} - -void s3c_udc_ep_clear_stall(struct s3c_ep *ep) -{ - u8 ep_num; - u32 ep_ctrl = 0; - - ep_num = ep_index(ep); - debug("%s: ep_num = %d, ep_type = %d\n", __func__, ep_num, ep->ep_type); - - if (ep_is_in(ep)) { - ep_ctrl = readl(®->in_endp[ep_num].diepctl); - - /* clear stall bit */ - ep_ctrl &= ~DEPCTL_STALL; - - /* - * USB Spec 9.4.5: For endpoints using data toggle, regardless - * of whether an endpoint has the Halt feature set, a - * ClearFeature(ENDPOINT_HALT) request always results in the - * data toggle being reinitialized to DATA0. - */ - if (ep->bmAttributes == USB_ENDPOINT_XFER_INT - || ep->bmAttributes == USB_ENDPOINT_XFER_BULK) { - ep_ctrl |= DEPCTL_SETD0PID; /* DATA0 */ - } - - writel(ep_ctrl, ®->in_endp[ep_num].diepctl); - debug("%s: cleared stall, DIEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->in_endp[ep_num].diepctl)); - - } else { - ep_ctrl = readl(®->out_endp[ep_num].doepctl); - - /* clear stall bit */ - ep_ctrl &= ~DEPCTL_STALL; - - if (ep->bmAttributes == USB_ENDPOINT_XFER_INT - || ep->bmAttributes == USB_ENDPOINT_XFER_BULK) { - ep_ctrl |= DEPCTL_SETD0PID; /* DATA0 */ - } - - writel(ep_ctrl, ®->out_endp[ep_num].doepctl); - debug("%s: cleared stall, DOEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->out_endp[ep_num].doepctl)); - } - - return; -} - -static int s3c_udc_set_halt(struct usb_ep *_ep, int value) -{ - struct s3c_ep *ep; - struct s3c_udc *dev; - unsigned long flags; - u8 ep_num; - - ep = container_of(_ep, struct s3c_ep, ep); - ep_num = ep_index(ep); - - if (unlikely(!_ep || !ep->desc || ep_num == EP0_CON || - ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC)) { - debug("%s: %s bad ep or descriptor\n", __func__, ep->ep.name); - return -EINVAL; - } - - /* Attempt to halt IN ep will fail if any transfer requests - * are still queue */ - if (value && ep_is_in(ep) && !list_empty(&ep->queue)) { - debug("%s: %s queue not empty, req = %p\n", - __func__, ep->ep.name, - list_entry(ep->queue.next, struct s3c_request, queue)); - - return -EAGAIN; - } - - dev = ep->dev; - debug("%s: ep_num = %d, value = %d\n", __func__, ep_num, value); - - spin_lock_irqsave(&dev->lock, flags); - - if (value == 0) { - ep->stopped = 0; - s3c_udc_ep_clear_stall(ep); - } else { - if (ep_num == 0) - dev->ep0state = WAIT_FOR_SETUP; - - ep->stopped = 1; - s3c_udc_ep_set_stall(ep); - } - - spin_unlock_irqrestore(&dev->lock, flags); - - return 0; -} - -void s3c_udc_ep_activate(struct s3c_ep *ep) -{ - u8 ep_num; - u32 ep_ctrl = 0, daintmsk = 0; - - ep_num = ep_index(ep); - - /* Read DEPCTLn register */ - if (ep_is_in(ep)) { - ep_ctrl = readl(®->in_endp[ep_num].diepctl); - daintmsk = 1 << ep_num; - } else { - ep_ctrl = readl(®->out_endp[ep_num].doepctl); - daintmsk = (1 << ep_num) << DAINT_OUT_BIT; - } - - debug("%s: EPCTRL%d = 0x%x, ep_is_in = %d\n", - __func__, ep_num, ep_ctrl, ep_is_in(ep)); - - /* If the EP is already active don't change the EP Control - * register. */ - if (!(ep_ctrl & DEPCTL_USBACTEP)) { - ep_ctrl = (ep_ctrl & ~DEPCTL_TYPE_MASK) | - (ep->bmAttributes << DEPCTL_TYPE_BIT); - ep_ctrl = (ep_ctrl & ~DEPCTL_MPS_MASK) | - (ep->ep.maxpacket << DEPCTL_MPS_BIT); - ep_ctrl |= (DEPCTL_SETD0PID | DEPCTL_USBACTEP | DEPCTL_SNAK); - - if (ep_is_in(ep)) { - writel(ep_ctrl, ®->in_endp[ep_num].diepctl); - debug("%s: USB Ative EP%d, DIEPCTRL%d = 0x%x\n", - __func__, ep_num, ep_num, - readl(®->in_endp[ep_num].diepctl)); - } else { - writel(ep_ctrl, ®->out_endp[ep_num].doepctl); - debug("%s: USB Ative EP%d, DOEPCTRL%d = 0x%x\n", - __func__, ep_num, ep_num, - readl(®->out_endp[ep_num].doepctl)); - } - } - - /* Unmask EP Interrtupt */ - writel(readl(®->daintmsk)|daintmsk, ®->daintmsk); - debug("%s: DAINTMSK = 0x%x\n", __func__, readl(®->daintmsk)); - -} - -static int s3c_udc_clear_feature(struct usb_ep *_ep) -{ - struct s3c_udc *dev; - struct s3c_ep *ep; - u8 ep_num; - - ep = container_of(_ep, struct s3c_ep, ep); - ep_num = ep_index(ep); - - dev = ep->dev; - debug_cond(DEBUG_SETUP != 0, - "%s: ep_num = %d, is_in = %d, clear_feature_flag = %d\n", - __func__, ep_num, ep_is_in(ep), clear_feature_flag); - - if (usb_ctrl->wLength != 0) { - debug_cond(DEBUG_SETUP != 0, - "\tCLEAR_FEATURE: wLength is not zero.....\n"); - return 1; - } - - switch (usb_ctrl->bRequestType & USB_RECIP_MASK) { - case USB_RECIP_DEVICE: - switch (usb_ctrl->wValue) { - case USB_DEVICE_REMOTE_WAKEUP: - debug_cond(DEBUG_SETUP != 0, - "\tOFF:USB_DEVICE_REMOTE_WAKEUP\n"); - break; - - case USB_DEVICE_TEST_MODE: - debug_cond(DEBUG_SETUP != 0, - "\tCLEAR_FEATURE: USB_DEVICE_TEST_MODE\n"); - /** @todo Add CLEAR_FEATURE for TEST modes. */ - break; - } - - s3c_udc_ep0_zlp(dev); - break; - - case USB_RECIP_ENDPOINT: - debug_cond(DEBUG_SETUP != 0, - "\tCLEAR_FEATURE:USB_RECIP_ENDPOINT, wValue = %d\n", - usb_ctrl->wValue); - - if (usb_ctrl->wValue == USB_ENDPOINT_HALT) { - if (ep_num == 0) { - s3c_udc_ep0_set_stall(ep); - return 0; - } - - s3c_udc_ep0_zlp(dev); - - s3c_udc_ep_clear_stall(ep); - s3c_udc_ep_activate(ep); - ep->stopped = 0; - - clear_feature_num = ep_num; - clear_feature_flag = 1; - } - break; - } - - return 0; -} - -static int s3c_udc_set_feature(struct usb_ep *_ep) -{ - struct s3c_udc *dev; - struct s3c_ep *ep; - u8 ep_num; - - ep = container_of(_ep, struct s3c_ep, ep); - ep_num = ep_index(ep); - dev = ep->dev; - - debug_cond(DEBUG_SETUP != 0, - "%s: *** USB_REQ_SET_FEATURE , ep_num = %d\n", - __func__, ep_num); - - if (usb_ctrl->wLength != 0) { - debug_cond(DEBUG_SETUP != 0, - "\tSET_FEATURE: wLength is not zero.....\n"); - return 1; - } - - switch (usb_ctrl->bRequestType & USB_RECIP_MASK) { - case USB_RECIP_DEVICE: - switch (usb_ctrl->wValue) { - case USB_DEVICE_REMOTE_WAKEUP: - debug_cond(DEBUG_SETUP != 0, - "\tSET_FEATURE:USB_DEVICE_REMOTE_WAKEUP\n"); - break; - case USB_DEVICE_B_HNP_ENABLE: - debug_cond(DEBUG_SETUP != 0, - "\tSET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n"); - break; - - case USB_DEVICE_A_HNP_SUPPORT: - /* RH port supports HNP */ - debug_cond(DEBUG_SETUP != 0, - "\tSET_FEATURE:USB_DEVICE_A_HNP_SUPPORT\n"); - break; - - case USB_DEVICE_A_ALT_HNP_SUPPORT: - /* other RH port does */ - debug_cond(DEBUG_SETUP != 0, - "\tSET: USB_DEVICE_A_ALT_HNP_SUPPORT\n"); - break; - } - - s3c_udc_ep0_zlp(dev); - return 0; - - case USB_RECIP_INTERFACE: - debug_cond(DEBUG_SETUP != 0, - "\tSET_FEATURE: USB_RECIP_INTERFACE\n"); - break; - - case USB_RECIP_ENDPOINT: - debug_cond(DEBUG_SETUP != 0, - "\tSET_FEATURE: USB_RECIP_ENDPOINT\n"); - if (usb_ctrl->wValue == USB_ENDPOINT_HALT) { - if (ep_num == 0) { - s3c_udc_ep0_set_stall(ep); - return 0; - } - ep->stopped = 1; - s3c_udc_ep_set_stall(ep); - } - - s3c_udc_ep0_zlp(dev); - return 0; - } - - return 1; -} - -/* - * WAIT_FOR_SETUP (OUT_PKT_RDY) - */ -void s3c_ep0_setup(struct s3c_udc *dev) -{ - struct s3c_ep *ep = &dev->ep[0]; - int i; - u8 ep_num; - - /* Nuke all previous transfers */ - nuke(ep, -EPROTO); - - /* read control req from fifo (8 bytes) */ - s3c_fifo_read(ep, (u32 *)usb_ctrl, 8); - - debug_cond(DEBUG_SETUP != 0, - "%s: bRequestType = 0x%x(%s), bRequest = 0x%x" - "\twLength = 0x%x, wValue = 0x%x, wIndex= 0x%x\n", - __func__, usb_ctrl->bRequestType, - (usb_ctrl->bRequestType & USB_DIR_IN) ? "IN" : "OUT", - usb_ctrl->bRequest, - usb_ctrl->wLength, usb_ctrl->wValue, usb_ctrl->wIndex); - -#ifdef DEBUG - { - int i, len = sizeof(*usb_ctrl); - char *p = (char *)usb_ctrl; - - printf("pkt = "); - for (i = 0; i < len; i++) { - printf("%02x", ((u8 *)p)[i]); - if ((i & 7) == 7) - printf(" "); - } - printf("\n"); - } -#endif - - if (usb_ctrl->bRequest == GET_MAX_LUN_REQUEST && - usb_ctrl->wLength != 1) { - debug_cond(DEBUG_SETUP != 0, - "\t%s:GET_MAX_LUN_REQUEST:invalid", - __func__); - debug_cond(DEBUG_SETUP != 0, - "wLength = %d, setup returned\n", - usb_ctrl->wLength); - - s3c_udc_ep0_set_stall(ep); - dev->ep0state = WAIT_FOR_SETUP; - - return; - } else if (usb_ctrl->bRequest == BOT_RESET_REQUEST && - usb_ctrl->wLength != 0) { - /* Bulk-Only *mass storge reset of class-specific request */ - debug_cond(DEBUG_SETUP != 0, - "%s:BOT Rest:invalid wLength =%d, setup returned\n", - __func__, usb_ctrl->wLength); - - s3c_udc_ep0_set_stall(ep); - dev->ep0state = WAIT_FOR_SETUP; - - return; - } - - /* Set direction of EP0 */ - if (likely(usb_ctrl->bRequestType & USB_DIR_IN)) { - ep->bEndpointAddress |= USB_DIR_IN; - } else { - ep->bEndpointAddress &= ~USB_DIR_IN; - } - /* cope with automagic for some standard requests. */ - dev->req_std = (usb_ctrl->bRequestType & USB_TYPE_MASK) - == USB_TYPE_STANDARD; - - dev->req_pending = 1; - - /* Handle some SETUP packets ourselves */ - if (dev->req_std) { - switch (usb_ctrl->bRequest) { - case USB_REQ_SET_ADDRESS: - debug_cond(DEBUG_SETUP != 0, - "%s: *** USB_REQ_SET_ADDRESS (%d)\n", - __func__, usb_ctrl->wValue); - if (usb_ctrl->bRequestType - != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) - break; - - udc_set_address(dev, usb_ctrl->wValue); - return; - - case USB_REQ_SET_CONFIGURATION: - debug_cond(DEBUG_SETUP != 0, - "=====================================\n"); - debug_cond(DEBUG_SETUP != 0, - "%s: USB_REQ_SET_CONFIGURATION (%d)\n", - __func__, usb_ctrl->wValue); - - if (usb_ctrl->bRequestType == USB_RECIP_DEVICE) - reset_available = 1; - - break; - - case USB_REQ_GET_DESCRIPTOR: - debug_cond(DEBUG_SETUP != 0, - "%s: *** USB_REQ_GET_DESCRIPTOR\n", - __func__); - break; - - case USB_REQ_SET_INTERFACE: - debug_cond(DEBUG_SETUP != 0, - "%s: *** USB_REQ_SET_INTERFACE (%d)\n", - __func__, usb_ctrl->wValue); - - if (usb_ctrl->bRequestType == USB_RECIP_INTERFACE) - reset_available = 1; - - break; - - case USB_REQ_GET_CONFIGURATION: - debug_cond(DEBUG_SETUP != 0, - "%s: *** USB_REQ_GET_CONFIGURATION\n", - __func__); - break; - - case USB_REQ_GET_STATUS: - if (!s3c_udc_get_status(dev, usb_ctrl)) - return; - - break; - - case USB_REQ_CLEAR_FEATURE: - ep_num = usb_ctrl->wIndex & 0x7f; - - if (!s3c_udc_clear_feature(&dev->ep[ep_num].ep)) - return; - - break; - - case USB_REQ_SET_FEATURE: - ep_num = usb_ctrl->wIndex & 0x7f; - - if (!s3c_udc_set_feature(&dev->ep[ep_num].ep)) - return; - - break; - - default: - debug_cond(DEBUG_SETUP != 0, - "%s: *** Default of usb_ctrl->bRequest=0x%x" - "happened.\n", __func__, usb_ctrl->bRequest); - break; - } - } - - - if (likely(dev->driver)) { - /* device-2-host (IN) or no data setup command, - * process immediately */ - debug_cond(DEBUG_SETUP != 0, - "%s:usb_ctrlreq will be passed to fsg_setup()\n", - __func__); - - spin_unlock(&dev->lock); - i = dev->driver->setup(&dev->gadget, usb_ctrl); - spin_lock(&dev->lock); - - if (i < 0) { - /* setup processing failed, force stall */ - s3c_udc_ep0_set_stall(ep); - dev->ep0state = WAIT_FOR_SETUP; - - debug_cond(DEBUG_SETUP != 0, - "\tdev->driver->setup failed (%d)," - " bRequest = %d\n", - i, usb_ctrl->bRequest); - - - } else if (dev->req_pending) { - dev->req_pending = 0; - debug_cond(DEBUG_SETUP != 0, - "\tdev->req_pending...\n"); - } - - debug_cond(DEBUG_SETUP != 0, - "\tep0state = %s\n", state_names[dev->ep0state]); - - } -} - -/* - * handle ep0 interrupt - */ -static void s3c_handle_ep0(struct s3c_udc *dev) -{ - if (dev->ep0state == WAIT_FOR_SETUP) { - debug_cond(DEBUG_OUT_EP != 0, - "%s: WAIT_FOR_SETUP\n", __func__); - s3c_ep0_setup(dev); - - } else { - debug_cond(DEBUG_OUT_EP != 0, - "%s: strange state!!(state = %s)\n", - __func__, state_names[dev->ep0state]); - } -} - -static void s3c_ep0_kick(struct s3c_udc *dev, struct s3c_ep *ep) -{ - debug_cond(DEBUG_EP0 != 0, - "%s: ep_is_in = %d\n", __func__, ep_is_in(ep)); - if (ep_is_in(ep)) { - dev->ep0state = DATA_STATE_XMIT; - s3c_ep0_write(dev); - - } else { - dev->ep0state = DATA_STATE_RECV; - s3c_ep0_read(dev); - } -} diff --git a/qemu/roms/u-boot/drivers/usb/gadget/storage_common.c b/qemu/roms/u-boot/drivers/usb/gadget/storage_common.c deleted file mode 100644 index 74300746b..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/storage_common.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * storage_common.c -- Common definitions for mass storage functionality - * - * Copyright (C) 2003-2008 Alan Stern - * Copyeight (C) 2009 Samsung Electronics - * Author: Michal Nazarewicz (m.nazarewicz@samsung.com) - * - * Ported to u-boot: - * Andrzej Pietrasiewicz <andrzej.p@samsung.com> - * - * Code refactoring & cleanup: - * Łukasz Majewski <l.majewski@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - - -/* - * This file requires the following identifiers used in USB strings to - * be defined (each of type pointer to char): - * - fsg_string_manufacturer -- name of the manufacturer - * - fsg_string_product -- name of the product - * - fsg_string_serial -- product's serial - * - fsg_string_config -- name of the configuration - * - fsg_string_interface -- name of the interface - * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS - * macro is defined prior to including this file. - */ - -/* - * When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and - * fsg_hs_intr_in_desc objects as well as - * FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES - * macros are not defined. - * - * When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER, - * FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not - * defined (as well as corresponding entries in string tables are - * missing) and FSG_STRING_INTERFACE has value of zero. - * - * When FSG_NO_OTG is defined fsg_otg_desc won't be defined. - */ - -/* - * When FSG_BUFFHD_STATIC_BUFFER is defined when this file is included - * the fsg_buffhd structure's buf field will be an array of FSG_BUFLEN - * characters rather then a pointer to void. - */ - - -/* #include <asm/unaligned.h> */ - - -/* - * Thanks to NetChip Technologies for donating this product ID. - * - * DO NOT REUSE THESE IDs with any other driver!! Ever!! - * Instead: allocate your own, using normal USB-IF procedures. - */ -#define FSG_VENDOR_ID 0x0525 /* NetChip */ -#define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ - -/*-------------------------------------------------------------------------*/ - -#ifndef DEBUG -#undef VERBOSE_DEBUG -#undef DUMP_MSGS -#endif /* !DEBUG */ - -#ifdef VERBOSE_DEBUG -#define VLDBG LDBG -#else -#define VLDBG(lun, fmt, args...) do { } while (0) -#endif /* VERBOSE_DEBUG */ - -/* -#define LDBG(lun, fmt, args...) dev_dbg (&(lun)->dev, fmt, ## args) -#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args) -#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) -#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) -*/ - -#define LDBG(lun, fmt, args...) do { } while (0) -#define LERROR(lun, fmt, args...) do { } while (0) -#define LWARN(lun, fmt, args...) do { } while (0) -#define LINFO(lun, fmt, args...) do { } while (0) - -/* - * Keep those macros in sync with those in - * include/linux/usb/composite.h or else GCC will complain. If they - * are identical (the same names of arguments, white spaces in the - * same places) GCC will allow redefinition otherwise (even if some - * white space is removed or added) warning will be issued. - * - * Those macros are needed here because File Storage Gadget does not - * include the composite.h header. For composite gadgets those macros - * are redundant since composite.h is included any way. - * - * One could check whether those macros are already defined (which - * would indicate composite.h had been included) or not (which would - * indicate we were in FSG) but this is not done because a warning is - * desired if definitions here differ from the ones in composite.h. - * - * We want the definitions to match and be the same in File Storage - * Gadget as well as Mass Storage Function (and so composite gadgets - * using MSF). If someone changes them in composite.h it will produce - * a warning in this file when building MSF. - */ - -#define DBG(d, fmt, args...) debug(fmt , ## args) -#define VDBG(d, fmt, args...) debug(fmt , ## args) -/* #define ERROR(d, fmt, args...) printf(fmt , ## args) */ -/* #define WARNING(d, fmt, args...) printf(fmt , ## args) */ -/* #define INFO(d, fmt, args...) printf(fmt , ## args) */ - -/* #define DBG(d, fmt, args...) do { } while (0) */ -/* #define VDBG(d, fmt, args...) do { } while (0) */ -#define ERROR(d, fmt, args...) do { } while (0) -#define WARNING(d, fmt, args...) do { } while (0) -#define INFO(d, fmt, args...) do { } while (0) - -#ifdef DUMP_MSGS - -/* dump_msg(fsg, const char * label, const u8 * buf, unsigned length); */ -# define dump_msg(fsg, label, buf, length) do { \ - if (length < 512) { \ - DBG(fsg, "%s, length %u:\n", label, length); \ - print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \ - 16, 1, buf, length, 0); \ - } \ -} while (0) - -# define dump_cdb(fsg) do { } while (0) - -#else - -# define dump_msg(fsg, /* const char * */ label, \ - /* const u8 * */ buf, /* unsigned */ length) do { } while (0) - -# ifdef VERBOSE_DEBUG - -# define dump_cdb(fsg) \ - print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, \ - 16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0) \ - -# else - -# define dump_cdb(fsg) do { } while (0) - -# endif /* VERBOSE_DEBUG */ - -#endif /* DUMP_MSGS */ - -/*-------------------------------------------------------------------------*/ - -/* SCSI device types */ -#define TYPE_DISK 0x00 -#define TYPE_CDROM 0x05 - -/* USB protocol value = the transport method */ -#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */ -#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */ -#define USB_PR_BULK 0x50 /* Bulk-only */ - -/* USB subclass value = the protocol encapsulation */ -#define USB_SC_RBC 0x01 /* Reduced Block Commands (flash) */ -#define USB_SC_8020 0x02 /* SFF-8020i, MMC-2, ATAPI (CD-ROM) */ -#define USB_SC_QIC 0x03 /* QIC-157 (tape) */ -#define USB_SC_UFI 0x04 /* UFI (floppy) */ -#define USB_SC_8070 0x05 /* SFF-8070i (removable) */ -#define USB_SC_SCSI 0x06 /* Transparent SCSI */ - -/* Bulk-only data structures */ - -/* Command Block Wrapper */ -struct fsg_bulk_cb_wrap { - __le32 Signature; /* Contains 'USBC' */ - u32 Tag; /* Unique per command id */ - __le32 DataTransferLength; /* Size of the data */ - u8 Flags; /* Direction in bit 7 */ - u8 Lun; /* LUN (normally 0) */ - u8 Length; /* Of the CDB, <= MAX_COMMAND_SIZE */ - u8 CDB[16]; /* Command Data Block */ -}; - -#define USB_BULK_CB_WRAP_LEN 31 -#define USB_BULK_CB_SIG 0x43425355 /* Spells out USBC */ -#define USB_BULK_IN_FLAG 0x80 - -/* Command Status Wrapper */ -struct bulk_cs_wrap { - __le32 Signature; /* Should = 'USBS' */ - u32 Tag; /* Same as original command */ - __le32 Residue; /* Amount not transferred */ - u8 Status; /* See below */ -}; - -#define USB_BULK_CS_WRAP_LEN 13 -#define USB_BULK_CS_SIG 0x53425355 /* Spells out 'USBS' */ -#define USB_STATUS_PASS 0 -#define USB_STATUS_FAIL 1 -#define USB_STATUS_PHASE_ERROR 2 - -/* Bulk-only class specific requests */ -#define USB_BULK_RESET_REQUEST 0xff -#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe - -/* CBI Interrupt data structure */ -struct interrupt_data { - u8 bType; - u8 bValue; -}; - -#define CBI_INTERRUPT_DATA_LEN 2 - -/* CBI Accept Device-Specific Command request */ -#define USB_CBI_ADSC_REQUEST 0x00 - -/* Length of a SCSI Command Data Block */ -#define MAX_COMMAND_SIZE 16 - -/* SCSI commands that we recognize */ -#define SC_FORMAT_UNIT 0x04 -#define SC_INQUIRY 0x12 -#define SC_MODE_SELECT_6 0x15 -#define SC_MODE_SELECT_10 0x55 -#define SC_MODE_SENSE_6 0x1a -#define SC_MODE_SENSE_10 0x5a -#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define SC_READ_6 0x08 -#define SC_READ_10 0x28 -#define SC_READ_12 0xa8 -#define SC_READ_CAPACITY 0x25 -#define SC_READ_FORMAT_CAPACITIES 0x23 -#define SC_READ_HEADER 0x44 -#define SC_READ_TOC 0x43 -#define SC_RELEASE 0x17 -#define SC_REQUEST_SENSE 0x03 -#define SC_RESERVE 0x16 -#define SC_SEND_DIAGNOSTIC 0x1d -#define SC_START_STOP_UNIT 0x1b -#define SC_SYNCHRONIZE_CACHE 0x35 -#define SC_TEST_UNIT_READY 0x00 -#define SC_VERIFY 0x2f -#define SC_WRITE_6 0x0a -#define SC_WRITE_10 0x2a -#define SC_WRITE_12 0xaa - -/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ -#define SS_NO_SENSE 0 -#define SS_COMMUNICATION_FAILURE 0x040800 -#define SS_INVALID_COMMAND 0x052000 -#define SS_INVALID_FIELD_IN_CDB 0x052400 -#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100 -#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500 -#define SS_MEDIUM_NOT_PRESENT 0x023a00 -#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302 -#define SS_NOT_READY_TO_READY_TRANSITION 0x062800 -#define SS_RESET_OCCURRED 0x062900 -#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900 -#define SS_UNRECOVERED_READ_ERROR 0x031100 -#define SS_WRITE_ERROR 0x030c02 -#define SS_WRITE_PROTECTED 0x072700 - -#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */ -#define ASC(x) ((u8) ((x) >> 8)) -#define ASCQ(x) ((u8) (x)) - -struct device_attribute { int i; }; -struct rw_semaphore { int i; }; -#define down_write(...) do { } while (0) -#define up_write(...) do { } while (0) -#define down_read(...) do { } while (0) -#define up_read(...) do { } while (0) -#define ETOOSMALL 525 - -#include <usb_mass_storage.h> - -/*-------------------------------------------------------------------------*/ - -struct fsg_lun { - loff_t file_length; - loff_t num_sectors; - - unsigned int initially_ro:1; - unsigned int ro:1; - unsigned int removable:1; - unsigned int cdrom:1; - unsigned int prevent_medium_removal:1; - unsigned int registered:1; - unsigned int info_valid:1; - unsigned int nofua:1; - - u32 sense_data; - u32 sense_data_info; - u32 unit_attention_data; - - struct device dev; -}; - -#define fsg_lun_is_open(curlun) ((curlun)->filp != NULL) -#if 0 -static struct fsg_lun *fsg_lun_from_dev(struct device *dev) -{ - return container_of(dev, struct fsg_lun, dev); -} -#endif - -/* Big enough to hold our biggest descriptor */ -#define EP0_BUFSIZE 256 -#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ - -/* Number of buffers we will use. 2 is enough for double-buffering */ -#ifndef CONFIG_CI_UDC -#define FSG_NUM_BUFFERS 2 -#else -#define FSG_NUM_BUFFERS 1 /* ci_udc only allows 1 req per ep at present */ -#endif - -/* Default size of buffer length. */ -#define FSG_BUFLEN ((u32)16384) - -/* Maximal number of LUNs supported in mass storage function */ -#define FSG_MAX_LUNS 8 - -enum fsg_buffer_state { - BUF_STATE_EMPTY = 0, - BUF_STATE_FULL, - BUF_STATE_BUSY -}; - -struct fsg_buffhd { -#ifdef FSG_BUFFHD_STATIC_BUFFER - char buf[FSG_BUFLEN]; -#else - void *buf; -#endif - enum fsg_buffer_state state; - struct fsg_buffhd *next; - - /* - * The NetChip 2280 is faster, and handles some protocol faults - * better, if we don't submit any short bulk-out read requests. - * So we will record the intended request length here. - */ - unsigned int bulk_out_intended_length; - - struct usb_request *inreq; - int inreq_busy; - struct usb_request *outreq; - int outreq_busy; -}; - -enum fsg_state { - /* This one isn't used anywhere */ - FSG_STATE_COMMAND_PHASE = -10, - FSG_STATE_DATA_PHASE, - FSG_STATE_STATUS_PHASE, - - FSG_STATE_IDLE = 0, - FSG_STATE_ABORT_BULK_OUT, - FSG_STATE_RESET, - FSG_STATE_INTERFACE_CHANGE, - FSG_STATE_CONFIG_CHANGE, - FSG_STATE_DISCONNECT, - FSG_STATE_EXIT, - FSG_STATE_TERMINATED -}; - -enum data_direction { - DATA_DIR_UNKNOWN = 0, - DATA_DIR_FROM_HOST, - DATA_DIR_TO_HOST, - DATA_DIR_NONE -}; - -/*-------------------------------------------------------------------------*/ - -static inline u32 get_unaligned_be24(u8 *buf) -{ - return 0xffffff & (u32) get_unaligned_be32(buf - 1); -} - -/*-------------------------------------------------------------------------*/ - -enum { -#ifndef FSG_NO_DEVICE_STRINGS - FSG_STRING_MANUFACTURER = 1, - FSG_STRING_PRODUCT, - FSG_STRING_SERIAL, - FSG_STRING_CONFIG, -#endif - FSG_STRING_INTERFACE -}; - -#ifndef FSG_NO_OTG -static struct usb_otg_descriptor -fsg_otg_desc = { - .bLength = sizeof fsg_otg_desc, - .bDescriptorType = USB_DT_OTG, - - .bmAttributes = USB_OTG_SRP, -}; -#endif - -/* There is only one interface. */ - -static struct usb_interface_descriptor -fsg_intf_desc = { - .bLength = sizeof fsg_intf_desc, - .bDescriptorType = USB_DT_INTERFACE, - - .bNumEndpoints = 2, /* Adjusted during fsg_bind() */ - .bInterfaceClass = USB_CLASS_MASS_STORAGE, - .bInterfaceSubClass = USB_SC_SCSI, /* Adjusted during fsg_bind() */ - .bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */ - .iInterface = FSG_STRING_INTERFACE, -}; - -/* - * Three full-speed endpoint descriptors: bulk-in, bulk-out, and - * interrupt-in. - */ - -static struct usb_endpoint_descriptor -fsg_fs_bulk_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - /* wMaxPacketSize set by autoconfiguration */ -}; - -static struct usb_endpoint_descriptor -fsg_fs_bulk_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - /* wMaxPacketSize set by autoconfiguration */ -}; - -#ifndef FSG_NO_INTR_EP - -static struct usb_endpoint_descriptor -fsg_fs_intr_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(2), - .bInterval = 32, /* frames -> 32 ms */ -}; - -#ifndef FSG_NO_OTG -# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 2 -#else -# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 1 -#endif - -#endif - -static struct usb_descriptor_header *fsg_fs_function[] = { -#ifndef FSG_NO_OTG - (struct usb_descriptor_header *) &fsg_otg_desc, -#endif - (struct usb_descriptor_header *) &fsg_intf_desc, - (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc, - (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc, -#ifndef FSG_NO_INTR_EP - (struct usb_descriptor_header *) &fsg_fs_intr_in_desc, -#endif - NULL, -}; - -/* - * USB 2.0 devices need to expose both high speed and full speed - * descriptors, unless they only run at full speed. - * - * That means alternate endpoint descriptors (bigger packets) - * and a "device qualifier" ... plus more construction options - * for the configuration descriptor. - */ -static struct usb_endpoint_descriptor -fsg_hs_bulk_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), -}; - -static struct usb_endpoint_descriptor -fsg_hs_bulk_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), - .bInterval = 1, /* NAK every 1 uframe */ -}; - -#ifndef FSG_NO_INTR_EP - -static struct usb_endpoint_descriptor -fsg_hs_intr_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(2), - .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */ -}; - -#ifndef FSG_NO_OTG -# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 2 -#else -# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 1 -#endif - -#endif - -static struct usb_descriptor_header *fsg_hs_function[] = { -#ifndef FSG_NO_OTG - (struct usb_descriptor_header *) &fsg_otg_desc, -#endif - (struct usb_descriptor_header *) &fsg_intf_desc, - (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc, - (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc, -#ifndef FSG_NO_INTR_EP - (struct usb_descriptor_header *) &fsg_hs_intr_in_desc, -#endif - NULL, -}; - -/* Maxpacket and other transfer characteristics vary by speed. */ -static struct usb_endpoint_descriptor * -fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, - struct usb_endpoint_descriptor *hs) -{ - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) - return hs; - return fs; -} - -/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ -static struct usb_string fsg_strings[] = { -#ifndef FSG_NO_DEVICE_STRINGS - {FSG_STRING_MANUFACTURER, fsg_string_manufacturer}, - {FSG_STRING_PRODUCT, fsg_string_product}, - {FSG_STRING_SERIAL, fsg_string_serial}, - {FSG_STRING_CONFIG, fsg_string_config}, -#endif - {FSG_STRING_INTERFACE, fsg_string_interface}, - {} -}; - -static struct usb_gadget_strings fsg_stringtab = { - .language = 0x0409, /* en-us */ - .strings = fsg_strings, -}; - -/*-------------------------------------------------------------------------*/ - -/* - * If the next two routines are called while the gadget is registered, - * the caller must own fsg->filesem for writing. - */ - -static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) -{ - int ro; - - /* R/W if we can, R/O if we must */ - ro = curlun->initially_ro; - - curlun->ro = ro; - curlun->file_length = ums->num_sectors << 9; - curlun->num_sectors = ums->num_sectors; - debug("open backing file: %s\n", filename); - - return 0; -} - -static void fsg_lun_close(struct fsg_lun *curlun) -{ -} - -/*-------------------------------------------------------------------------*/ - -/* - * Sync the file data, don't bother with the metadata. - * This code was copied from fs/buffer.c:sys_fdatasync(). - */ -static int fsg_lun_fsync_sub(struct fsg_lun *curlun) -{ - return 0; -} - -static void store_cdrom_address(u8 *dest, int msf, u32 addr) -{ - if (msf) { - /* Convert to Minutes-Seconds-Frames */ - addr >>= 2; /* Convert to 2048-byte frames */ - addr += 2*75; /* Lead-in occupies 2 seconds */ - dest[3] = addr % 75; /* Frames */ - addr /= 75; - dest[2] = addr % 60; /* Seconds */ - addr /= 60; - dest[1] = addr; /* Minutes */ - dest[0] = 0; /* Reserved */ - } else { - /* Absolute sector */ - put_unaligned_be32(addr, dest); - } -} - -/*-------------------------------------------------------------------------*/ diff --git a/qemu/roms/u-boot/drivers/usb/gadget/usbstring.c b/qemu/roms/u-boot/drivers/usb/gadget/usbstring.c deleted file mode 100644 index 8c3ff64fe..000000000 --- a/qemu/roms/u-boot/drivers/usb/gadget/usbstring.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2003 David Brownell - * - * SPDX-License-Identifier: LGPL-2.1+ - * - * Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and - * Remy Bohmer <linux@bohmer.net> - */ - -#include <common.h> -#include <asm/errno.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> - -#include <asm/unaligned.h> - - -static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len) -{ - int count = 0; - u8 c; - u16 uchar; - - /* - * this insists on correct encodings, though not minimal ones. - * BUT it currently rejects legit 4-byte UTF-8 code points, - * which need surrogate pairs. (Unicode 3.1 can use them.) - */ - while (len != 0 && (c = (u8) *s++) != 0) { - if ((c & 0x80)) { - /* - * 2-byte sequence: - * 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx - */ - if ((c & 0xe0) == 0xc0) { - uchar = (c & 0x1f) << 6; - - c = (u8) *s++; - if ((c & 0xc0) != 0x80) - goto fail; - c &= 0x3f; - uchar |= c; - - /* - * 3-byte sequence (most CJKV characters): - * zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx - */ - } else if ((c & 0xf0) == 0xe0) { - uchar = (c & 0x0f) << 12; - - c = (u8) *s++; - if ((c & 0xc0) != 0x80) - goto fail; - c &= 0x3f; - uchar |= c << 6; - - c = (u8) *s++; - if ((c & 0xc0) != 0x80) - goto fail; - c &= 0x3f; - uchar |= c; - - /* no bogus surrogates */ - if (0xd800 <= uchar && uchar <= 0xdfff) - goto fail; - - /* - * 4-byte sequence (surrogate pairs, currently rare): - * 11101110wwwwzzzzyy + 110111yyyyxxxxxx - * = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx - * (uuuuu = wwww + 1) - * FIXME accept the surrogate code points (only) - */ - } else - goto fail; - } else - uchar = c; - put_unaligned_le16(uchar, cp++); - count++; - len--; - } - return count; -fail: - return -1; -} - - -/** - * usb_gadget_get_string - fill out a string descriptor - * @table: of c strings encoded using UTF-8 - * @id: string id, from low byte of wValue in get string descriptor - * @buf: at least 256 bytes - * - * Finds the UTF-8 string matching the ID, and converts it into a - * string descriptor in utf16-le. - * Returns length of descriptor (always even) or negative errno - * - * If your driver needs stings in multiple languages, you'll probably - * "switch (wIndex) { ... }" in your ep0 string descriptor logic, - * using this routine after choosing which set of UTF-8 strings to use. - * Note that US-ASCII is a strict subset of UTF-8; any string bytes with - * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1 - * characters (which are also widely used in C strings). - */ -int -usb_gadget_get_string(struct usb_gadget_strings *table, int id, u8 *buf) -{ - struct usb_string *s; - int len; - - if (!table) - return -EINVAL; - - /* descriptor 0 has the language id */ - if (id == 0) { - buf[0] = 4; - buf[1] = USB_DT_STRING; - buf[2] = (u8) table->language; - buf[3] = (u8) (table->language >> 8); - return 4; - } - for (s = table->strings; s && s->s; s++) - if (s->id == id) - break; - - /* unrecognized: stall. */ - if (!s || !s->s) - return -EINVAL; - - /* string descriptors have length, tag, then UTF16-LE text */ - len = min((size_t) 126, strlen(s->s)); - memset(buf + 2, 0, 2 * len); /* zero all the bytes */ - len = utf8_to_utf16le(s->s, (__le16 *)&buf[2], len); - if (len < 0) - return -EINVAL; - buf[0] = (len + 1) * 2; - buf[1] = USB_DT_STRING; - return buf[0]; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/Makefile b/qemu/roms/u-boot/drivers/usb/host/Makefile deleted file mode 100644 index b301e2825..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# -# (C) Copyright 2000-2007 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -# ohci -obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o -obj-$(CONFIG_USB_ATMEL) += ohci-at91.o -obj-$(CONFIG_USB_OHCI_DA8XX) += ohci-da8xx.o -obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o -obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o -obj-$(CONFIG_USB_SL811HS) += sl811-hcd.o -obj-$(CONFIG_USB_OHCI_S3C24XX) += ohci-s3c24xx.o - -# echi -obj-$(CONFIG_USB_EHCI) += ehci-hcd.o -obj-$(CONFIG_USB_EHCI_ARMADA100) += ehci-armada100.o utmi-armada100.o -obj-$(CONFIG_USB_EHCI_ATMEL) += ehci-atmel.o -ifdef CONFIG_MPC512X -obj-$(CONFIG_USB_EHCI_FSL) += ehci-mpc512x.o -else -obj-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o -endif -obj-$(CONFIG_USB_EHCI_FARADAY) += ehci-faraday.o -obj-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o -obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o -obj-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o -obj-$(CONFIG_USB_EHCI_MX5) += ehci-mx5.o -obj-$(CONFIG_USB_EHCI_MX6) += ehci-mx6.o -obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o -obj-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o -obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o -obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o -obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o -obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o -obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o -obj-$(CONFIG_USB_EHCI_RMOBILE) += ehci-rmobile.o - -# xhci -obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o -obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o -obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-armada100.c b/qemu/roms/u-boot/drivers/usb/host/ehci-armada100.c deleted file mode 100644 index 012eb3a1a..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-armada100.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * (C) Copyright 2012 - * eInfochips Ltd. <www.einfochips.com> - * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com> - * - * This driver is based on Kirkwood echi driver - * (C) Copyright 2009 - * Marvell Semiconductor <www.marvell.com> - * Written-by: Prafulla Wadaskar <prafulla@marvell.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include "ehci.h" -#include <asm/arch/cpu.h> -#include <asm/arch/armada100.h> -#include <asm/arch/utmi-armada100.h> - -/* - * EHCI host controller init - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - if (utmi_init() < 0) - return -1; - - *hccr = (struct ehci_hccr *)(ARMD1_USB_HOST_BASE + 0x100); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr - + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - debug("armada100-ehci: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -/* - * EHCI host controller stop - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-atmel.c b/qemu/roms/u-boot/drivers/usb/host/ehci-atmel.c deleted file mode 100644 index 9ffe5010b..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-atmel.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * (C) Copyright 2012 - * Atmel Semiconductor <www.atmel.com> - * Written-by: Bo Shen <voice.shen@atmel.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <watchdog.h> -#include <usb.h> -#include <asm/io.h> -#include <asm/arch/hardware.h> -#include <asm/arch/at91_pmc.h> -#include <asm/arch/clk.h> - -#include "ehci.h" - -/* Enable UTMI PLL time out 500us - * 10 times as datasheet specified - */ -#define EN_UPLL_TIMEOUT 500UL - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; - ulong start_time, tmp_time; - - start_time = get_timer(0); - /* Enable UTMI PLL */ - writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKU) != AT91_PMC_LOCKU) { - WATCHDOG_RESET(); - tmp_time = get_timer(0); - if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) { - printf("ERROR: failed to enable UPLL\n"); - return -1; - } - } - - /* Enable USB Host clock */ - writel(1 << ATMEL_ID_UHPHS, &pmc->pcer); - - *hccr = (struct ehci_hccr *)ATMEL_BASE_EHCI; - *hcor = (struct ehci_hcor *)((uint32_t)*hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -int ehci_hcd_stop(int index) -{ - at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; - ulong start_time, tmp_time; - - /* Disable USB Host Clock */ - writel(1 << ATMEL_ID_UHPHS, &pmc->pcdr); - - start_time = get_timer(0); - /* Disable UTMI PLL */ - writel(readl(&pmc->uckr) & ~AT91_PMC_UPLLEN, &pmc->uckr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKU) == AT91_PMC_LOCKU) { - WATCHDOG_RESET(); - tmp_time = get_timer(0); - if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) { - printf("ERROR: failed to stop UPLL\n"); - return -1; - } - } - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-exynos.c b/qemu/roms/u-boot/drivers/usb/host/ehci-exynos.c deleted file mode 100644 index edd91a84a..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-exynos.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * SAMSUNG EXYNOS USB HOST EHCI Controller - * - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Vivek Gautam <gautam.vivek@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <fdtdec.h> -#include <libfdt.h> -#include <malloc.h> -#include <usb.h> -#include <asm/arch/cpu.h> -#include <asm/arch/ehci.h> -#include <asm/arch/system.h> -#include <asm/arch/power.h> -#include <asm/gpio.h> -#include <asm-generic/errno.h> -#include <linux/compat.h> -#include "ehci.h" - -/* Declare global data pointer */ -DECLARE_GLOBAL_DATA_PTR; - -/** - * Contains pointers to register base addresses - * for the usb controller. - */ -struct exynos_ehci { - struct exynos_usb_phy *usb; - struct ehci_hccr *hcd; - struct fdt_gpio_state vbus_gpio; -}; - -static struct exynos_ehci exynos; - -#ifdef CONFIG_OF_CONTROL -static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos) -{ - fdt_addr_t addr; - unsigned int node; - int depth; - - node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_EHCI); - if (node <= 0) { - debug("EHCI: Can't get device node for ehci\n"); - return -ENODEV; - } - - /* - * Get the base address for EHCI controller from the device node - */ - addr = fdtdec_get_addr(blob, node, "reg"); - if (addr == FDT_ADDR_T_NONE) { - debug("Can't get the EHCI register address\n"); - return -ENXIO; - } - - exynos->hcd = (struct ehci_hccr *)addr; - - /* Vbus gpio */ - fdtdec_decode_gpio(blob, node, "samsung,vbus-gpio", &exynos->vbus_gpio); - - depth = 0; - node = fdtdec_next_compatible_subnode(blob, node, - COMPAT_SAMSUNG_EXYNOS_USB_PHY, &depth); - if (node <= 0) { - debug("EHCI: Can't get device node for usb-phy controller\n"); - return -ENODEV; - } - - /* - * Get the base address for usbphy from the device node - */ - exynos->usb = (struct exynos_usb_phy *)fdtdec_get_addr(blob, node, - "reg"); - if (exynos->usb == NULL) { - debug("Can't get the usbphy register address\n"); - return -ENXIO; - } - - return 0; -} -#endif - -/* Setup the EHCI host controller. */ -static void setup_usb_phy(struct exynos_usb_phy *usb) -{ - u32 hsic_ctrl; - - set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN); - - set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN); - - clrbits_le32(&usb->usbphyctrl0, - HOST_CTRL0_FSEL_MASK | - HOST_CTRL0_COMMONON_N | - /* HOST Phy setting */ - HOST_CTRL0_PHYSWRST | - HOST_CTRL0_PHYSWRSTALL | - HOST_CTRL0_SIDDQ | - HOST_CTRL0_FORCESUSPEND | - HOST_CTRL0_FORCESLEEP); - - setbits_le32(&usb->usbphyctrl0, - /* Setting up the ref freq */ - (CLK_24MHZ << 16) | - /* HOST Phy setting */ - HOST_CTRL0_LINKSWRST | - HOST_CTRL0_UTMISWRST); - udelay(10); - clrbits_le32(&usb->usbphyctrl0, - HOST_CTRL0_LINKSWRST | - HOST_CTRL0_UTMISWRST); - - /* HSIC Phy Setting */ - hsic_ctrl = (HSIC_CTRL_FORCESUSPEND | - HSIC_CTRL_FORCESLEEP | - HSIC_CTRL_SIDDQ); - - clrbits_le32(&usb->hsicphyctrl1, hsic_ctrl); - clrbits_le32(&usb->hsicphyctrl2, hsic_ctrl); - - hsic_ctrl = (((HSIC_CTRL_REFCLKDIV_12 & HSIC_CTRL_REFCLKDIV_MASK) - << HSIC_CTRL_REFCLKDIV_SHIFT) - | ((HSIC_CTRL_REFCLKSEL & HSIC_CTRL_REFCLKSEL_MASK) - << HSIC_CTRL_REFCLKSEL_SHIFT) - | HSIC_CTRL_UTMISWRST); - - setbits_le32(&usb->hsicphyctrl1, hsic_ctrl); - setbits_le32(&usb->hsicphyctrl2, hsic_ctrl); - - udelay(10); - - clrbits_le32(&usb->hsicphyctrl1, HSIC_CTRL_PHYSWRST | - HSIC_CTRL_UTMISWRST); - - clrbits_le32(&usb->hsicphyctrl2, HSIC_CTRL_PHYSWRST | - HSIC_CTRL_UTMISWRST); - - udelay(20); - - /* EHCI Ctrl setting */ - setbits_le32(&usb->ehcictrl, - EHCICTRL_ENAINCRXALIGN | - EHCICTRL_ENAINCR4 | - EHCICTRL_ENAINCR8 | - EHCICTRL_ENAINCR16); -} - -/* Reset the EHCI host controller. */ -static void reset_usb_phy(struct exynos_usb_phy *usb) -{ - u32 hsic_ctrl; - - /* HOST_PHY reset */ - setbits_le32(&usb->usbphyctrl0, - HOST_CTRL0_PHYSWRST | - HOST_CTRL0_PHYSWRSTALL | - HOST_CTRL0_SIDDQ | - HOST_CTRL0_FORCESUSPEND | - HOST_CTRL0_FORCESLEEP); - - /* HSIC Phy reset */ - hsic_ctrl = (HSIC_CTRL_FORCESUSPEND | - HSIC_CTRL_FORCESLEEP | - HSIC_CTRL_SIDDQ | - HSIC_CTRL_PHYSWRST); - - setbits_le32(&usb->hsicphyctrl1, hsic_ctrl); - setbits_le32(&usb->hsicphyctrl2, hsic_ctrl); - - set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE); -} - -/* - * EHCI-initialization - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - struct exynos_ehci *ctx = &exynos; - -#ifdef CONFIG_OF_CONTROL - if (exynos_usb_parse_dt(gd->fdt_blob, ctx)) { - debug("Unable to parse device tree for ehci-exynos\n"); - return -ENODEV; - } -#else - ctx->usb = (struct exynos_usb_phy *)samsung_get_base_usb_phy(); - ctx->hcd = (struct ehci_hccr *)samsung_get_base_usb_ehci(); -#endif - -#ifdef CONFIG_OF_CONTROL - /* setup the Vbus gpio here */ - if (fdt_gpio_isvalid(&ctx->vbus_gpio) && - !fdtdec_setup_gpio(&ctx->vbus_gpio)) - gpio_direction_output(ctx->vbus_gpio.gpio, 1); -#endif - - setup_usb_phy(ctx->usb); - - board_usb_init(index, init); - - *hccr = ctx->hcd; - *hcor = (struct ehci_hcor *)((uint32_t) *hccr - + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - debug("Exynos5-ehci: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - struct exynos_ehci *ctx = &exynos; - - reset_usb_phy(ctx->usb); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-faraday.c b/qemu/roms/u-boot/drivers/usb/host/ehci-faraday.c deleted file mode 100644 index 3b761bc32..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-faraday.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Faraday USB 2.0 EHCI Controller - * - * (C) Copyright 2010 Faraday Technology - * Dante Su <dantesu@faraday-tech.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include <usb/fusbh200.h> -#include <usb/fotg210.h> - -#include "ehci.h" - -#ifndef CONFIG_USB_EHCI_BASE_LIST -#define CONFIG_USB_EHCI_BASE_LIST { CONFIG_USB_EHCI_BASE } -#endif - -union ehci_faraday_regs { - struct fusbh200_regs usb; - struct fotg210_regs otg; -}; - -static inline int ehci_is_fotg2xx(union ehci_faraday_regs *regs) -{ - return !readl(®s->usb.easstr); -} - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **ret_hccr, struct ehci_hcor **ret_hcor) -{ - struct ehci_hccr *hccr; - struct ehci_hcor *hcor; - union ehci_faraday_regs *regs; - uint32_t base_list[] = CONFIG_USB_EHCI_BASE_LIST; - - if (index < 0 || index >= ARRAY_SIZE(base_list)) - return -1; - regs = (void __iomem *)base_list[index]; - hccr = (struct ehci_hccr *)®s->usb.hccr; - hcor = (struct ehci_hcor *)®s->usb.hcor; - - if (ehci_is_fotg2xx(regs)) { - /* A-device bus reset */ - /* ... Power off A-device */ - setbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSDROP); - /* ... Drop vbus and bus traffic */ - clrbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSREQ); - mdelay(1); - /* ... Power on A-device */ - clrbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSDROP); - /* ... Drive vbus and bus traffic */ - setbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSREQ); - mdelay(1); - /* Disable OTG & DEV interrupts, triggered at level-high */ - writel(IMR_IRQLH | IMR_OTG | IMR_DEV, ®s->otg.imr); - /* Clear all interrupt status */ - writel(ISR_HOST | ISR_OTG | ISR_DEV, ®s->otg.isr); - } else { - /* Interrupt=level-high */ - setbits_le32(®s->usb.bmcsr, BMCSR_IRQLH); - /* VBUS on */ - clrbits_le32(®s->usb.bmcsr, BMCSR_VBUS_OFF); - /* Disable all interrupts */ - writel(0x00, ®s->usb.bmier); - writel(0x1f, ®s->usb.bmisr); - } - - *ret_hccr = hccr; - *ret_hcor = hcor; - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} - -/* - * This ehci_set_usbmode() overrides the weak function - * in "ehci-hcd.c". - */ -void ehci_set_usbmode(int index) -{ - /* nothing needs to be done */ -} - -/* - * This ehci_get_port_speed() overrides the weak function - * in "ehci-hcd.c". - */ -int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) -{ - int spd, ret = PORTSC_PSPD_HS; - union ehci_faraday_regs *regs = (void __iomem *)((ulong)hcor - 0x10); - - if (ehci_is_fotg2xx(regs)) - spd = OTGCSR_SPD(readl(®s->otg.otgcsr)); - else - spd = BMCSR_SPD(readl(®s->usb.bmcsr)); - - switch (spd) { - case 0: /* full speed */ - ret = PORTSC_PSPD_FS; - break; - case 1: /* low speed */ - ret = PORTSC_PSPD_LS; - break; - case 2: /* high speed */ - ret = PORTSC_PSPD_HS; - break; - default: - printf("ehci-faraday: invalid device speed\n"); - break; - } - - return ret; -} - -/* - * This ehci_get_portsc_register() overrides the weak function - * in "ehci-hcd.c". - */ -uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) -{ - /* Faraday EHCI has one and only one portsc register */ - if (port) { - /* Printing the message would cause a scan failure! */ - debug("The request port(%d) is not configured\n", port); - return NULL; - } - - /* Faraday EHCI PORTSC register offset is 0x20 from hcor */ - return (uint32_t *)((uint8_t *)hcor + 0x20); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-fsl.c b/qemu/roms/u-boot/drivers/usb/host/ehci-fsl.c deleted file mode 100644 index 6cb4d9866..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-fsl.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * (C) Copyright 2009, 2011 Freescale Semiconductor, Inc. - * - * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB - * - * Author: Tor Krill tor@excito.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <pci.h> -#include <usb.h> -#include <asm/io.h> -#include <usb/ehci-fsl.h> -#include <hwconfig.h> -#include <asm/fsl_errata.h> - -#include "ehci.h" - -static void set_txfifothresh(struct usb_ehci *, u32); - -/* Check USB PHY clock valid */ -static int usb_phy_clk_valid(struct usb_ehci *ehci) -{ - if (!((in_be32(&ehci->control) & PHY_CLK_VALID) || - in_be32(&ehci->prictrl))) { - printf("USB PHY clock invalid!\n"); - return 0; - } else { - return 1; - } -} - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - * - * Excerpts from linux ehci fsl driver. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - struct usb_ehci *ehci = NULL; - const char *phy_type = NULL; - size_t len; - char current_usb_controller[5]; -#ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY - char usb_phy[5]; - - usb_phy[0] = '\0'; -#endif - if (has_erratum_a007075()) { - /* - * A 5ms delay is needed after applying soft-reset to the - * controller to let external ULPI phy come out of reset. - * This delay needs to be added before re-initializing - * the controller after soft-resetting completes - */ - mdelay(5); - } - memset(current_usb_controller, '\0', 5); - snprintf(current_usb_controller, 4, "usb%d", index+1); - - switch (index) { - case 0: - ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR; - break; - case 1: - ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB2_ADDR; - break; - default: - printf("ERROR: wrong controller index!!\n"); - break; - }; - - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - /* Set to Host mode */ - setbits_le32(&ehci->usbmode, CM_HOST); - - out_be32(&ehci->snoop1, SNOOP_SIZE_2GB); - out_be32(&ehci->snoop2, 0x80000000 | SNOOP_SIZE_2GB); - - /* Init phy */ - if (hwconfig_sub(current_usb_controller, "phy_type")) - phy_type = hwconfig_subarg(current_usb_controller, - "phy_type", &len); - else - phy_type = getenv("usb_phy_type"); - - if (!phy_type) { -#ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY - /* if none specified assume internal UTMI */ - strcpy(usb_phy, "utmi"); - phy_type = usb_phy; -#else - printf("WARNING: USB phy type not defined !!\n"); - return -1; -#endif - } - - if (!strncmp(phy_type, "utmi", 4)) { -#if defined(CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY) - setbits_be32(&ehci->control, PHY_CLK_SEL_UTMI); - setbits_be32(&ehci->control, UTMI_PHY_EN); - udelay(1000); /* delay required for PHY Clk to appear */ -#endif - out_le32(&(*hcor)->or_portsc[0], PORT_PTS_UTMI); - setbits_be32(&ehci->control, USB_EN); - } else { - setbits_be32(&ehci->control, PHY_CLK_SEL_ULPI); - clrsetbits_be32(&ehci->control, UTMI_PHY_EN, USB_EN); - udelay(1000); /* delay required for PHY Clk to appear */ - if (!usb_phy_clk_valid(ehci)) - return -EINVAL; - out_le32(&(*hcor)->or_portsc[0], PORT_PTS_ULPI); - } - - out_be32(&ehci->prictrl, 0x0000000c); - out_be32(&ehci->age_cnt_limit, 0x00000040); - out_be32(&ehci->sictrl, 0x00000001); - - in_le32(&ehci->usbmode); - - if (SVR_SOC_VER(get_svr()) == SVR_T4240 && - IS_SVR_REV(get_svr(), 2, 0)) - set_txfifothresh(ehci, TXFIFOTHRESH); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} - -/* - * Setting the value of TXFIFO_THRESH field in TXFILLTUNING register - * to counter DDR latencies in writing data into Tx buffer. - * This prevents Tx buffer from getting underrun - */ -static void set_txfifothresh(struct usb_ehci *ehci, u32 txfifo_thresh) -{ - u32 cmd; - cmd = ehci_readl(&ehci->txfilltuning); - cmd &= ~TXFIFO_THRESH_MASK; - cmd |= TXFIFO_THRESH(txfifo_thresh); - ehci_writel(&ehci->txfilltuning, cmd); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-hcd.c b/qemu/roms/u-boot/drivers/usb/host/ehci-hcd.c deleted file mode 100644 index eaf59134c..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-hcd.c +++ /dev/null @@ -1,1404 +0,0 @@ -/*- - * Copyright (c) 2007-2008, Juniper Networks, Inc. - * Copyright (c) 2008, Excito Elektronik i Skåne AB - * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> - * - * All rights reserved. - * - * 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 version 2 of - * the License. - * - * 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., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include <common.h> -#include <errno.h> -#include <asm/byteorder.h> -#include <asm/unaligned.h> -#include <usb.h> -#include <asm/io.h> -#include <malloc.h> -#include <watchdog.h> -#include <linux/compiler.h> - -#include "ehci.h" - -#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT -#define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#endif - -/* - * EHCI spec page 20 says that the HC may take up to 16 uFrames (= 4ms) to halt. - * Let's time out after 8 to have a little safety margin on top of that. - */ -#define HCHALT_TIMEOUT (8 * 1000) - -static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; - -#define ALIGN_END_ADDR(type, ptr, size) \ - ((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN)) - -static struct descriptor { - struct usb_hub_descriptor hub; - struct usb_device_descriptor device; - struct usb_linux_config_descriptor config; - struct usb_linux_interface_descriptor interface; - struct usb_endpoint_descriptor endpoint; -} __attribute__ ((packed)) descriptor = { - { - 0x8, /* bDescLength */ - 0x29, /* bDescriptorType: hub descriptor */ - 2, /* bNrPorts -- runtime modified */ - 0, /* wHubCharacteristics */ - 10, /* bPwrOn2PwrGood */ - 0, /* bHubCntrCurrent */ - {}, /* Device removable */ - {} /* at most 7 ports! XXX */ - }, - { - 0x12, /* bLength */ - 1, /* bDescriptorType: UDESC_DEVICE */ - cpu_to_le16(0x0200), /* bcdUSB: v2.0 */ - 9, /* bDeviceClass: UDCLASS_HUB */ - 0, /* bDeviceSubClass: UDSUBCLASS_HUB */ - 1, /* bDeviceProtocol: UDPROTO_HSHUBSTT */ - 64, /* bMaxPacketSize: 64 bytes */ - 0x0000, /* idVendor */ - 0x0000, /* idProduct */ - cpu_to_le16(0x0100), /* bcdDevice */ - 1, /* iManufacturer */ - 2, /* iProduct */ - 0, /* iSerialNumber */ - 1 /* bNumConfigurations: 1 */ - }, - { - 0x9, - 2, /* bDescriptorType: UDESC_CONFIG */ - cpu_to_le16(0x19), - 1, /* bNumInterface */ - 1, /* bConfigurationValue */ - 0, /* iConfiguration */ - 0x40, /* bmAttributes: UC_SELF_POWER */ - 0 /* bMaxPower */ - }, - { - 0x9, /* bLength */ - 4, /* bDescriptorType: UDESC_INTERFACE */ - 0, /* bInterfaceNumber */ - 0, /* bAlternateSetting */ - 1, /* bNumEndpoints */ - 9, /* bInterfaceClass: UICLASS_HUB */ - 0, /* bInterfaceSubClass: UISUBCLASS_HUB */ - 0, /* bInterfaceProtocol: UIPROTO_HSHUBSTT */ - 0 /* iInterface */ - }, - { - 0x7, /* bLength */ - 5, /* bDescriptorType: UDESC_ENDPOINT */ - 0x81, /* bEndpointAddress: - * UE_DIR_IN | EHCI_INTR_ENDPT - */ - 3, /* bmAttributes: UE_INTERRUPT */ - 8, /* wMaxPacketSize */ - 255 /* bInterval */ - }, -}; - -#if defined(CONFIG_EHCI_IS_TDI) -#define ehci_is_TDI() (1) -#else -#define ehci_is_TDI() (0) -#endif - -int __ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) -{ - return PORTSC_PSPD(reg); -} - -int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) - __attribute__((weak, alias("__ehci_get_port_speed"))); - -void __ehci_set_usbmode(int index) -{ - uint32_t tmp; - uint32_t *reg_ptr; - - reg_ptr = (uint32_t *)((u8 *)&ehcic[index].hcor->or_usbcmd + USBMODE); - tmp = ehci_readl(reg_ptr); - tmp |= USBMODE_CM_HC; -#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) - tmp |= USBMODE_BE; -#endif - ehci_writel(reg_ptr, tmp); -} - -void ehci_set_usbmode(int index) - __attribute__((weak, alias("__ehci_set_usbmode"))); - -void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) -{ - mdelay(50); -} - -void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) - __attribute__((weak, alias("__ehci_powerup_fixup"))); - -static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) -{ - uint32_t result; - do { - result = ehci_readl(ptr); - udelay(5); - if (result == ~(uint32_t)0) - return -1; - result &= mask; - if (result == done) - return 0; - usec--; - } while (usec > 0); - return -1; -} - -static int ehci_reset(int index) -{ - uint32_t cmd; - int ret = 0; - - cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); - cmd = (cmd & ~CMD_RUN) | CMD_RESET; - ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); - ret = handshake((uint32_t *)&ehcic[index].hcor->or_usbcmd, - CMD_RESET, 0, 250 * 1000); - if (ret < 0) { - printf("EHCI fail to reset\n"); - goto out; - } - - if (ehci_is_TDI()) - ehci_set_usbmode(index); - -#ifdef CONFIG_USB_EHCI_TXFIFO_THRESH - cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning); - cmd &= ~TXFIFO_THRESH_MASK; - cmd |= TXFIFO_THRESH(CONFIG_USB_EHCI_TXFIFO_THRESH); - ehci_writel(&ehcic[index].hcor->or_txfilltuning, cmd); -#endif -out: - return ret; -} - -static int ehci_shutdown(struct ehci_ctrl *ctrl) -{ - int i, ret = 0; - uint32_t cmd, reg; - - if (!ctrl || !ctrl->hcor) - return -EINVAL; - - cmd = ehci_readl(&ctrl->hcor->or_usbcmd); - cmd &= ~(CMD_PSE | CMD_ASE); - ehci_writel(&ctrl->hcor->or_usbcmd, cmd); - ret = handshake(&ctrl->hcor->or_usbsts, STS_ASS | STS_PSS, 0, - 100 * 1000); - - if (!ret) { - for (i = 0; i < CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS; i++) { - reg = ehci_readl(&ctrl->hcor->or_portsc[i]); - reg |= EHCI_PS_SUSP; - ehci_writel(&ctrl->hcor->or_portsc[i], reg); - } - - cmd &= ~CMD_RUN; - ehci_writel(&ctrl->hcor->or_usbcmd, cmd); - ret = handshake(&ctrl->hcor->or_usbsts, STS_HALT, STS_HALT, - HCHALT_TIMEOUT); - } - - if (ret) - puts("EHCI failed to shut down host controller.\n"); - - return ret; -} - -static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz) -{ - uint32_t delta, next; - uint32_t addr = (uint32_t)buf; - int idx; - - if (addr != ALIGN(addr, ARCH_DMA_MINALIGN)) - debug("EHCI-HCD: Misaligned buffer address (%p)\n", buf); - - flush_dcache_range(addr, ALIGN(addr + sz, ARCH_DMA_MINALIGN)); - - idx = 0; - while (idx < QT_BUFFER_CNT) { - td->qt_buffer[idx] = cpu_to_hc32(addr); - td->qt_buffer_hi[idx] = 0; - next = (addr + EHCI_PAGE_SIZE) & ~(EHCI_PAGE_SIZE - 1); - delta = next - addr; - if (delta >= sz) - break; - sz -= delta; - addr = next; - idx++; - } - - if (idx == QT_BUFFER_CNT) { - printf("out of buffer pointers (%u bytes left)\n", sz); - return -1; - } - - return 0; -} - -static inline u8 ehci_encode_speed(enum usb_device_speed speed) -{ - #define QH_HIGH_SPEED 2 - #define QH_FULL_SPEED 0 - #define QH_LOW_SPEED 1 - if (speed == USB_SPEED_HIGH) - return QH_HIGH_SPEED; - if (speed == USB_SPEED_LOW) - return QH_LOW_SPEED; - return QH_FULL_SPEED; -} - -static int -ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, struct devrequest *req) -{ - ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN); - struct qTD *qtd; - int qtd_count = 0; - int qtd_counter = 0; - volatile struct qTD *vtd; - unsigned long ts; - uint32_t *tdp; - uint32_t endpt, maxpacket, token, usbsts; - uint32_t c, toggle; - uint32_t cmd; - int timeout; - int ret = 0; - struct ehci_ctrl *ctrl = dev->controller; - - debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, - buffer, length, req); - if (req != NULL) - debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n", - req->request, req->request, - req->requesttype, req->requesttype, - le16_to_cpu(req->value), le16_to_cpu(req->value), - le16_to_cpu(req->index)); - -#define PKT_ALIGN 512 - /* - * The USB transfer is split into qTD transfers. Eeach qTD transfer is - * described by a transfer descriptor (the qTD). The qTDs form a linked - * list with a queue head (QH). - * - * Each qTD transfer starts with a new USB packet, i.e. a packet cannot - * have its beginning in a qTD transfer and its end in the following - * one, so the qTD transfer lengths have to be chosen accordingly. - * - * Each qTD transfer uses up to QT_BUFFER_CNT data buffers, mapped to - * single pages. The first data buffer can start at any offset within a - * page (not considering the cache-line alignment issues), while the - * following buffers must be page-aligned. There is no alignment - * constraint on the size of a qTD transfer. - */ - if (req != NULL) - /* 1 qTD will be needed for SETUP, and 1 for ACK. */ - qtd_count += 1 + 1; - if (length > 0 || req == NULL) { - /* - * Determine the qTD transfer size that will be used for the - * data payload (not considering the first qTD transfer, which - * may be longer or shorter, and the final one, which may be - * shorter). - * - * In order to keep each packet within a qTD transfer, the qTD - * transfer size is aligned to PKT_ALIGN, which is a multiple of - * wMaxPacketSize (except in some cases for interrupt transfers, - * see comment in submit_int_msg()). - * - * By default, i.e. if the input buffer is aligned to PKT_ALIGN, - * QT_BUFFER_CNT full pages will be used. - */ - int xfr_sz = QT_BUFFER_CNT; - /* - * However, if the input buffer is not aligned to PKT_ALIGN, the - * qTD transfer size will be one page shorter, and the first qTD - * data buffer of each transfer will be page-unaligned. - */ - if ((uint32_t)buffer & (PKT_ALIGN - 1)) - xfr_sz--; - /* Convert the qTD transfer size to bytes. */ - xfr_sz *= EHCI_PAGE_SIZE; - /* - * Approximate by excess the number of qTDs that will be - * required for the data payload. The exact formula is way more - * complicated and saves at most 2 qTDs, i.e. a total of 128 - * bytes. - */ - qtd_count += 2 + length / xfr_sz; - } -/* - * Threshold value based on the worst-case total size of the allocated qTDs for - * a mass-storage transfer of 65535 blocks of 512 bytes. - */ -#if CONFIG_SYS_MALLOC_LEN <= 64 + 128 * 1024 -#warning CONFIG_SYS_MALLOC_LEN may be too small for EHCI -#endif - qtd = memalign(USB_DMA_MINALIGN, qtd_count * sizeof(struct qTD)); - if (qtd == NULL) { - printf("unable to allocate TDs\n"); - return -1; - } - - memset(qh, 0, sizeof(struct QH)); - memset(qtd, 0, qtd_count * sizeof(*qtd)); - - toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); - - /* - * Setup QH (3.6 in ehci-r10.pdf) - * - * qh_link ................. 03-00 H - * qh_endpt1 ............... 07-04 H - * qh_endpt2 ............... 0B-08 H - * - qh_curtd - * qh_overlay.qt_next ...... 13-10 H - * - qh_overlay.qt_altnext - */ - qh->qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list | QH_LINK_TYPE_QH); - c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe); - maxpacket = usb_maxpacket(dev, pipe); - endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) | - QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) | - QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) | - QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | - QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) | - QH_ENDPT1_DEVADDR(usb_pipedevice(pipe)); - qh->qh_endpt1 = cpu_to_hc32(endpt); - endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_PORTNUM(dev->portnr) | - QH_ENDPT2_HUBADDR(dev->parent->devnum) | - QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0); - qh->qh_endpt2 = cpu_to_hc32(endpt); - qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - - tdp = &qh->qh_overlay.qt_next; - - if (req != NULL) { - /* - * Setup request qTD (3.5 in ehci-r10.pdf) - * - * qt_next ................ 03-00 H - * qt_altnext ............. 07-04 H - * qt_token ............... 0B-08 H - * - * [ buffer, buffer_hi ] loaded with "req". - */ - qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - token = QT_TOKEN_DT(0) | QT_TOKEN_TOTALBYTES(sizeof(*req)) | - QT_TOKEN_IOC(0) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | - QT_TOKEN_PID(QT_TOKEN_PID_SETUP) | - QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); - qtd[qtd_counter].qt_token = cpu_to_hc32(token); - if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req))) { - printf("unable to construct SETUP TD\n"); - goto fail; - } - /* Update previous qTD! */ - *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); - tdp = &qtd[qtd_counter++].qt_next; - toggle = 1; - } - - if (length > 0 || req == NULL) { - uint8_t *buf_ptr = buffer; - int left_length = length; - - do { - /* - * Determine the size of this qTD transfer. By default, - * QT_BUFFER_CNT full pages can be used. - */ - int xfr_bytes = QT_BUFFER_CNT * EHCI_PAGE_SIZE; - /* - * However, if the input buffer is not page-aligned, the - * portion of the first page before the buffer start - * offset within that page is unusable. - */ - xfr_bytes -= (uint32_t)buf_ptr & (EHCI_PAGE_SIZE - 1); - /* - * In order to keep each packet within a qTD transfer, - * align the qTD transfer size to PKT_ALIGN. - */ - xfr_bytes &= ~(PKT_ALIGN - 1); - /* - * This transfer may be shorter than the available qTD - * transfer size that has just been computed. - */ - xfr_bytes = min(xfr_bytes, left_length); - - /* - * Setup request qTD (3.5 in ehci-r10.pdf) - * - * qt_next ................ 03-00 H - * qt_altnext ............. 07-04 H - * qt_token ............... 0B-08 H - * - * [ buffer, buffer_hi ] loaded with "buffer". - */ - qtd[qtd_counter].qt_next = - cpu_to_hc32(QT_NEXT_TERMINATE); - qtd[qtd_counter].qt_altnext = - cpu_to_hc32(QT_NEXT_TERMINATE); - token = QT_TOKEN_DT(toggle) | - QT_TOKEN_TOTALBYTES(xfr_bytes) | - QT_TOKEN_IOC(req == NULL) | QT_TOKEN_CPAGE(0) | - QT_TOKEN_CERR(3) | - QT_TOKEN_PID(usb_pipein(pipe) ? - QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) | - QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); - qtd[qtd_counter].qt_token = cpu_to_hc32(token); - if (ehci_td_buffer(&qtd[qtd_counter], buf_ptr, - xfr_bytes)) { - printf("unable to construct DATA TD\n"); - goto fail; - } - /* Update previous qTD! */ - *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); - tdp = &qtd[qtd_counter++].qt_next; - /* - * Data toggle has to be adjusted since the qTD transfer - * size is not always an even multiple of - * wMaxPacketSize. - */ - if ((xfr_bytes / maxpacket) & 1) - toggle ^= 1; - buf_ptr += xfr_bytes; - left_length -= xfr_bytes; - } while (left_length > 0); - } - - if (req != NULL) { - /* - * Setup request qTD (3.5 in ehci-r10.pdf) - * - * qt_next ................ 03-00 H - * qt_altnext ............. 07-04 H - * qt_token ............... 0B-08 H - */ - qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - token = QT_TOKEN_DT(1) | QT_TOKEN_TOTALBYTES(0) | - QT_TOKEN_IOC(1) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | - QT_TOKEN_PID(usb_pipein(pipe) ? - QT_TOKEN_PID_OUT : QT_TOKEN_PID_IN) | - QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); - qtd[qtd_counter].qt_token = cpu_to_hc32(token); - /* Update previous qTD! */ - *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); - tdp = &qtd[qtd_counter++].qt_next; - } - - ctrl->qh_list.qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH); - - /* Flush dcache */ - flush_dcache_range((uint32_t)&ctrl->qh_list, - ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); - flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1)); - flush_dcache_range((uint32_t)qtd, - ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); - - /* Set async. queue head pointer. */ - ehci_writel(&ctrl->hcor->or_asynclistaddr, (uint32_t)&ctrl->qh_list); - - usbsts = ehci_readl(&ctrl->hcor->or_usbsts); - ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f)); - - /* Enable async. schedule. */ - cmd = ehci_readl(&ctrl->hcor->or_usbcmd); - cmd |= CMD_ASE; - ehci_writel(&ctrl->hcor->or_usbcmd, cmd); - - ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS, - 100 * 1000); - if (ret < 0) { - printf("EHCI fail timeout STS_ASS set\n"); - goto fail; - } - - /* Wait for TDs to be processed. */ - ts = get_timer(0); - vtd = &qtd[qtd_counter - 1]; - timeout = USB_TIMEOUT_MS(pipe); - do { - /* Invalidate dcache */ - invalidate_dcache_range((uint32_t)&ctrl->qh_list, - ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); - invalidate_dcache_range((uint32_t)qh, - ALIGN_END_ADDR(struct QH, qh, 1)); - invalidate_dcache_range((uint32_t)qtd, - ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); - - token = hc32_to_cpu(vtd->qt_token); - if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) - break; - WATCHDOG_RESET(); - } while (get_timer(ts) < timeout); - - /* - * Invalidate the memory area occupied by buffer - * Don't try to fix the buffer alignment, if it isn't properly - * aligned it's upper layer's fault so let invalidate_dcache_range() - * vow about it. But we have to fix the length as it's actual - * transfer length and can be unaligned. This is potentially - * dangerous operation, it's responsibility of the calling - * code to make sure enough space is reserved. - */ - invalidate_dcache_range((uint32_t)buffer, - ALIGN((uint32_t)buffer + length, ARCH_DMA_MINALIGN)); - - /* Check that the TD processing happened */ - if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE) - printf("EHCI timed out on TD - token=%#x\n", token); - - /* Disable async schedule. */ - cmd = ehci_readl(&ctrl->hcor->or_usbcmd); - cmd &= ~CMD_ASE; - ehci_writel(&ctrl->hcor->or_usbcmd, cmd); - - ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0, - 100 * 1000); - if (ret < 0) { - printf("EHCI fail timeout STS_ASS reset\n"); - goto fail; - } - - token = hc32_to_cpu(qh->qh_overlay.qt_token); - if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) { - debug("TOKEN=%#x\n", token); - switch (QT_TOKEN_GET_STATUS(token) & - ~(QT_TOKEN_STATUS_SPLITXSTATE | QT_TOKEN_STATUS_PERR)) { - case 0: - toggle = QT_TOKEN_GET_DT(token); - usb_settoggle(dev, usb_pipeendpoint(pipe), - usb_pipeout(pipe), toggle); - dev->status = 0; - break; - case QT_TOKEN_STATUS_HALTED: - dev->status = USB_ST_STALLED; - break; - case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR: - case QT_TOKEN_STATUS_DATBUFERR: - dev->status = USB_ST_BUF_ERR; - break; - case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET: - case QT_TOKEN_STATUS_BABBLEDET: - dev->status = USB_ST_BABBLE_DET; - break; - default: - dev->status = USB_ST_CRC_ERR; - if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_HALTED) - dev->status |= USB_ST_STALLED; - break; - } - dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token); - } else { - dev->act_len = 0; -#ifndef CONFIG_USB_EHCI_FARADAY - debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n", - dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts), - ehci_readl(&ctrl->hcor->or_portsc[0]), - ehci_readl(&ctrl->hcor->or_portsc[1])); -#endif - } - - free(qtd); - return (dev->status != USB_ST_NOT_PROC) ? 0 : -1; - -fail: - free(qtd); - return -1; -} - -__weak uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) -{ - if (port < 0 || port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { - /* Printing the message would cause a scan failure! */ - debug("The request port(%u) is not configured\n", port); - return NULL; - } - - return (uint32_t *)&hcor->or_portsc[port]; -} - -int -ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, struct devrequest *req) -{ - uint8_t tmpbuf[4]; - u16 typeReq; - void *srcptr = NULL; - int len, srclen; - uint32_t reg; - uint32_t *status_reg; - int port = le16_to_cpu(req->index) & 0xff; - struct ehci_ctrl *ctrl = dev->controller; - - srclen = 0; - - debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n", - req->request, req->request, - req->requesttype, req->requesttype, - le16_to_cpu(req->value), le16_to_cpu(req->index)); - - typeReq = req->request | req->requesttype << 8; - - switch (typeReq) { - case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): - case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - status_reg = ehci_get_portsc_register(ctrl->hcor, port - 1); - if (!status_reg) - return -1; - break; - default: - status_reg = NULL; - break; - } - - switch (typeReq) { - case DeviceRequest | USB_REQ_GET_DESCRIPTOR: - switch (le16_to_cpu(req->value) >> 8) { - case USB_DT_DEVICE: - debug("USB_DT_DEVICE request\n"); - srcptr = &descriptor.device; - srclen = descriptor.device.bLength; - break; - case USB_DT_CONFIG: - debug("USB_DT_CONFIG config\n"); - srcptr = &descriptor.config; - srclen = descriptor.config.bLength + - descriptor.interface.bLength + - descriptor.endpoint.bLength; - break; - case USB_DT_STRING: - debug("USB_DT_STRING config\n"); - switch (le16_to_cpu(req->value) & 0xff) { - case 0: /* Language */ - srcptr = "\4\3\1\0"; - srclen = 4; - break; - case 1: /* Vendor */ - srcptr = "\16\3u\0-\0b\0o\0o\0t\0"; - srclen = 14; - break; - case 2: /* Product */ - srcptr = "\52\3E\0H\0C\0I\0 " - "\0H\0o\0s\0t\0 " - "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0"; - srclen = 42; - break; - default: - debug("unknown value DT_STRING %x\n", - le16_to_cpu(req->value)); - goto unknown; - } - break; - default: - debug("unknown value %x\n", le16_to_cpu(req->value)); - goto unknown; - } - break; - case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8): - switch (le16_to_cpu(req->value) >> 8) { - case USB_DT_HUB: - debug("USB_DT_HUB config\n"); - srcptr = &descriptor.hub; - srclen = descriptor.hub.bLength; - break; - default: - debug("unknown value %x\n", le16_to_cpu(req->value)); - goto unknown; - } - break; - case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8): - debug("USB_REQ_SET_ADDRESS\n"); - ctrl->rootdev = le16_to_cpu(req->value); - break; - case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: - debug("USB_REQ_SET_CONFIGURATION\n"); - /* Nothing to do */ - break; - case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8): - tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */ - tmpbuf[1] = 0; - srcptr = tmpbuf; - srclen = 2; - break; - case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): - memset(tmpbuf, 0, 4); - reg = ehci_readl(status_reg); - if (reg & EHCI_PS_CS) - tmpbuf[0] |= USB_PORT_STAT_CONNECTION; - if (reg & EHCI_PS_PE) - tmpbuf[0] |= USB_PORT_STAT_ENABLE; - if (reg & EHCI_PS_SUSP) - tmpbuf[0] |= USB_PORT_STAT_SUSPEND; - if (reg & EHCI_PS_OCA) - tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT; - if (reg & EHCI_PS_PR) - tmpbuf[0] |= USB_PORT_STAT_RESET; - if (reg & EHCI_PS_PP) - tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; - - if (ehci_is_TDI()) { - switch (ehci_get_port_speed(ctrl->hcor, reg)) { - case PORTSC_PSPD_FS: - break; - case PORTSC_PSPD_LS: - tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; - break; - case PORTSC_PSPD_HS: - default: - tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; - break; - } - } else { - tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; - } - - if (reg & EHCI_PS_CSC) - tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; - if (reg & EHCI_PS_PEC) - tmpbuf[2] |= USB_PORT_STAT_C_ENABLE; - if (reg & EHCI_PS_OCC) - tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT; - if (ctrl->portreset & (1 << port)) - tmpbuf[2] |= USB_PORT_STAT_C_RESET; - - srcptr = tmpbuf; - srclen = 4; - break; - case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - reg = ehci_readl(status_reg); - reg &= ~EHCI_PS_CLEAR; - switch (le16_to_cpu(req->value)) { - case USB_PORT_FEAT_ENABLE: - reg |= EHCI_PS_PE; - ehci_writel(status_reg, reg); - break; - case USB_PORT_FEAT_POWER: - if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) { - reg |= EHCI_PS_PP; - ehci_writel(status_reg, reg); - } - break; - case USB_PORT_FEAT_RESET: - if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS && - !ehci_is_TDI() && - EHCI_PS_IS_LOWSPEED(reg)) { - /* Low speed device, give up ownership. */ - debug("port %d low speed --> companion\n", - port - 1); - reg |= EHCI_PS_PO; - ehci_writel(status_reg, reg); - break; - } else { - int ret; - - reg |= EHCI_PS_PR; - reg &= ~EHCI_PS_PE; - ehci_writel(status_reg, reg); - /* - * caller must wait, then call GetPortStatus - * usb 2.0 specification say 50 ms resets on - * root - */ - ehci_powerup_fixup(status_reg, ®); - - ehci_writel(status_reg, reg & ~EHCI_PS_PR); - /* - * A host controller must terminate the reset - * and stabilize the state of the port within - * 2 milliseconds - */ - ret = handshake(status_reg, EHCI_PS_PR, 0, - 2 * 1000); - if (!ret) - ctrl->portreset |= 1 << port; - else - printf("port(%d) reset error\n", - port - 1); - } - break; - case USB_PORT_FEAT_TEST: - ehci_shutdown(ctrl); - reg &= ~(0xf << 16); - reg |= ((le16_to_cpu(req->index) >> 8) & 0xf) << 16; - ehci_writel(status_reg, reg); - break; - default: - debug("unknown feature %x\n", le16_to_cpu(req->value)); - goto unknown; - } - /* unblock posted writes */ - (void) ehci_readl(&ctrl->hcor->or_usbcmd); - break; - case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - reg = ehci_readl(status_reg); - reg &= ~EHCI_PS_CLEAR; - switch (le16_to_cpu(req->value)) { - case USB_PORT_FEAT_ENABLE: - reg &= ~EHCI_PS_PE; - break; - case USB_PORT_FEAT_C_ENABLE: - reg |= EHCI_PS_PE; - break; - case USB_PORT_FEAT_POWER: - if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) - reg &= ~EHCI_PS_PP; - break; - case USB_PORT_FEAT_C_CONNECTION: - reg |= EHCI_PS_CSC; - break; - case USB_PORT_FEAT_OVER_CURRENT: - reg |= EHCI_PS_OCC; - break; - case USB_PORT_FEAT_C_RESET: - ctrl->portreset &= ~(1 << port); - break; - default: - debug("unknown feature %x\n", le16_to_cpu(req->value)); - goto unknown; - } - ehci_writel(status_reg, reg); - /* unblock posted write */ - (void) ehci_readl(&ctrl->hcor->or_usbcmd); - break; - default: - debug("Unknown request\n"); - goto unknown; - } - - mdelay(1); - len = min3(srclen, le16_to_cpu(req->length), length); - if (srcptr != NULL && len > 0) - memcpy(buffer, srcptr, len); - else - debug("Len is 0\n"); - - dev->act_len = len; - dev->status = 0; - return 0; - -unknown: - debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\n", - req->requesttype, req->request, le16_to_cpu(req->value), - le16_to_cpu(req->index), le16_to_cpu(req->length)); - - dev->act_len = 0; - dev->status = USB_ST_STALLED; - return -1; -} - -int usb_lowlevel_stop(int index) -{ - ehci_shutdown(&ehcic[index]); - return ehci_hcd_stop(index); -} - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - uint32_t reg; - uint32_t cmd; - struct QH *qh_list; - struct QH *periodic; - int i; - int rc; - - rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor); - if (rc) - return rc; - if (init == USB_INIT_DEVICE) - goto done; - - /* EHCI spec section 4.1 */ - if (ehci_reset(index)) - return -1; - -#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET) - rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor); - if (rc) - return rc; -#endif - /* Set the high address word (aka segment) for 64-bit controller */ - if (ehci_readl(&ehcic[index].hccr->cr_hccparams) & 1) - ehci_writel(&ehcic[index].hcor->or_ctrldssegment, 0); - - qh_list = &ehcic[index].qh_list; - - /* Set head of reclaim list */ - memset(qh_list, 0, sizeof(*qh_list)); - qh_list->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH); - qh_list->qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) | - QH_ENDPT1_EPS(USB_SPEED_HIGH)); - qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE); - qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - qh_list->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - qh_list->qh_overlay.qt_token = - cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED)); - - flush_dcache_range((uint32_t)qh_list, - ALIGN_END_ADDR(struct QH, qh_list, 1)); - - /* Set async. queue head pointer. */ - ehci_writel(&ehcic[index].hcor->or_asynclistaddr, (uint32_t)qh_list); - - /* - * Set up periodic list - * Step 1: Parent QH for all periodic transfers. - */ - periodic = &ehcic[index].periodic_queue; - memset(periodic, 0, sizeof(*periodic)); - periodic->qh_link = cpu_to_hc32(QH_LINK_TERMINATE); - periodic->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - periodic->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - - flush_dcache_range((uint32_t)periodic, - ALIGN_END_ADDR(struct QH, periodic, 1)); - - /* - * Step 2: Setup frame-list: Every microframe, USB tries the same list. - * In particular, device specifications on polling frequency - * are disregarded. Keyboards seem to send NAK/NYet reliably - * when polled with an empty buffer. - * - * Split Transactions will be spread across microframes using - * S-mask and C-mask. - */ - if (ehcic[index].periodic_list == NULL) - ehcic[index].periodic_list = memalign(4096, 1024 * 4); - - if (!ehcic[index].periodic_list) - return -ENOMEM; - for (i = 0; i < 1024; i++) { - ehcic[index].periodic_list[i] = cpu_to_hc32((uint32_t)periodic - | QH_LINK_TYPE_QH); - } - - flush_dcache_range((uint32_t)ehcic[index].periodic_list, - ALIGN_END_ADDR(uint32_t, ehcic[index].periodic_list, - 1024)); - - /* Set periodic list base address */ - ehci_writel(&ehcic[index].hcor->or_periodiclistbase, - (uint32_t)ehcic[index].periodic_list); - - reg = ehci_readl(&ehcic[index].hccr->cr_hcsparams); - descriptor.hub.bNbrPorts = HCS_N_PORTS(reg); - debug("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); - /* Port Indicators */ - if (HCS_INDICATOR(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x80, &descriptor.hub.wHubCharacteristics); - /* Port Power Control */ - if (HCS_PPC(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x01, &descriptor.hub.wHubCharacteristics); - - /* Start the host controller. */ - cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); - /* - * Philips, Intel, and maybe others need CMD_RUN before the - * root hub will detect new devices (why?); NEC doesn't - */ - cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); - cmd |= CMD_RUN; - ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); - -#ifndef CONFIG_USB_EHCI_FARADAY - /* take control over the ports */ - cmd = ehci_readl(&ehcic[index].hcor->or_configflag); - cmd |= FLAG_CF; - ehci_writel(&ehcic[index].hcor->or_configflag, cmd); -#endif - - /* unblock posted write */ - cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); - mdelay(5); - reg = HC_VERSION(ehci_readl(&ehcic[index].hccr->cr_capbase)); - printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff); - - ehcic[index].rootdev = 0; -done: - *controller = &ehcic[index]; - return 0; -} - -int -submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length) -{ - - if (usb_pipetype(pipe) != PIPE_BULK) { - debug("non-bulk pipe (type=%lu)", usb_pipetype(pipe)); - return -1; - } - return ehci_submit_async(dev, pipe, buffer, length, NULL); -} - -int -submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, struct devrequest *setup) -{ - struct ehci_ctrl *ctrl = dev->controller; - - if (usb_pipetype(pipe) != PIPE_CONTROL) { - debug("non-control pipe (type=%lu)", usb_pipetype(pipe)); - return -1; - } - - if (usb_pipedevice(pipe) == ctrl->rootdev) { - if (!ctrl->rootdev) - dev->speed = USB_SPEED_HIGH; - return ehci_submit_root(dev, pipe, buffer, length, setup); - } - return ehci_submit_async(dev, pipe, buffer, length, setup); -} - -struct int_queue { - struct QH *first; - struct QH *current; - struct QH *last; - struct qTD *tds; -}; - -#define NEXT_QH(qh) (struct QH *)(hc32_to_cpu((qh)->qh_link) & ~0x1f) - -static int -enable_periodic(struct ehci_ctrl *ctrl) -{ - uint32_t cmd; - struct ehci_hcor *hcor = ctrl->hcor; - int ret; - - cmd = ehci_readl(&hcor->or_usbcmd); - cmd |= CMD_PSE; - ehci_writel(&hcor->or_usbcmd, cmd); - - ret = handshake((uint32_t *)&hcor->or_usbsts, - STS_PSS, STS_PSS, 100 * 1000); - if (ret < 0) { - printf("EHCI failed: timeout when enabling periodic list\n"); - return -ETIMEDOUT; - } - udelay(1000); - return 0; -} - -static int -disable_periodic(struct ehci_ctrl *ctrl) -{ - uint32_t cmd; - struct ehci_hcor *hcor = ctrl->hcor; - int ret; - - cmd = ehci_readl(&hcor->or_usbcmd); - cmd &= ~CMD_PSE; - ehci_writel(&hcor->or_usbcmd, cmd); - - ret = handshake((uint32_t *)&hcor->or_usbsts, - STS_PSS, 0, 100 * 1000); - if (ret < 0) { - printf("EHCI failed: timeout when disabling periodic list\n"); - return -ETIMEDOUT; - } - return 0; -} - -static int periodic_schedules; - -struct int_queue * -create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, - int elementsize, void *buffer) -{ - struct ehci_ctrl *ctrl = dev->controller; - struct int_queue *result = NULL; - int i; - - debug("Enter create_int_queue\n"); - if (usb_pipetype(pipe) != PIPE_INTERRUPT) { - debug("non-interrupt pipe (type=%lu)", usb_pipetype(pipe)); - return NULL; - } - - /* limit to 4 full pages worth of data - - * we can safely fit them in a single TD, - * no matter the alignment - */ - if (elementsize >= 16384) { - debug("too large elements for interrupt transfers\n"); - return NULL; - } - - result = malloc(sizeof(*result)); - if (!result) { - debug("ehci intr queue: out of memory\n"); - goto fail1; - } - result->first = memalign(USB_DMA_MINALIGN, - sizeof(struct QH) * queuesize); - if (!result->first) { - debug("ehci intr queue: out of memory\n"); - goto fail2; - } - result->current = result->first; - result->last = result->first + queuesize - 1; - result->tds = memalign(USB_DMA_MINALIGN, - sizeof(struct qTD) * queuesize); - if (!result->tds) { - debug("ehci intr queue: out of memory\n"); - goto fail3; - } - memset(result->first, 0, sizeof(struct QH) * queuesize); - memset(result->tds, 0, sizeof(struct qTD) * queuesize); - - for (i = 0; i < queuesize; i++) { - struct QH *qh = result->first + i; - struct qTD *td = result->tds + i; - void **buf = &qh->buffer; - - qh->qh_link = cpu_to_hc32((uint32_t)(qh+1) | QH_LINK_TYPE_QH); - if (i == queuesize - 1) - qh->qh_link = cpu_to_hc32(QH_LINK_TERMINATE); - - qh->qh_overlay.qt_next = cpu_to_hc32((uint32_t)td); - qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - qh->qh_endpt1 = - cpu_to_hc32((0 << 28) | /* No NAK reload (ehci 4.9) */ - (usb_maxpacket(dev, pipe) << 16) | /* MPS */ - (1 << 14) | - QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | - (usb_pipeendpoint(pipe) << 8) | /* Endpoint Number */ - (usb_pipedevice(pipe) << 0)); - qh->qh_endpt2 = cpu_to_hc32((1 << 30) | /* 1 Tx per mframe */ - (1 << 0)); /* S-mask: microframe 0 */ - if (dev->speed == USB_SPEED_LOW || - dev->speed == USB_SPEED_FULL) { - debug("TT: port: %d, hub address: %d\n", - dev->portnr, dev->parent->devnum); - qh->qh_endpt2 |= cpu_to_hc32((dev->portnr << 23) | - (dev->parent->devnum << 16) | - (0x1c << 8)); /* C-mask: microframes 2-4 */ - } - - td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - debug("communication direction is '%s'\n", - usb_pipein(pipe) ? "in" : "out"); - td->qt_token = cpu_to_hc32((elementsize << 16) | - ((usb_pipein(pipe) ? 1 : 0) << 8) | /* IN/OUT token */ - 0x80); /* active */ - td->qt_buffer[0] = - cpu_to_hc32((uint32_t)buffer + i * elementsize); - td->qt_buffer[1] = - cpu_to_hc32((td->qt_buffer[0] + 0x1000) & ~0xfff); - td->qt_buffer[2] = - cpu_to_hc32((td->qt_buffer[0] + 0x2000) & ~0xfff); - td->qt_buffer[3] = - cpu_to_hc32((td->qt_buffer[0] + 0x3000) & ~0xfff); - td->qt_buffer[4] = - cpu_to_hc32((td->qt_buffer[0] + 0x4000) & ~0xfff); - - *buf = buffer + i * elementsize; - } - - flush_dcache_range((uint32_t)buffer, - ALIGN_END_ADDR(char, buffer, - queuesize * elementsize)); - flush_dcache_range((uint32_t)result->first, - ALIGN_END_ADDR(struct QH, result->first, - queuesize)); - flush_dcache_range((uint32_t)result->tds, - ALIGN_END_ADDR(struct qTD, result->tds, - queuesize)); - - if (disable_periodic(ctrl) < 0) { - debug("FATAL: periodic should never fail, but did"); - goto fail3; - } - - /* hook up to periodic list */ - struct QH *list = &ctrl->periodic_queue; - result->last->qh_link = list->qh_link; - list->qh_link = cpu_to_hc32((uint32_t)result->first | QH_LINK_TYPE_QH); - - flush_dcache_range((uint32_t)result->last, - ALIGN_END_ADDR(struct QH, result->last, 1)); - flush_dcache_range((uint32_t)list, - ALIGN_END_ADDR(struct QH, list, 1)); - - if (enable_periodic(ctrl) < 0) { - debug("FATAL: periodic should never fail, but did"); - goto fail3; - } - periodic_schedules++; - - debug("Exit create_int_queue\n"); - return result; -fail3: - if (result->tds) - free(result->tds); -fail2: - if (result->first) - free(result->first); - if (result) - free(result); -fail1: - return NULL; -} - -void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) -{ - struct QH *cur = queue->current; - - /* depleted queue */ - if (cur == NULL) { - debug("Exit poll_int_queue with completed queue\n"); - return NULL; - } - /* still active */ - invalidate_dcache_range((uint32_t)cur, - ALIGN_END_ADDR(struct QH, cur, 1)); - if (cur->qh_overlay.qt_token & cpu_to_hc32(0x80)) { - debug("Exit poll_int_queue with no completed intr transfer. " - "token is %x\n", cur->qh_overlay.qt_token); - return NULL; - } - if (!(cur->qh_link & QH_LINK_TERMINATE)) - queue->current++; - else - queue->current = NULL; - debug("Exit poll_int_queue with completed intr transfer. " - "token is %x at %p (first at %p)\n", cur->qh_overlay.qt_token, - &cur->qh_overlay.qt_token, queue->first); - return cur->buffer; -} - -/* Do not free buffers associated with QHs, they're owned by someone else */ -int -destroy_int_queue(struct usb_device *dev, struct int_queue *queue) -{ - struct ehci_ctrl *ctrl = dev->controller; - int result = -1; - unsigned long timeout; - - if (disable_periodic(ctrl) < 0) { - debug("FATAL: periodic should never fail, but did"); - goto out; - } - periodic_schedules--; - - struct QH *cur = &ctrl->periodic_queue; - timeout = get_timer(0) + 500; /* abort after 500ms */ - while (!(cur->qh_link & cpu_to_hc32(QH_LINK_TERMINATE))) { - debug("considering %p, with qh_link %x\n", cur, cur->qh_link); - if (NEXT_QH(cur) == queue->first) { - debug("found candidate. removing from chain\n"); - cur->qh_link = queue->last->qh_link; - result = 0; - break; - } - cur = NEXT_QH(cur); - if (get_timer(0) > timeout) { - printf("Timeout destroying interrupt endpoint queue\n"); - result = -1; - goto out; - } - } - - if (periodic_schedules > 0) { - result = enable_periodic(ctrl); - if (result < 0) - debug("FATAL: periodic should never fail, but did"); - } - -out: - free(queue->tds); - free(queue->first); - free(queue); - - return result; -} - -int -submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, int interval) -{ - void *backbuffer; - struct int_queue *queue; - unsigned long timeout; - int result = 0, ret; - - debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d", - dev, pipe, buffer, length, interval); - - /* - * Interrupt transfers requiring several transactions are not supported - * because bInterval is ignored. - * - * Also, ehci_submit_async() relies on wMaxPacketSize being a power of 2 - * <= PKT_ALIGN if several qTDs are required, while the USB - * specification does not constrain this for interrupt transfers. That - * means that ehci_submit_async() would support interrupt transfers - * requiring several transactions only as long as the transfer size does - * not require more than a single qTD. - */ - if (length > usb_maxpacket(dev, pipe)) { - printf("%s: Interrupt transfers requiring several " - "transactions are not supported.\n", __func__); - return -1; - } - - queue = create_int_queue(dev, pipe, 1, length, buffer); - - timeout = get_timer(0) + USB_TIMEOUT_MS(pipe); - while ((backbuffer = poll_int_queue(dev, queue)) == NULL) - if (get_timer(0) > timeout) { - printf("Timeout poll on interrupt endpoint\n"); - result = -ETIMEDOUT; - break; - } - - if (backbuffer != buffer) { - debug("got wrong buffer back (%x instead of %x)\n", - (uint32_t)backbuffer, (uint32_t)buffer); - return -EINVAL; - } - - invalidate_dcache_range((uint32_t)buffer, - ALIGN_END_ADDR(char, buffer, length)); - - ret = destroy_int_queue(dev, queue); - if (ret < 0) - return ret; - - /* everything worked out fine */ - return result; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-marvell.c b/qemu/roms/u-boot/drivers/usb/host/ehci-marvell.c deleted file mode 100644 index 52c43fdc5..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-marvell.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * (C) Copyright 2009 - * Marvell Semiconductor <www.marvell.com> - * Written-by: Prafulla Wadaskar <prafulla@marvell.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include "ehci.h" -#include <asm/arch/cpu.h> - -#if defined(CONFIG_KIRKWOOD) -#include <asm/arch/kirkwood.h> -#elif defined(CONFIG_ORION5X) -#include <asm/arch/orion5x.h> -#endif - -DECLARE_GLOBAL_DATA_PTR; - -#define rdl(off) readl(MVUSB0_BASE + (off)) -#define wrl(off, val) writel((val), MVUSB0_BASE + (off)) - -#define USB_WINDOW_CTRL(i) (0x320 + ((i) << 4)) -#define USB_WINDOW_BASE(i) (0x324 + ((i) << 4)) -#define USB_TARGET_DRAM 0x0 - -/* - * USB 2.0 Bridge Address Decoding registers setup - */ -static void usb_brg_adrdec_setup(void) -{ - int i; - u32 size, base, attrib; - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - - /* Enable DRAM bank */ - switch (i) { - case 0: - attrib = MVUSB0_CPU_ATTR_DRAM_CS0; - break; - case 1: - attrib = MVUSB0_CPU_ATTR_DRAM_CS1; - break; - case 2: - attrib = MVUSB0_CPU_ATTR_DRAM_CS2; - break; - case 3: - attrib = MVUSB0_CPU_ATTR_DRAM_CS3; - break; - default: - /* invalide bank, disable access */ - attrib = 0; - break; - } - - size = gd->bd->bi_dram[i].size; - base = gd->bd->bi_dram[i].start; - if ((size) && (attrib)) - wrl(USB_WINDOW_CTRL(i), - MVCPU_WIN_CTRL_DATA(size, USB_TARGET_DRAM, - attrib, MVCPU_WIN_ENABLE)); - else - wrl(USB_WINDOW_CTRL(i), MVCPU_WIN_DISABLE); - - wrl(USB_WINDOW_BASE(i), base); - } -} - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - usb_brg_adrdec_setup(); - - *hccr = (struct ehci_hccr *)(MVUSB0_BASE + 0x100); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr - + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - debug("ehci-marvell: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-mpc512x.c b/qemu/roms/u-boot/drivers/usb/host/ehci-mpc512x.c deleted file mode 100644 index b320c4a4e..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-mpc512x.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * (C) Copyright 2010, Damien Dusha, <d.dusha@gmail.com> - * - * (C) Copyright 2009, Value Team S.p.A. - * Francesco Rendine, <francesco.rendine@valueteam.com> - * - * (C) Copyright 2009 Freescale Semiconductor, Inc. - * - * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB - * - * Author: Tor Krill tor@excito.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <pci.h> -#include <usb.h> -#include <asm/io.h> -#include <usb/ehci-fsl.h> - -#include "ehci.h" - -static void fsl_setup_phy(volatile struct ehci_hcor *); -static void fsl_platform_set_host_mode(volatile struct usb_ehci *ehci); -static int reset_usb_controller(volatile struct usb_ehci *ehci); -static void usb_platform_dr_init(volatile struct usb_ehci *ehci); - -/* - * Initialize SOC FSL EHCI Controller - * - * This code is derived from EHCI FSL USB Linux driver for MPC5121 - * - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - volatile struct usb_ehci *ehci; - - /* Hook the memory mapped registers for EHCI-Controller */ - ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR; - *hccr = (struct ehci_hccr *)((uint32_t)&(ehci->caplength)); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - /* configure interface for UTMI_WIDE */ - usb_platform_dr_init(ehci); - - /* Init Phy USB0 to UTMI+ */ - fsl_setup_phy(*hcor); - - /* Set to host mode */ - fsl_platform_set_host_mode(ehci); - - /* - * Setting the burst size seems to be required to prevent the - * USB from hanging when communicating with certain USB Mass - * storage devices. This was determined by analysing the - * EHCI registers under Linux vs U-Boot and burstsize was the - * major non-interrupt related difference between the two - * implementations. - * - * Some USB sticks behave better than others. In particular, - * the following USB stick is especially problematic: - * 0930:6545 Toshiba Corp - * - * The burstsize is set here to match the Linux implementation. - */ - out_be32(&ehci->burstsize, FSL_EHCI_TXPBURST(8) | - FSL_EHCI_RXPBURST(8)); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - volatile struct usb_ehci *ehci; - int exit_status = 0; - - /* Reset the USB controller */ - ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR; - exit_status = reset_usb_controller(ehci); - - return exit_status; -} - -static int reset_usb_controller(volatile struct usb_ehci *ehci) -{ - unsigned int i; - - /* Command a reset of the USB Controller */ - out_be32(&(ehci->usbcmd), EHCI_FSL_USBCMD_RST); - - /* Wait for the reset process to finish */ - for (i = 65535 ; i > 0 ; i--) { - /* - * The host will set this bit to zero once the - * reset process is complete - */ - if ((in_be32(&(ehci->usbcmd)) & EHCI_FSL_USBCMD_RST) == 0) - return 0; - } - - /* Hub did not reset in time */ - return -1; -} - -static void fsl_setup_phy(volatile struct ehci_hcor *hcor) -{ - uint32_t portsc; - - portsc = ehci_readl(&hcor->or_portsc[0]); - portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); - - /* Enable the phy mode to UTMI Wide */ - portsc |= PORT_PTS_PTW; - portsc |= PORT_PTS_UTMI; - - ehci_writel(&hcor->or_portsc[0], portsc); -} - -static void fsl_platform_set_host_mode(volatile struct usb_ehci *ehci) -{ - uint32_t temp; - - temp = in_le32(&ehci->usbmode); - temp |= CM_HOST | ES_BE; - out_le32(&ehci->usbmode, temp); -} - -static void usb_platform_dr_init(volatile struct usb_ehci *ehci) -{ - /* Configure interface for UTMI_WIDE */ - out_be32(&ehci->isiphyctrl, PHYCTRL_PHYE | PHYCTRL_PXE); - out_be32(&ehci->usbgenctrl, GC_PPP | GC_PFP ); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-mx5.c b/qemu/roms/u-boot/drivers/usb/host/ehci-mx5.c deleted file mode 100644 index 7566c6128..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-mx5.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> - * Copyright (C) 2010 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> -#include <errno.h> -#include <linux/compiler.h> -#include <usb/ehci-fsl.h> -#include <asm/io.h> -#include <asm/arch/imx-regs.h> -#include <asm/arch/clock.h> - -#include "ehci.h" - -#define MX5_USBOTHER_REGS_OFFSET 0x800 - - -#define MXC_OTG_OFFSET 0 -#define MXC_H1_OFFSET 0x200 -#define MXC_H2_OFFSET 0x400 -#define MXC_H3_OFFSET 0x600 - -#define MXC_USBCTRL_OFFSET 0 -#define MXC_USB_PHY_CTR_FUNC_OFFSET 0x8 -#define MXC_USB_PHY_CTR_FUNC2_OFFSET 0xc -#define MXC_USB_CTRL_1_OFFSET 0x10 -#define MXC_USBH2CTRL_OFFSET 0x14 -#define MXC_USBH3CTRL_OFFSET 0x18 - -/* USB_CTRL */ -/* OTG wakeup intr enable */ -#define MXC_OTG_UCTRL_OWIE_BIT (1 << 27) -/* OTG power mask */ -#define MXC_OTG_UCTRL_OPM_BIT (1 << 24) -/* OTG power pin polarity */ -#define MXC_OTG_UCTRL_O_PWR_POL_BIT (1 << 24) -/* Host1 ULPI interrupt enable */ -#define MXC_H1_UCTRL_H1UIE_BIT (1 << 12) -/* HOST1 wakeup intr enable */ -#define MXC_H1_UCTRL_H1WIE_BIT (1 << 11) -/* HOST1 power mask */ -#define MXC_H1_UCTRL_H1PM_BIT (1 << 8) -/* HOST1 power pin polarity */ -#define MXC_H1_UCTRL_H1_PWR_POL_BIT (1 << 8) - -/* USB_PHY_CTRL_FUNC */ -/* OTG Polarity of Overcurrent */ -#define MXC_OTG_PHYCTRL_OC_POL_BIT (1 << 9) -/* OTG Disable Overcurrent Event */ -#define MXC_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) -/* UH1 Polarity of Overcurrent */ -#define MXC_H1_OC_POL_BIT (1 << 6) -/* UH1 Disable Overcurrent Event */ -#define MXC_H1_OC_DIS_BIT (1 << 5) -/* OTG Power Pin Polarity */ -#define MXC_OTG_PHYCTRL_PWR_POL_BIT (1 << 3) - -/* USBH2CTRL */ -#define MXC_H2_UCTRL_H2_OC_POL_BIT (1 << 31) -#define MXC_H2_UCTRL_H2_OC_DIS_BIT (1 << 30) -#define MXC_H2_UCTRL_H2UIE_BIT (1 << 8) -#define MXC_H2_UCTRL_H2WIE_BIT (1 << 7) -#define MXC_H2_UCTRL_H2PM_BIT (1 << 4) -#define MXC_H2_UCTRL_H2_PWR_POL_BIT (1 << 4) - -/* USBH3CTRL */ -#define MXC_H3_UCTRL_H3_OC_POL_BIT (1 << 31) -#define MXC_H3_UCTRL_H3_OC_DIS_BIT (1 << 30) -#define MXC_H3_UCTRL_H3UIE_BIT (1 << 8) -#define MXC_H3_UCTRL_H3WIE_BIT (1 << 7) -#define MXC_H3_UCTRL_H3_PWR_POL_BIT (1 << 4) - -/* USB_CTRL_1 */ -#define MXC_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) - -int mxc_set_usbcontrol(int port, unsigned int flags) -{ - unsigned int v; - void __iomem *usb_base = (void __iomem *)OTG_BASE_ADDR; - void __iomem *usbother_base; - int ret = 0; - - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - switch (port) { - case 0: /* OTG port */ - if (flags & MXC_EHCI_INTERNAL_PHY) { - v = __raw_readl(usbother_base + - MXC_USB_PHY_CTR_FUNC_OFFSET); - if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW) - v |= MXC_OTG_PHYCTRL_OC_POL_BIT; - else - v &= ~MXC_OTG_PHYCTRL_OC_POL_BIT; - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - /* OC/USBPWR is used */ - v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT; - else - /* OC/USBPWR is not used */ - v |= MXC_OTG_PHYCTRL_OC_DIS_BIT; -#ifdef CONFIG_MX51 - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MXC_OTG_PHYCTRL_PWR_POL_BIT; - else - v &= ~MXC_OTG_PHYCTRL_PWR_POL_BIT; -#endif - __raw_writel(v, usbother_base + - MXC_USB_PHY_CTR_FUNC_OFFSET); - - v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); -#ifdef CONFIG_MX51 - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_OTG_UCTRL_OPM_BIT; - else - v |= MXC_OTG_UCTRL_OPM_BIT; -#endif -#ifdef CONFIG_MX53 - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MXC_OTG_UCTRL_O_PWR_POL_BIT; - else - v &= ~MXC_OTG_UCTRL_O_PWR_POL_BIT; -#endif - __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); - } - break; - case 1: /* Host 1 ULPI */ -#ifdef CONFIG_MX51 - /* The clock for the USBH1 ULPI port will come externally - from the PHY. */ - v = __raw_readl(usbother_base + MXC_USB_CTRL_1_OFFSET); - __raw_writel(v | MXC_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + - MXC_USB_CTRL_1_OFFSET); -#endif - - v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); -#ifdef CONFIG_MX51 - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H1_UCTRL_H1PM_BIT; /* H1 power mask unused */ - else - v |= MXC_H1_UCTRL_H1PM_BIT; /* H1 power mask used */ -#endif -#ifdef CONFIG_MX53 - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MXC_H1_UCTRL_H1_PWR_POL_BIT; - else - v &= ~MXC_H1_UCTRL_H1_PWR_POL_BIT; -#endif - __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); - - v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); - if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW) - v |= MXC_H1_OC_POL_BIT; - else - v &= ~MXC_H1_OC_POL_BIT; - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */ - else - v |= MXC_H1_OC_DIS_BIT; /* OC is not used */ - __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); - - break; - case 2: /* Host 2 ULPI */ - v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET); -#ifdef CONFIG_MX51 - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H2_UCTRL_H2PM_BIT; /* H2 power mask unused */ - else - v |= MXC_H2_UCTRL_H2PM_BIT; /* H2 power mask used */ -#endif -#ifdef CONFIG_MX53 - if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW) - v |= MXC_H2_UCTRL_H2_OC_POL_BIT; - else - v &= ~MXC_H2_UCTRL_H2_OC_POL_BIT; - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H2_UCTRL_H2_OC_DIS_BIT; /* OC is used */ - else - v |= MXC_H2_UCTRL_H2_OC_DIS_BIT; /* OC is not used */ - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MXC_H2_UCTRL_H2_PWR_POL_BIT; - else - v &= ~MXC_H2_UCTRL_H2_PWR_POL_BIT; -#endif - __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET); - break; -#ifdef CONFIG_MX53 - case 3: /* Host 3 ULPI */ - v = __raw_readl(usbother_base + MXC_USBH3CTRL_OFFSET); - if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW) - v |= MXC_H3_UCTRL_H3_OC_POL_BIT; - else - v &= ~MXC_H3_UCTRL_H3_OC_POL_BIT; - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H3_UCTRL_H3_OC_DIS_BIT; /* OC is used */ - else - v |= MXC_H3_UCTRL_H3_OC_DIS_BIT; /* OC is not used */ - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MXC_H3_UCTRL_H3_PWR_POL_BIT; - else - v &= ~MXC_H3_UCTRL_H3_PWR_POL_BIT; - __raw_writel(v, usbother_base + MXC_USBH3CTRL_OFFSET); - break; -#endif - } - - return ret; -} - -int __weak board_ehci_hcd_init(int port) -{ - return 0; -} - -void __weak board_ehci_hcd_postinit(struct usb_ehci *ehci, int port) -{ -} - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - struct usb_ehci *ehci; - - set_usboh3_clk(); - enable_usboh3_clk(true); - set_usb_phy_clk(); - enable_usb_phy1_clk(true); - enable_usb_phy2_clk(true); - mdelay(1); - - /* Do board specific initialization */ - board_ehci_hcd_init(CONFIG_MXC_USB_PORT); - - ehci = (struct usb_ehci *)(OTG_BASE_ADDR + - (0x200 * CONFIG_MXC_USB_PORT)); - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t)*hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - setbits_le32(&ehci->usbmode, CM_HOST); - - __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); - setbits_le32(&ehci->portsc, USB_EN); - - mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS); - mdelay(10); - - /* Do board specific post-initialization */ - board_ehci_hcd_postinit(ehci, CONFIG_MXC_USB_PORT); - - return 0; -} - -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-mx6.c b/qemu/roms/u-boot/drivers/usb/host/ehci-mx6.c deleted file mode 100644 index c0a557b2a..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-mx6.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> - * Copyright (C) 2010 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> -#include <errno.h> -#include <linux/compiler.h> -#include <usb/ehci-fsl.h> -#include <asm/io.h> -#include <asm/arch/imx-regs.h> -#include <asm/arch/clock.h> -#include <asm/imx-common/iomux-v3.h> - -#include "ehci.h" - -#define USB_OTGREGS_OFFSET 0x000 -#define USB_H1REGS_OFFSET 0x200 -#define USB_H2REGS_OFFSET 0x400 -#define USB_H3REGS_OFFSET 0x600 -#define USB_OTHERREGS_OFFSET 0x800 - -#define USB_H1_CTRL_OFFSET 0x04 - -#define USBPHY_CTRL 0x00000030 -#define USBPHY_CTRL_SET 0x00000034 -#define USBPHY_CTRL_CLR 0x00000038 -#define USBPHY_CTRL_TOG 0x0000003c - -#define USBPHY_PWD 0x00000000 -#define USBPHY_CTRL_SFTRST 0x80000000 -#define USBPHY_CTRL_CLKGATE 0x40000000 -#define USBPHY_CTRL_ENUTMILEVEL3 0x00008000 -#define USBPHY_CTRL_ENUTMILEVEL2 0x00004000 -#define USBPHY_CTRL_OTG_ID 0x08000000 - -#define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000 -#define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000 - -#define ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000 -#define ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000 -#define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000 -#define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040 - - -#define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ -#define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ - -/* USBCMD */ -#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ -#define UCMD_RESET (1 << 1) /* controller reset */ - -static const unsigned phy_bases[] = { - USB_PHY0_BASE_ADDR, - USB_PHY1_BASE_ADDR, -}; - -static void usb_internal_phy_clock_gate(int index, int on) -{ - void __iomem *phy_reg; - - if (index >= ARRAY_SIZE(phy_bases)) - return; - - phy_reg = (void __iomem *)phy_bases[index]; - phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET; - __raw_writel(USBPHY_CTRL_CLKGATE, phy_reg); -} - -static void usb_power_config(int index) -{ - struct anatop_regs __iomem *anatop = - (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; - void __iomem *chrg_detect; - void __iomem *pll_480_ctrl_clr; - void __iomem *pll_480_ctrl_set; - - switch (index) { - case 0: - chrg_detect = &anatop->usb1_chrg_detect; - pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr; - pll_480_ctrl_set = &anatop->usb1_pll_480_ctrl_set; - break; - case 1: - chrg_detect = &anatop->usb2_chrg_detect; - pll_480_ctrl_clr = &anatop->usb2_pll_480_ctrl_clr; - pll_480_ctrl_set = &anatop->usb2_pll_480_ctrl_set; - break; - default: - return; - } - /* - * Some phy and power's special controls - * 1. The external charger detector needs to be disabled - * or the signal at DP will be poor - * 2. The PLL's power and output to usb - * is totally controlled by IC, so the Software only needs - * to enable them at initializtion. - */ - __raw_writel(ANADIG_USB2_CHRG_DETECT_EN_B | - ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, - chrg_detect); - - __raw_writel(ANADIG_USB2_PLL_480_CTRL_BYPASS, - pll_480_ctrl_clr); - - __raw_writel(ANADIG_USB2_PLL_480_CTRL_ENABLE | - ANADIG_USB2_PLL_480_CTRL_POWER | - ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, - pll_480_ctrl_set); -} - -/* Return 0 : host node, <>0 : device mode */ -static int usb_phy_enable(int index, struct usb_ehci *ehci) -{ - void __iomem *phy_reg; - void __iomem *phy_ctrl; - void __iomem *usb_cmd; - u32 val; - - if (index >= ARRAY_SIZE(phy_bases)) - return 0; - - phy_reg = (void __iomem *)phy_bases[index]; - phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); - usb_cmd = (void __iomem *)&ehci->usbcmd; - - /* Stop then Reset */ - val = __raw_readl(usb_cmd); - val &= ~UCMD_RUN_STOP; - __raw_writel(val, usb_cmd); - while (__raw_readl(usb_cmd) & UCMD_RUN_STOP) - ; - - val = __raw_readl(usb_cmd); - val |= UCMD_RESET; - __raw_writel(val, usb_cmd); - while (__raw_readl(usb_cmd) & UCMD_RESET) - ; - - /* Reset USBPHY module */ - val = __raw_readl(phy_ctrl); - val |= USBPHY_CTRL_SFTRST; - __raw_writel(val, phy_ctrl); - udelay(10); - - /* Remove CLKGATE and SFTRST */ - val = __raw_readl(phy_ctrl); - val &= ~(USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); - __raw_writel(val, phy_ctrl); - udelay(10); - - /* Power up the PHY */ - __raw_writel(0, phy_reg + USBPHY_PWD); - /* enable FS/LS device */ - val = __raw_readl(phy_ctrl); - val |= (USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3); - __raw_writel(val, phy_ctrl); - - return val & USBPHY_CTRL_OTG_ID; -} - -/* Base address for this IP block is 0x02184800 */ -struct usbnc_regs { - u32 ctrl[4]; /* otg/host1-3 */ - u32 uh2_hsic_ctrl; - u32 uh3_hsic_ctrl; - u32 otg_phy_ctrl_0; - u32 uh1_phy_ctrl_0; -}; - -static void usb_oc_config(int index) -{ - struct usbnc_regs *usbnc = (struct usbnc_regs *)(USBOH3_USB_BASE_ADDR + - USB_OTHERREGS_OFFSET); - void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); - u32 val; - - val = __raw_readl(ctrl); -#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 - /* mx6qarm2 seems to required a different setting*/ - val &= ~UCTRL_OVER_CUR_POL; -#else - val |= UCTRL_OVER_CUR_POL; -#endif - __raw_writel(val, ctrl); - - val = __raw_readl(ctrl); - val |= UCTRL_OVER_CUR_DIS; - __raw_writel(val, ctrl); -} - -int __weak board_ehci_hcd_init(int port) -{ - return 0; -} - -int __weak board_ehci_power(int port, int on) -{ - return 0; -} - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - enum usb_init_type type; - struct usb_ehci *ehci = (struct usb_ehci *)(USBOH3_USB_BASE_ADDR + - (0x200 * index)); - - if (index > 3) - return -EINVAL; - enable_usboh3_clk(1); - mdelay(1); - - /* Do board specific initialization */ - board_ehci_hcd_init(index); - - usb_power_config(index); - usb_oc_config(index); - usb_internal_phy_clock_gate(index, 1); - type = usb_phy_enable(index, ehci) ? USB_INIT_DEVICE : USB_INIT_HOST; - - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t)*hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - if ((type == init) || (type == USB_INIT_DEVICE)) - board_ehci_power(index, (type == USB_INIT_DEVICE) ? 0 : 1); - if (type != init) - return -ENODEV; - if (type == USB_INIT_DEVICE) - return 0; - setbits_le32(&ehci->usbmode, CM_HOST); - __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); - setbits_le32(&ehci->portsc, USB_EN); - - mdelay(10); - - return 0; -} - -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-mxc.c b/qemu/roms/u-boot/drivers/usb/host/ehci-mxc.c deleted file mode 100644 index f09c75a9b..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-mxc.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - - -#include <common.h> -#include <usb.h> -#include <asm/io.h> -#include <asm/arch/imx-regs.h> -#include <usb/ehci-fsl.h> -#include <errno.h> - -#include "ehci.h" - -#define USBCTRL_OTGBASE_OFFSET 0x600 - -#define MX25_OTG_SIC_SHIFT 29 -#define MX25_OTG_SIC_MASK (0x3 << MX25_OTG_SIC_SHIFT) -#define MX25_OTG_PM_BIT (1 << 24) -#define MX25_OTG_PP_BIT (1 << 11) -#define MX25_OTG_OCPOL_BIT (1 << 3) - -#define MX25_H1_SIC_SHIFT 21 -#define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT) -#define MX25_H1_PP_BIT (1 << 18) -#define MX25_H1_PM_BIT (1 << 16) -#define MX25_H1_IPPUE_UP_BIT (1 << 7) -#define MX25_H1_IPPUE_DOWN_BIT (1 << 6) -#define MX25_H1_TLL_BIT (1 << 5) -#define MX25_H1_USBTE_BIT (1 << 4) -#define MX25_H1_OCPOL_BIT (1 << 2) - -#define MX31_OTG_SIC_SHIFT 29 -#define MX31_OTG_SIC_MASK (0x3 << MX31_OTG_SIC_SHIFT) -#define MX31_OTG_PM_BIT (1 << 24) - -#define MX31_H2_SIC_SHIFT 21 -#define MX31_H2_SIC_MASK (0x3 << MX31_H2_SIC_SHIFT) -#define MX31_H2_PM_BIT (1 << 16) -#define MX31_H2_DT_BIT (1 << 5) - -#define MX31_H1_SIC_SHIFT 13 -#define MX31_H1_SIC_MASK (0x3 << MX31_H1_SIC_SHIFT) -#define MX31_H1_PM_BIT (1 << 8) -#define MX31_H1_DT_BIT (1 << 4) - -#define MX35_OTG_SIC_SHIFT 29 -#define MX35_OTG_SIC_MASK (0x3 << MX35_OTG_SIC_SHIFT) -#define MX35_OTG_PM_BIT (1 << 24) -#define MX35_OTG_PP_BIT (1 << 11) -#define MX35_OTG_OCPOL_BIT (1 << 3) - -#define MX35_H1_SIC_SHIFT 21 -#define MX35_H1_SIC_MASK (0x3 << MX35_H1_SIC_SHIFT) -#define MX35_H1_PP_BIT (1 << 18) -#define MX35_H1_PM_BIT (1 << 16) -#define MX35_H1_IPPUE_UP_BIT (1 << 7) -#define MX35_H1_IPPUE_DOWN_BIT (1 << 6) -#define MX35_H1_TLL_BIT (1 << 5) -#define MX35_H1_USBTE_BIT (1 << 4) -#define MX35_H1_OCPOL_BIT (1 << 2) - -static int mxc_set_usbcontrol(int port, unsigned int flags) -{ - unsigned int v; - - v = readl(IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET); -#if defined(CONFIG_MX25) - switch (port) { - case 0: /* OTG port */ - v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT | MX25_OTG_PP_BIT | - MX25_OTG_OCPOL_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX25_OTG_PM_BIT; - - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MX25_OTG_PP_BIT; - - if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) - v |= MX25_OTG_OCPOL_BIT; - - break; - case 1: /* H1 port */ - v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_PP_BIT | - MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | - MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | - MX25_H1_IPPUE_UP_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX25_H1_PM_BIT; - - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MX25_H1_PP_BIT; - - if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) - v |= MX25_H1_OCPOL_BIT; - - if (!(flags & MXC_EHCI_TTL_ENABLED)) - v |= MX25_H1_TLL_BIT; - - if (flags & MXC_EHCI_INTERNAL_PHY) - v |= MX25_H1_USBTE_BIT; - - if (flags & MXC_EHCI_IPPUE_DOWN) - v |= MX25_H1_IPPUE_DOWN_BIT; - - if (flags & MXC_EHCI_IPPUE_UP) - v |= MX25_H1_IPPUE_UP_BIT; - - break; - default: - return -EINVAL; - } -#elif defined(CONFIG_MX31) - switch (port) { - case 0: /* OTG port */ - v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_OTG_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX31_OTG_PM_BIT; - - break; - case 1: /* H1 port */ - v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H1_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX31_H1_PM_BIT; - - if (!(flags & MXC_EHCI_TTL_ENABLED)) - v |= MX31_H1_DT_BIT; - - break; - case 2: /* H2 port */ - v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H2_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX31_H2_PM_BIT; - - if (!(flags & MXC_EHCI_TTL_ENABLED)) - v |= MX31_H2_DT_BIT; - - break; - default: - return -EINVAL; - } -#elif defined(CONFIG_MX35) - switch (port) { - case 0: /* OTG port */ - v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT | MX35_OTG_PP_BIT | - MX35_OTG_OCPOL_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_OTG_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX35_OTG_PM_BIT; - - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MX35_OTG_PP_BIT; - - if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) - v |= MX35_OTG_OCPOL_BIT; - - break; - case 1: /* H1 port */ - v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_PP_BIT | - MX35_H1_OCPOL_BIT | MX35_H1_TLL_BIT | - MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | - MX35_H1_IPPUE_UP_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_H1_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX35_H1_PM_BIT; - - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MX35_H1_PP_BIT; - - if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) - v |= MX35_H1_OCPOL_BIT; - - if (!(flags & MXC_EHCI_TTL_ENABLED)) - v |= MX35_H1_TLL_BIT; - - if (flags & MXC_EHCI_INTERNAL_PHY) - v |= MX35_H1_USBTE_BIT; - - if (flags & MXC_EHCI_IPPUE_DOWN) - v |= MX35_H1_IPPUE_DOWN_BIT; - - if (flags & MXC_EHCI_IPPUE_UP) - v |= MX35_H1_IPPUE_UP_BIT; - - break; - default: - return -EINVAL; - } -#else -#error MXC EHCI USB driver not supported on this platform -#endif - writel(v, IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET); - - return 0; -} - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - struct usb_ehci *ehci; -#ifdef CONFIG_MX31 - struct clock_control_regs *sc_regs = - (struct clock_control_regs *)CCM_BASE; - - __raw_readl(&sc_regs->ccmr); - __raw_writel(__raw_readl(&sc_regs->ccmr) | (1 << 9), &sc_regs->ccmr) ; -#endif - - udelay(80); - - ehci = (struct usb_ehci *)(IMX_USB_BASE + - IMX_USB_PORT_OFFSET * CONFIG_MXC_USB_PORT); - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - setbits_le32(&ehci->usbmode, CM_HOST); - __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); - mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS); -#ifdef CONFIG_MX35 - /* Workaround for ENGcm11601 */ - __raw_writel(0, &ehci->sbuscfg); -#endif - - udelay(10000); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-mxs.c b/qemu/roms/u-boot/drivers/usb/host/ehci-mxs.c deleted file mode 100644 index 4d652b32d..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-mxs.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Freescale i.MX28 USB Host driver - * - * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> - * on behalf of DENX Software Engineering GmbH - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/arch/imx-regs.h> -#include <errno.h> - -#include "ehci.h" - -/* This DIGCTL register ungates clock to USB */ -#define HW_DIGCTL_CTRL 0x8001c000 -#define HW_DIGCTL_CTRL_USB0_CLKGATE (1 << 2) -#define HW_DIGCTL_CTRL_USB1_CLKGATE (1 << 16) - -struct ehci_mxs_port { - uint32_t usb_regs; - struct mxs_usbphy_regs *phy_regs; - - struct mxs_register_32 *pll; - uint32_t pll_en_bits; - uint32_t pll_dis_bits; - uint32_t gate_bits; -}; - -static const struct ehci_mxs_port mxs_port[] = { -#ifdef CONFIG_EHCI_MXS_PORT0 - { - MXS_USBCTRL0_BASE, - (struct mxs_usbphy_regs *)MXS_USBPHY0_BASE, - (struct mxs_register_32 *)(MXS_CLKCTRL_BASE + - offsetof(struct mxs_clkctrl_regs, - hw_clkctrl_pll0ctrl0_reg)), - CLKCTRL_PLL0CTRL0_EN_USB_CLKS | CLKCTRL_PLL0CTRL0_POWER, - CLKCTRL_PLL0CTRL0_EN_USB_CLKS, - HW_DIGCTL_CTRL_USB0_CLKGATE, - }, -#endif -#ifdef CONFIG_EHCI_MXS_PORT1 - { - MXS_USBCTRL1_BASE, - (struct mxs_usbphy_regs *)MXS_USBPHY1_BASE, - (struct mxs_register_32 *)(MXS_CLKCTRL_BASE + - offsetof(struct mxs_clkctrl_regs, - hw_clkctrl_pll1ctrl0_reg)), - CLKCTRL_PLL1CTRL0_EN_USB_CLKS | CLKCTRL_PLL1CTRL0_POWER, - CLKCTRL_PLL1CTRL0_EN_USB_CLKS, - HW_DIGCTL_CTRL_USB1_CLKGATE, - }, -#endif -}; - -static int ehci_mxs_toggle_clock(const struct ehci_mxs_port *port, int enable) -{ - struct mxs_register_32 *digctl_ctrl = - (struct mxs_register_32 *)HW_DIGCTL_CTRL; - int pll_offset, dig_offset; - - if (enable) { - pll_offset = offsetof(struct mxs_register_32, reg_set); - dig_offset = offsetof(struct mxs_register_32, reg_clr); - writel(port->gate_bits, (u32)&digctl_ctrl->reg + dig_offset); - writel(port->pll_en_bits, (u32)port->pll + pll_offset); - } else { - pll_offset = offsetof(struct mxs_register_32, reg_clr); - dig_offset = offsetof(struct mxs_register_32, reg_set); - writel(port->pll_dis_bits, (u32)port->pll + pll_offset); - writel(port->gate_bits, (u32)&digctl_ctrl->reg + dig_offset); - } - - return 0; -} - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - - int ret; - uint32_t usb_base, cap_base; - const struct ehci_mxs_port *port; - - if ((index < 0) || (index >= ARRAY_SIZE(mxs_port))) { - printf("Invalid port index (index = %d)!\n", index); - return -EINVAL; - } - - port = &mxs_port[index]; - - /* Reset the PHY block */ - writel(USBPHY_CTRL_SFTRST, &port->phy_regs->hw_usbphy_ctrl_set); - udelay(10); - writel(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE, - &port->phy_regs->hw_usbphy_ctrl_clr); - - /* Enable USB clock */ - ret = ehci_mxs_toggle_clock(port, 1); - if (ret) - return ret; - - /* Start USB PHY */ - writel(0, &port->phy_regs->hw_usbphy_pwd); - - /* Enable UTMI+ Level 2 and Level 3 compatibility */ - writel(USBPHY_CTRL_ENUTMILEVEL3 | USBPHY_CTRL_ENUTMILEVEL2 | 1, - &port->phy_regs->hw_usbphy_ctrl_set); - - usb_base = port->usb_regs + 0x100; - *hccr = (struct ehci_hccr *)usb_base; - - cap_base = ehci_readl(&(*hccr)->cr_capbase); - *hcor = (struct ehci_hcor *)(usb_base + HC_LENGTH(cap_base)); - - return 0; -} - -int ehci_hcd_stop(int index) -{ - int ret; - uint32_t usb_base, cap_base, tmp; - struct ehci_hccr *hccr; - struct ehci_hcor *hcor; - const struct ehci_mxs_port *port; - - if ((index < 0) || (index >= ARRAY_SIZE(mxs_port))) { - printf("Invalid port index (index = %d)!\n", index); - return -EINVAL; - } - - port = &mxs_port[index]; - - /* Stop the USB port */ - usb_base = port->usb_regs + 0x100; - hccr = (struct ehci_hccr *)usb_base; - cap_base = ehci_readl(&hccr->cr_capbase); - hcor = (struct ehci_hcor *)(usb_base + HC_LENGTH(cap_base)); - - tmp = ehci_readl(&hcor->or_usbcmd); - tmp &= ~CMD_RUN; - ehci_writel(tmp, &hcor->or_usbcmd); - - /* Disable the PHY */ - tmp = USBPHY_PWD_RXPWDRX | USBPHY_PWD_RXPWDDIFF | - USBPHY_PWD_RXPWD1PT1 | USBPHY_PWD_RXPWDENV | - USBPHY_PWD_TXPWDV2I | USBPHY_PWD_TXPWDIBIAS | - USBPHY_PWD_TXPWDFS; - writel(tmp, &port->phy_regs->hw_usbphy_pwd); - - /* Disable USB clock */ - ret = ehci_mxs_toggle_clock(port, 0); - - return ret; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-omap.c b/qemu/roms/u-boot/drivers/usb/host/ehci-omap.c deleted file mode 100644 index 1b215c25f..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-omap.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * (C) Copyright 2011 Ilya Yanok, Emcraft Systems - * (C) Copyright 2004-2008 - * Texas Instruments, <www.ti.com> - * - * Derived from Beagle Board code by - * Sunil Kumar <sunilsaini05@gmail.com> - * Shashi Ranjan <shashiranjanmca05@gmail.com> - * - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> -#include <usb/ulpi.h> -#include <errno.h> -#include <asm/io.h> -#include <asm/gpio.h> -#include <asm/arch/ehci.h> -#include <asm/ehci-omap.h> - -#include "ehci.h" - -static struct omap_uhh *const uhh = (struct omap_uhh *)OMAP_UHH_BASE; -static struct omap_usbtll *const usbtll = (struct omap_usbtll *)OMAP_USBTLL_BASE; -static struct omap_ehci *const ehci = (struct omap_ehci *)OMAP_EHCI_BASE; - -static int omap_uhh_reset(void) -{ - int timeout = 0; - u32 rev; - - rev = readl(&uhh->rev); - - /* Soft RESET */ - writel(OMAP_UHH_SYSCONFIG_SOFTRESET, &uhh->sysc); - - switch (rev) { - case OMAP_USBHS_REV1: - /* Wait for soft RESET to complete */ - while (!(readl(&uhh->syss) & 0x1)) { - if (timeout > 100) { - printf("%s: RESET timeout\n", __func__); - return -1; - } - udelay(10); - timeout++; - } - - /* Set No-Idle, No-Standby */ - writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc); - break; - - default: /* Rev. 2 onwards */ - - udelay(2); /* Need to wait before accessing SYSCONFIG back */ - - /* Wait for soft RESET to complete */ - while ((readl(&uhh->sysc) & 0x1)) { - if (timeout > 100) { - printf("%s: RESET timeout\n", __func__); - return -1; - } - udelay(10); - timeout++; - } - - writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc); - break; - } - - return 0; -} - -static int omap_ehci_tll_reset(void) -{ - unsigned long init = get_timer(0); - - /* perform TLL soft reset, and wait until reset is complete */ - writel(OMAP_USBTLL_SYSCONFIG_SOFTRESET, &usbtll->sysc); - - /* Wait for TLL reset to complete */ - while (!(readl(&usbtll->syss) & OMAP_USBTLL_SYSSTATUS_RESETDONE)) - if (get_timer(init) > CONFIG_SYS_HZ) { - debug("OMAP EHCI error: timeout resetting TLL\n"); - return -EL3RST; - } - - return 0; -} - -static void omap_usbhs_hsic_init(int port) -{ - unsigned int reg; - - /* Enable channels now */ - reg = readl(&usbtll->channel_conf + port); - - setbits_le32(®, (OMAP_TLL_CHANNEL_CONF_CHANMODE_TRANSPARENT_UTMI - | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF - | OMAP_TLL_CHANNEL_CONF_DRVVBUS - | OMAP_TLL_CHANNEL_CONF_CHRGVBUS - | OMAP_TLL_CHANNEL_CONF_CHANEN)); - - writel(reg, &usbtll->channel_conf + port); -} - -#ifdef CONFIG_USB_ULPI -static void omap_ehci_soft_phy_reset(int port) -{ - struct ulpi_viewport ulpi_vp; - - ulpi_vp.viewport_addr = (u32)&ehci->insreg05_utmi_ulpi; - ulpi_vp.port_num = port; - - ulpi_reset(&ulpi_vp); -} -#else -static void omap_ehci_soft_phy_reset(int port) -{ - return; -} -#endif - -#if defined(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO) || \ - defined(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO) || \ - defined(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO) -/* controls PHY(s) reset signal(s) */ -static inline void omap_ehci_phy_reset(int on, int delay) -{ - /* - * Refer ISSUE1: - * Hold the PHY in RESET for enough time till - * PHY is settled and ready - */ - if (delay && !on) - udelay(delay); -#ifdef CONFIG_OMAP_EHCI_PHY1_RESET_GPIO - gpio_request(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, "USB PHY1 reset"); - gpio_direction_output(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, !on); -#endif -#ifdef CONFIG_OMAP_EHCI_PHY2_RESET_GPIO - gpio_request(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, "USB PHY2 reset"); - gpio_direction_output(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, !on); -#endif -#ifdef CONFIG_OMAP_EHCI_PHY3_RESET_GPIO - gpio_request(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, "USB PHY3 reset"); - gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, !on); -#endif - - /* Hold the PHY in RESET for enough time till DIR is high */ - /* Refer: ISSUE1 */ - if (delay && on) - udelay(delay); -} -#else -#define omap_ehci_phy_reset(on, delay) do {} while (0) -#endif - -/* Reset is needed otherwise the kernel-driver will throw an error. */ -int omap_ehci_hcd_stop(void) -{ - debug("Resetting OMAP EHCI\n"); - omap_ehci_phy_reset(1, 0); - - if (omap_uhh_reset() < 0) - return -1; - - if (omap_ehci_tll_reset() < 0) - return -1; - - return 0; -} - -/* - * Initialize the OMAP EHCI controller and PHY. - * Based on "drivers/usb/host/ehci-omap.c" from Linux 3.1 - * See there for additional Copyrights. - */ -int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - int ret; - unsigned int i, reg = 0, rev = 0; - - debug("Initializing OMAP EHCI\n"); - - ret = board_usb_init(index, USB_INIT_HOST); - if (ret < 0) - return ret; - - /* Put the PHY in RESET */ - omap_ehci_phy_reset(1, 10); - - ret = omap_uhh_reset(); - if (ret < 0) - return ret; - - ret = omap_ehci_tll_reset(); - if (ret) - return ret; - - writel(OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | - OMAP_USBTLL_SYSCONFIG_SIDLEMODE | - OMAP_USBTLL_SYSCONFIG_CACTIVITY, &usbtll->sysc); - - /* Put UHH in NoIdle/NoStandby mode */ - writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc); - - /* setup ULPI bypass and burst configurations */ - clrsetbits_le32(®, OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN, - (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | - OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN | - OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN)); - - rev = readl(&uhh->rev); - if (rev == OMAP_USBHS_REV1) { - if (is_ehci_phy_mode(usbhs_pdata->port_mode[0])) - clrbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS); - else - setbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS); - - if (is_ehci_phy_mode(usbhs_pdata->port_mode[1])) - clrbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS); - else - setbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS); - - if (is_ehci_phy_mode(usbhs_pdata->port_mode[2])) - clrbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS); - else - setbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS); - } else if (rev == OMAP_USBHS_REV2) { - - clrsetbits_le32(®, (OMAP_P1_MODE_CLEAR | OMAP_P2_MODE_CLEAR), - OMAP4_UHH_HOSTCONFIG_APP_START_CLK); - - /* Clear port mode fields for PHY mode */ - - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[0])) - setbits_le32(®, OMAP_P1_MODE_HSIC); - - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[1])) - setbits_le32(®, OMAP_P2_MODE_HSIC); - - } else if (rev == OMAP_USBHS_REV2_1) { - - clrsetbits_le32(®, - (OMAP_P1_MODE_CLEAR | - OMAP_P2_MODE_CLEAR | - OMAP_P3_MODE_CLEAR), - OMAP4_UHH_HOSTCONFIG_APP_START_CLK); - - /* Clear port mode fields for PHY mode */ - - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[0])) - setbits_le32(®, OMAP_P1_MODE_HSIC); - - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[1])) - setbits_le32(®, OMAP_P2_MODE_HSIC); - - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[2])) - setbits_le32(®, OMAP_P3_MODE_HSIC); - } - - debug("OMAP UHH_REVISION 0x%x\n", rev); - writel(reg, &uhh->hostconfig); - - for (i = 0; i < OMAP_HS_USB_PORTS; i++) - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[i])) - omap_usbhs_hsic_init(i); - - omap_ehci_phy_reset(0, 10); - - /* - * An undocumented "feature" in the OMAP3 EHCI controller, - * causes suspended ports to be taken out of suspend when - * the USBCMD.Run/Stop bit is cleared (for example when - * we do ehci_bus_suspend). - * This breaks suspend-resume if the root-hub is allowed - * to suspend. Writing 1 to this undocumented register bit - * disables this feature and restores normal behavior. - */ - writel(EHCI_INSNREG04_DISABLE_UNSUSPEND, &ehci->insreg04); - - for (i = 0; i < OMAP_HS_USB_PORTS; i++) - if (is_ehci_phy_mode(usbhs_pdata->port_mode[i])) - omap_ehci_soft_phy_reset(i); - - *hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE); - *hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10); - - debug("OMAP EHCI init done\n"); - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-pci.c b/qemu/roms/u-boot/drivers/usb/host/ehci-pci.c deleted file mode 100644 index 991b19998..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-pci.c +++ /dev/null @@ -1,138 +0,0 @@ -/*- - * Copyright (c) 2007-2008, Juniper Networks, Inc. - * All rights reserved. - * - * 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 version 2 of - * the License. - * - * 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., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <errno.h> -#include <pci.h> -#include <usb.h> - -#include "ehci.h" - -#ifdef CONFIG_PCI_EHCI_DEVICE -static struct pci_device_id ehci_pci_ids[] = { - /* Please add supported PCI EHCI controller ids here */ - {0x1033, 0x00E0}, /* NEC */ - {0x10B9, 0x5239}, /* ULI1575 PCI EHCI module ids */ - {0x12D8, 0x400F}, /* Pericom */ - {0, 0} -}; -#else -static pci_dev_t ehci_find_class(int index) -{ - int bus; - int devnum; - pci_dev_t bdf; - uint32_t class; - - for (bus = 0; bus <= pci_last_busno(); bus++) { - for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) { - pci_read_config_dword(PCI_BDF(bus, devnum, 0), - PCI_CLASS_REVISION, &class); - if (class >> 16 == 0xffff) - continue; - - for (bdf = PCI_BDF(bus, devnum, 0); - bdf <= PCI_BDF(bus, devnum, - PCI_MAX_PCI_FUNCTIONS - 1); - bdf += PCI_BDF(0, 0, 1)) { - pci_read_config_dword(bdf, PCI_CLASS_REVISION, - &class); - class >>= 8; - /* - * Here be dragons! In case we have multiple - * PCI EHCI controllers, this function will - * be called multiple times as well. This - * function will scan the PCI busses, always - * starting from bus 0, device 0, function 0, - * until it finds an USB controller. The USB - * stack gives us an 'index' of a controller - * that is currently being registered, which - * is a number, starting from 0 and growing - * in ascending order as controllers are added. - * To avoid probing the same controller in tne - * subsequent runs of this function, we will - * skip 'index - 1' detected controllers and - * report the index'th controller. - */ - if (class != PCI_CLASS_SERIAL_USB_EHCI) - continue; - if (index) { - index--; - continue; - } - /* Return index'th controller. */ - return bdf; - } - } - } - - return -ENODEV; -} -#endif - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **ret_hccr, struct ehci_hcor **ret_hcor) -{ - pci_dev_t pdev; - uint32_t cmd; - struct ehci_hccr *hccr; - struct ehci_hcor *hcor; - -#ifdef CONFIG_PCI_EHCI_DEVICE - pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE); -#else - pdev = ehci_find_class(index); -#endif - if (pdev < 0) { - printf("EHCI host controller not found\n"); - return -1; - } - - hccr = (struct ehci_hccr *)pci_map_bar(pdev, - PCI_BASE_ADDRESS_0, PCI_REGION_MEM); - hcor = (struct ehci_hcor *)((uint32_t) hccr + - HC_LENGTH(ehci_readl(&hccr->cr_capbase))); - - debug("EHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n", - (uint32_t)hccr, (uint32_t)hcor, - (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase))); - - *ret_hccr = hccr; - *ret_hcor = hcor; - - /* enable busmaster */ - pci_read_config_dword(pdev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - pci_write_config_dword(pdev, PCI_COMMAND, cmd); - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-ppc4xx.c b/qemu/roms/u-boot/drivers/usb/host/ehci-ppc4xx.c deleted file mode 100644 index 9aee3ff78..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-ppc4xx.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * (C) Copyright 2010, Chris Zhang <chris@seamicro.com> - * - * Author: Chris Zhang <chris@seamicro.com> - * This code is based on ehci freescale driver - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include <common.h> -#include <usb.h> - -#include "ehci.h" - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - *hccr = (struct ehci_hccr *)(CONFIG_SYS_PPC4XX_USB_ADDR); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-rmobile.c b/qemu/roms/u-boot/drivers/usb/host/ehci-rmobile.c deleted file mode 100644 index 049e4c4e6..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-rmobile.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * EHCI HCD (Host Controller Driver) for USB. - * - * Copyright (C) 2013,2014 Renesas Electronics Corporation - * Copyright (C) 2014 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/arch/ehci-rmobile.h> -#include "ehci.h" - -#if defined(CONFIG_R8A7740) -static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = { - 0xC6700000 -}; -#elif defined(CONFIG_R8A7790) -static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = { - 0xEE080000, /* USB0 (EHCI) */ - 0xEE0A0000, /* USB1 */ - 0xEE0C0000, /* USB2 */ - 0xEE000000 /* USB3 (USB3.0 Host)*/ -}; -#elif defined(CONFIG_R8A7791) -static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = { - 0xEE080000, /* USB0 (EHCI) */ - 0xEE0C0000, /* USB1 */ - 0xEE000000 /* USB3 (USB3.0 Host)*/ -}; -#else -#error rmobile EHCI USB driver not supported on this platform -#endif - -int ehci_hcd_stop(int index) -{ - int i; - u32 base; - struct ahbcom_pci_bridge *ahbcom_pci; - - base = usb_base_address[index]; - ahbcom_pci = (struct ahbcom_pci_bridge *)(base + AHBPCI_OFFSET); - writel(0, &ahbcom_pci->ahb_bus_ctr); - - /* reset ehci */ - setbits_le32(base + EHCI_USBCMD, CMD_RESET); - for (i = 100; i > 0; i--) { - if (!(readl(base + EHCI_USBCMD) & CMD_RESET)) - break; - udelay(100); - } - - if (!i) - printf("error : ehci(%d) reset failed.\n", index); - - if (index == (CONFIG_USB_MAX_CONTROLLER_COUNT - 1)) - setbits_le32(SMSTPCR7, SMSTPCR703); - - return 0; -} - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - u32 base; - u32 phys_base; - struct rmobile_ehci_reg *rehci; - struct ahbcom_pci_bridge *ahbcom_pci; - struct ahbconf_pci_bridge *ahbconf_pci; - struct ahb_pciconf *ahb_pciconf_ohci; - struct ahb_pciconf *ahb_pciconf_ehci; - uint32_t cap_base; - - base = usb_base_address[index]; - phys_base = base; - if (index == 0) - clrbits_le32(SMSTPCR7, SMSTPCR703); - - rehci = (struct rmobile_ehci_reg *)(base + EHCI_OFFSET); - ahbcom_pci = (struct ahbcom_pci_bridge *)(base + AHBPCI_OFFSET); - ahbconf_pci = - (struct ahbconf_pci_bridge *)(base + PCI_CONF_AHBPCI_OFFSET); - ahb_pciconf_ohci = (struct ahb_pciconf *)(base + PCI_CONF_OHCI_OFFSET); - ahb_pciconf_ehci = (struct ahb_pciconf *)(base + PCI_CONF_EHCI_OFFSET); - - /* Clock & Reset & Direct Power Down */ - clrsetbits_le32(&ahbcom_pci->usbctr, - (DIRPD | PCICLK_MASK | USBH_RST), USBCTR_WIN_SIZE_1GB); - clrbits_le32(&ahbcom_pci->usbctr, PLL_RST); - - /* AHB-PCI Bridge Communication Registers */ - writel(AHB_BUS_CTR_INIT, &ahbcom_pci->ahb_bus_ctr); - writel((CONFIG_SYS_SDRAM_BASE & 0xf0000000) | PCIAHB_WIN_PREFETCH, - &ahbcom_pci->pciahb_win1_ctr); - writel(0xf0000000 | PCIAHB_WIN_PREFETCH, - &ahbcom_pci->pciahb_win2_ctr); - writel(phys_base | PCIWIN2_PCICMD, &ahbcom_pci->ahbpci_win2_ctr); - - setbits_le32(&ahbcom_pci->pci_arbiter_ctr, - PCIBP_MODE | PCIREQ1 | PCIREQ0); - - /* PCI Configuration Registers for AHBPCI */ - writel(PCIWIN1_PCICMD | AHB_CFG_AHBPCI, - &ahbcom_pci->ahbpci_win1_ctr); - writel(phys_base + AHBPCI_OFFSET, &ahbconf_pci->basead); - writel(CONFIG_SYS_SDRAM_BASE & 0xf0000000, &ahbconf_pci->win1_basead); - writel(0xf0000000, &ahbconf_pci->win2_basead); - writel(SERREN | PERREN | MASTEREN | MEMEN, - &ahbconf_pci->cmnd_sts); - - /* PCI Configuration Registers for EHCI */ - writel(PCIWIN1_PCICMD | AHB_CFG_HOST, &ahbcom_pci->ahbpci_win1_ctr); - writel(phys_base + OHCI_OFFSET, &ahb_pciconf_ohci->basead); - writel(phys_base + EHCI_OFFSET, &ahb_pciconf_ehci->basead); - writel(SERREN | PERREN | MASTEREN | MEMEN, - &ahb_pciconf_ohci->cmnd_sts); - writel(SERREN | PERREN | MASTEREN | MEMEN, - &ahb_pciconf_ehci->cmnd_sts); - - /* Enable PCI interrupt */ - setbits_le32(&ahbcom_pci->pci_int_enable, - USBH_PMEEN | USBH_INTBEN | USBH_INTAEN); - - *hccr = (struct ehci_hccr *)((uint32_t)&rehci->hciversion); - cap_base = ehci_readl(&(*hccr)->cr_capbase); - *hcor = (struct ehci_hcor *)((uint32_t)*hccr + HC_LENGTH(cap_base)); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-spear.c b/qemu/roms/u-boot/drivers/usb/host/ehci-spear.c deleted file mode 100644 index 210ee9e88..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-spear.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * (C) Copyright 2010 - * Armando Visconti, ST Micoelectronics, <armando.visconti@st.com>. - * - * (C) Copyright 2009 - * Marvell Semiconductor <www.marvell.com> - * Written-by: Prafulla Wadaskar <prafulla@marvell.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include "ehci.h" -#include <asm/arch/hardware.h> - - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - *hccr = (struct ehci_hccr *)(CONFIG_SYS_UHC0_EHCI_BASE + 0x100); - *hcor = (struct ehci_hcor *)((uint32_t)*hccr - + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - debug("SPEAr-ehci: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-tegra.c b/qemu/roms/u-boot/drivers/usb/host/ehci-tegra.c deleted file mode 100644 index 38db18e2c..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-tegra.c +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * Copyright (c) 2009-2013 NVIDIA Corporation - * Copyright (c) 2013 Lucas Stach - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/errno.h> -#include <asm/io.h> -#include <asm-generic/gpio.h> -#include <asm/arch/clock.h> -#include <asm/arch-tegra/usb.h> -#include <asm/arch-tegra/clk_rst.h> -#include <usb.h> -#include <usb/ulpi.h> -#include <libfdt.h> -#include <fdtdec.h> - -#include "ehci.h" - -#define USB1_ADDR_MASK 0xFFFF0000 - -#define HOSTPC1_DEVLC 0x84 -#define HOSTPC1_PSPD(x) (((x) >> 25) & 0x3) - -#ifdef CONFIG_USB_ULPI - #ifndef CONFIG_USB_ULPI_VIEWPORT - #error "To use CONFIG_USB_ULPI on Tegra Boards you have to also \ - define CONFIG_USB_ULPI_VIEWPORT" - #endif -#endif - -enum { - USB_PORTS_MAX = 3, /* Maximum ports we allow */ -}; - -/* Parameters we need for USB */ -enum { - PARAM_DIVN, /* PLL FEEDBACK DIVIDer */ - PARAM_DIVM, /* PLL INPUT DIVIDER */ - PARAM_DIVP, /* POST DIVIDER (2^N) */ - PARAM_CPCON, /* BASE PLLC CHARGE Pump setup ctrl */ - PARAM_LFCON, /* BASE PLLC LOOP FILter setup ctrl */ - PARAM_ENABLE_DELAY_COUNT, /* PLL-U Enable Delay Count */ - PARAM_STABLE_COUNT, /* PLL-U STABLE count */ - PARAM_ACTIVE_DELAY_COUNT, /* PLL-U Active delay count */ - PARAM_XTAL_FREQ_COUNT, /* PLL-U XTAL frequency count */ - PARAM_DEBOUNCE_A_TIME, /* 10MS DELAY for BIAS_DEBOUNCE_A */ - PARAM_BIAS_TIME, /* 20US DELAY AFter bias cell op */ - - PARAM_COUNT -}; - -/* Possible port types (dual role mode) */ -enum dr_mode { - DR_MODE_NONE = 0, - DR_MODE_HOST, /* supports host operation */ - DR_MODE_DEVICE, /* supports device operation */ - DR_MODE_OTG, /* supports both */ -}; - -/* Information about a USB port */ -struct fdt_usb { - struct usb_ctlr *reg; /* address of registers in physical memory */ - unsigned utmi:1; /* 1 if port has external tranceiver, else 0 */ - unsigned ulpi:1; /* 1 if port has external ULPI transceiver */ - unsigned enabled:1; /* 1 to enable, 0 to disable */ - unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */ - unsigned initialized:1; /* has this port already been initialized? */ - enum dr_mode dr_mode; /* dual role mode */ - enum periph_id periph_id;/* peripheral id */ - struct fdt_gpio_state vbus_gpio; /* GPIO for vbus enable */ - struct fdt_gpio_state phy_reset_gpio; /* GPIO to reset ULPI phy */ -}; - -static struct fdt_usb port[USB_PORTS_MAX]; /* List of valid USB ports */ -static unsigned port_count; /* Number of available ports */ -/* Port that needs to clear CSC after Port Reset */ -static u32 port_addr_clear_csc; - -/* - * This table has USB timing parameters for each Oscillator frequency we - * support. There are four sets of values: - * - * 1. PLLU configuration information (reference clock is osc/clk_m and - * PLLU-FOs are fixed at 12MHz/60MHz/480MHz). - * - * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz - * ---------------------------------------------------------------------- - * DIVN 960 (0x3c0) 200 (0c8) 960 (3c0h) 960 (3c0) - * DIVM 13 (0d) 4 (04) 12 (0c) 26 (1a) - * Filter frequency (MHz) 1 4.8 6 2 - * CPCON 1100b 0011b 1100b 1100b - * LFCON0 0 0 0 0 - * - * 2. PLL CONFIGURATION & PARAMETERS for different clock generators: - * - * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz - * --------------------------------------------------------------------------- - * PLLU_ENABLE_DLY_COUNT 02 (0x02) 03 (03) 02 (02) 04 (04) - * PLLU_STABLE_COUNT 51 (33) 75 (4B) 47 (2F) 102 (66) - * PLL_ACTIVE_DLY_COUNT 05 (05) 06 (06) 04 (04) 09 (09) - * XTAL_FREQ_COUNT 127 (7F) 187 (BB) 118 (76) 254 (FE) - * - * 3. Debounce values IdDig, Avalid, Bvalid, VbusValid, VbusWakeUp, and - * SessEnd. Each of these signals have their own debouncer and for each of - * those one out of two debouncing times can be chosen (BIAS_DEBOUNCE_A or - * BIAS_DEBOUNCE_B). - * - * The values of DEBOUNCE_A and DEBOUNCE_B are calculated as follows: - * 0xffff -> No debouncing at all - * <n> ms = <n> *1000 / (1/19.2MHz) / 4 - * - * So to program a 1 ms debounce for BIAS_DEBOUNCE_A, we have: - * BIAS_DEBOUNCE_A[15:0] = 1000 * 19.2 / 4 = 4800 = 0x12c0 - * - * We need to use only DebounceA for BOOTROM. We don't need the DebounceB - * values, so we can keep those to default. - * - * 4. The 20 microsecond delay after bias cell operation. - */ -static const unsigned T20_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { - /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ - { 0x3C0, 0x0D, 0x00, 0xC, 0, 0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 }, - { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 }, - { 0x3C0, 0x0C, 0x00, 0xC, 0, 0x02, 0x2F, 0x04, 0x76, 0x7530, 5 }, - { 0x3C0, 0x1A, 0x00, 0xC, 0, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } -}; - -static const unsigned T30_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { - /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ - { 0x3C0, 0x0D, 0x00, 0xC, 1, 0x02, 0x33, 0x09, 0x7F, 0x7EF4, 5 }, - { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 7 }, - { 0x3C0, 0x0C, 0x00, 0xC, 1, 0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, - { 0x3C0, 0x1A, 0x00, 0xC, 1, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } -}; - -static const unsigned T114_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { - /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ - { 0x3C0, 0x0D, 0x00, 0xC, 2, 0x02, 0x33, 0x09, 0x7F, 0x7EF4, 6 }, - { 0x0C8, 0x04, 0x00, 0x3, 2, 0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 8 }, - { 0x3C0, 0x0C, 0x00, 0xC, 2, 0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, - { 0x3C0, 0x1A, 0x00, 0xC, 2, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 0xB } -}; - -/* UTMIP Idle Wait Delay */ -static const u8 utmip_idle_wait_delay = 17; - -/* UTMIP Elastic limit */ -static const u8 utmip_elastic_limit = 16; - -/* UTMIP High Speed Sync Start Delay */ -static const u8 utmip_hs_sync_start_delay = 9; - -struct fdt_usb_controller { - int compat; - /* flag to determine whether controller supports hostpc register */ - u32 has_hostpc:1; - const unsigned *pll_parameter; -}; - -static struct fdt_usb_controller fdt_usb_controllers[] = { - { - .compat = COMPAT_NVIDIA_TEGRA20_USB, - .has_hostpc = 0, - .pll_parameter = (const unsigned *)T20_usb_pll, - }, - { - .compat = COMPAT_NVIDIA_TEGRA30_USB, - .has_hostpc = 1, - .pll_parameter = (const unsigned *)T30_usb_pll, - }, - { - .compat = COMPAT_NVIDIA_TEGRA114_USB, - .has_hostpc = 1, - .pll_parameter = (const unsigned *)T114_usb_pll, - }, -}; - -static struct fdt_usb_controller *controller; - -/* - * A known hardware issue where Connect Status Change bit of PORTSC register - * of USB1 controller will be set after Port Reset. - * We have to clear it in order for later device enumeration to proceed. - * This ehci_powerup_fixup overrides the weak function ehci_powerup_fixup - * in "ehci-hcd.c". - */ -void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) -{ - mdelay(50); - /* This is to avoid PORT_ENABLE bit to be cleared in "ehci-hcd.c". */ - if (controller->has_hostpc) - *reg |= EHCI_PS_PE; - - if (((u32)status_reg & TEGRA_USB_ADDR_MASK) != port_addr_clear_csc) - return; - /* For EHCI_PS_CSC to be cleared in ehci_hcd.c */ - if (ehci_readl(status_reg) & EHCI_PS_CSC) - *reg |= EHCI_PS_CSC; -} - -/* - * This ehci_set_usbmode overrides the weak function ehci_set_usbmode - * in "ehci-hcd.c". - */ -void ehci_set_usbmode(int index) -{ - struct fdt_usb *config; - struct usb_ctlr *usbctlr; - uint32_t tmp; - - config = &port[index]; - usbctlr = config->reg; - - tmp = ehci_readl(&usbctlr->usb_mode); - tmp |= USBMODE_CM_HC; - ehci_writel(&usbctlr->usb_mode, tmp); -} - -/* - * This ehci_get_port_speed overrides the weak function ehci_get_port_speed - * in "ehci-hcd.c". - */ -int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) -{ - uint32_t tmp; - uint32_t *reg_ptr; - - if (controller->has_hostpc) { - reg_ptr = (uint32_t *)((u8 *)&hcor->or_usbcmd + HOSTPC1_DEVLC); - tmp = ehci_readl(reg_ptr); - return HOSTPC1_PSPD(tmp); - } else - return PORTSC_PSPD(reg); -} - -/* Put the port into host mode */ -static void set_host_mode(struct fdt_usb *config) -{ - /* - * If we are an OTG port, check if remote host is driving VBus and - * bail out in this case. - */ - if (config->dr_mode == DR_MODE_OTG && - (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS)) - return; - - /* - * If not driving, we set the GPIO to enable VBUS. We assume - * that the pinmux is set up correctly for this. - */ - if (fdt_gpio_isvalid(&config->vbus_gpio)) { - fdtdec_setup_gpio(&config->vbus_gpio); - gpio_direction_output(config->vbus_gpio.gpio, - (config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? - 0 : 1); - debug("set_host_mode: GPIO %d %s\n", config->vbus_gpio.gpio, - (config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? - "low" : "high"); - } -} - -void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr) -{ - /* Reset the USB controller with 2us delay */ - reset_periph(config->periph_id, 2); - - /* - * Set USB1_NO_LEGACY_MODE to 1, Registers are accessible under - * base address - */ - if (config->has_legacy_mode) - setbits_le32(&usbctlr->usb1_legacy_ctrl, USB1_NO_LEGACY_MODE); - - /* Put UTMIP1/3 in reset */ - setbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); - - /* Enable the UTMIP PHY */ - if (config->utmi) - setbits_le32(&usbctlr->susp_ctrl, UTMIP_PHY_ENB); -} - -static const unsigned *get_pll_timing(void) -{ - const unsigned *timing; - - timing = controller->pll_parameter + - clock_get_osc_freq() * PARAM_COUNT; - - return timing; -} - -/* set up the UTMI USB controller with the parameters provided */ -static int init_utmi_usb_controller(struct fdt_usb *config) -{ - u32 val; - int loop_count; - const unsigned *timing; - struct usb_ctlr *usbctlr = config->reg; - struct clk_rst_ctlr *clkrst; - struct usb_ctlr *usb1ctlr; - - clock_enable(config->periph_id); - - /* Reset the usb controller */ - usbf_reset_controller(config, usbctlr); - - /* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */ - clrbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); - - /* Follow the crystal clock disable by >100ns delay */ - udelay(1); - - /* - * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP - * mux must be switched to actually use a_sess_vld threshold. - */ - if (config->dr_mode == DR_MODE_OTG && - fdt_gpio_isvalid(&config->vbus_gpio)) - clrsetbits_le32(&usbctlr->usb1_legacy_ctrl, - VBUS_SENSE_CTL_MASK, - VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT); - - /* - * PLL Delay CONFIGURATION settings. The following parameters control - * the bring up of the plls. - */ - timing = get_pll_timing(); - - if (!controller->has_hostpc) { - val = readl(&usbctlr->utmip_misc_cfg1); - clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, - timing[PARAM_STABLE_COUNT] << - UTMIP_PLLU_STABLE_COUNT_SHIFT); - clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, - timing[PARAM_ACTIVE_DELAY_COUNT] << - UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); - writel(val, &usbctlr->utmip_misc_cfg1); - - /* Set PLL enable delay count and crystal frequency count */ - val = readl(&usbctlr->utmip_pll_cfg1); - clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, - timing[PARAM_ENABLE_DELAY_COUNT] << - UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); - clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, - timing[PARAM_XTAL_FREQ_COUNT] << - UTMIP_XTAL_FREQ_COUNT_SHIFT); - writel(val, &usbctlr->utmip_pll_cfg1); - } else { - clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - - val = readl(&clkrst->crc_utmip_pll_cfg2); - clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, - timing[PARAM_STABLE_COUNT] << - UTMIP_PLLU_STABLE_COUNT_SHIFT); - clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, - timing[PARAM_ACTIVE_DELAY_COUNT] << - UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); - writel(val, &clkrst->crc_utmip_pll_cfg2); - - /* Set PLL enable delay count and crystal frequency count */ - val = readl(&clkrst->crc_utmip_pll_cfg1); - clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, - timing[PARAM_ENABLE_DELAY_COUNT] << - UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); - clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, - timing[PARAM_XTAL_FREQ_COUNT] << - UTMIP_XTAL_FREQ_COUNT_SHIFT); - writel(val, &clkrst->crc_utmip_pll_cfg1); - - /* Disable Power Down state for PLL */ - clrbits_le32(&clkrst->crc_utmip_pll_cfg1, - PLLU_POWERDOWN | PLL_ENABLE_POWERDOWN | - PLL_ACTIVE_POWERDOWN); - - /* Recommended PHY settings for EYE diagram */ - val = readl(&usbctlr->utmip_xcvr_cfg0); - clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MASK, - 0x4 << UTMIP_XCVR_SETUP_SHIFT); - clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MSB_MASK, - 0x3 << UTMIP_XCVR_SETUP_MSB_SHIFT); - clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW_MSB_MASK, - 0x8 << UTMIP_XCVR_HSSLEW_MSB_SHIFT); - writel(val, &usbctlr->utmip_xcvr_cfg0); - clrsetbits_le32(&usbctlr->utmip_xcvr_cfg1, - UTMIP_XCVR_TERM_RANGE_ADJ_MASK, - 0x7 << UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT); - - /* Some registers can be controlled from USB1 only. */ - if (config->periph_id != PERIPH_ID_USBD) { - clock_enable(PERIPH_ID_USBD); - /* Disable Reset if in Reset state */ - reset_set_enable(PERIPH_ID_USBD, 0); - } - usb1ctlr = (struct usb_ctlr *) - ((u32)config->reg & USB1_ADDR_MASK); - val = readl(&usb1ctlr->utmip_bias_cfg0); - setbits_le32(&val, UTMIP_HSDISCON_LEVEL_MSB); - clrsetbits_le32(&val, UTMIP_HSDISCON_LEVEL_MASK, - 0x1 << UTMIP_HSDISCON_LEVEL_SHIFT); - clrsetbits_le32(&val, UTMIP_HSSQUELCH_LEVEL_MASK, - 0x2 << UTMIP_HSSQUELCH_LEVEL_SHIFT); - writel(val, &usb1ctlr->utmip_bias_cfg0); - - /* Miscellaneous setting mentioned in Programming Guide */ - clrbits_le32(&usbctlr->utmip_misc_cfg0, - UTMIP_SUSPEND_EXIT_ON_EDGE); - } - - /* Setting the tracking length time */ - clrsetbits_le32(&usbctlr->utmip_bias_cfg1, - UTMIP_BIAS_PDTRK_COUNT_MASK, - timing[PARAM_BIAS_TIME] << UTMIP_BIAS_PDTRK_COUNT_SHIFT); - - /* Program debounce time for VBUS to become valid */ - clrsetbits_le32(&usbctlr->utmip_debounce_cfg0, - UTMIP_DEBOUNCE_CFG0_MASK, - timing[PARAM_DEBOUNCE_A_TIME] << UTMIP_DEBOUNCE_CFG0_SHIFT); - - setbits_le32(&usbctlr->utmip_tx_cfg0, UTMIP_FS_PREAMBLE_J); - - /* Disable battery charge enabling bit */ - setbits_le32(&usbctlr->utmip_bat_chrg_cfg0, UTMIP_PD_CHRG); - - clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_XCVR_LSBIAS_SE); - setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL); - - /* - * Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT - * Setting these fields, together with default values of the - * other fields, results in programming the registers below as - * follows: - * UTMIP_HSRX_CFG0 = 0x9168c000 - * UTMIP_HSRX_CFG1 = 0x13 - */ - - /* Set PLL enable delay count and Crystal frequency count */ - val = readl(&usbctlr->utmip_hsrx_cfg0); - clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK, - utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT); - clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK, - utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT); - writel(val, &usbctlr->utmip_hsrx_cfg0); - - /* Configure the UTMIP_HS_SYNC_START_DLY */ - clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1, - UTMIP_HS_SYNC_START_DLY_MASK, - utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT); - - /* Preceed the crystal clock disable by >100ns delay. */ - udelay(1); - - /* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */ - setbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); - - if (controller->has_hostpc) { - if (config->periph_id == PERIPH_ID_USBD) - clrbits_le32(&clkrst->crc_utmip_pll_cfg2, - UTMIP_FORCE_PD_SAMP_A_POWERDOWN); - if (config->periph_id == PERIPH_ID_USB2) - clrbits_le32(&clkrst->crc_utmip_pll_cfg2, - UTMIP_FORCE_PD_SAMP_B_POWERDOWN); - if (config->periph_id == PERIPH_ID_USB3) - clrbits_le32(&clkrst->crc_utmip_pll_cfg2, - UTMIP_FORCE_PD_SAMP_C_POWERDOWN); - } - /* Finished the per-controller init. */ - - /* De-assert UTMIP_RESET to bring out of reset. */ - clrbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); - - /* Wait for the phy clock to become valid in 100 ms */ - for (loop_count = 100000; loop_count != 0; loop_count--) { - if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) - break; - udelay(1); - } - if (!loop_count) - return -1; - - /* Disable ICUSB FS/LS transceiver */ - clrbits_le32(&usbctlr->icusb_ctrl, IC_ENB1); - - /* Select UTMI parallel interface */ -#if defined(CONFIG_TEGRA20) - if (config->periph_id == PERIPH_ID_USBD) { - clrsetbits_le32(&usbctlr->port_sc1, PTS1_MASK, - PTS_UTMI << PTS1_SHIFT); - clrbits_le32(&usbctlr->port_sc1, STS1); - } else { - clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, - PTS_UTMI << PTS_SHIFT); - clrbits_le32(&usbctlr->port_sc1, STS); - } -#else - clrsetbits_le32(&usbctlr->hostpc1_devlc, PTS_MASK, - PTS_UTMI << PTS_SHIFT); - clrbits_le32(&usbctlr->hostpc1_devlc, STS); -#endif - - /* Deassert power down state */ - clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_FORCE_PD_POWERDOWN | - UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN); - clrbits_le32(&usbctlr->utmip_xcvr_cfg1, UTMIP_FORCE_PDDISC_POWERDOWN | - UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN); - - if (controller->has_hostpc) { - /* - * BIAS Pad Power Down is common among all 3 USB - * controllers and can be controlled from USB1 only. - */ - usb1ctlr = (struct usb_ctlr *) - ((u32)config->reg & USB1_ADDR_MASK); - clrbits_le32(&usb1ctlr->utmip_bias_cfg0, UTMIP_BIASPD); - udelay(25); - clrbits_le32(&usb1ctlr->utmip_bias_cfg1, - UTMIP_FORCE_PDTRK_POWERDOWN); - } - return 0; -} - -#ifdef CONFIG_USB_ULPI -/* if board file does not set a ULPI reference frequency we default to 24MHz */ -#ifndef CONFIG_ULPI_REF_CLK -#define CONFIG_ULPI_REF_CLK 24000000 -#endif - -/* set up the ULPI USB controller with the parameters provided */ -static int init_ulpi_usb_controller(struct fdt_usb *config) -{ - u32 val; - int loop_count; - struct ulpi_viewport ulpi_vp; - struct usb_ctlr *usbctlr = config->reg; - - /* set up ULPI reference clock on pllp_out4 */ - clock_enable(PERIPH_ID_DEV2_OUT); - clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK); - - /* reset ULPI phy */ - if (fdt_gpio_isvalid(&config->phy_reset_gpio)) { - fdtdec_setup_gpio(&config->phy_reset_gpio); - gpio_direction_output(config->phy_reset_gpio.gpio, 0); - mdelay(5); - gpio_set_value(config->phy_reset_gpio.gpio, 1); - } - - /* Reset the usb controller */ - clock_enable(config->periph_id); - usbf_reset_controller(config, usbctlr); - - /* enable pinmux bypass */ - setbits_le32(&usbctlr->ulpi_timing_ctrl_0, - ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP); - - /* Select ULPI parallel interface */ -#if defined(CONFIG_TEGRA20) - clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, - PTS_ULPI << PTS_SHIFT); -#else - clrsetbits_le32(&usbctlr->hostpc1_devlc, PTS_MASK, - PTS_ULPI << PTS_SHIFT); -#endif - - /* enable ULPI transceiver */ - setbits_le32(&usbctlr->susp_ctrl, ULPI_PHY_ENB); - - /* configure ULPI transceiver timings */ - val = 0; - writel(val, &usbctlr->ulpi_timing_ctrl_1); - - val |= ULPI_DATA_TRIMMER_SEL(4); - val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); - val |= ULPI_DIR_TRIMMER_SEL(4); - writel(val, &usbctlr->ulpi_timing_ctrl_1); - udelay(10); - - val |= ULPI_DATA_TRIMMER_LOAD; - val |= ULPI_STPDIRNXT_TRIMMER_LOAD; - val |= ULPI_DIR_TRIMMER_LOAD; - writel(val, &usbctlr->ulpi_timing_ctrl_1); - - /* set up phy for host operation with external vbus supply */ - ulpi_vp.port_num = 0; - ulpi_vp.viewport_addr = (u32)&usbctlr->ulpi_viewport; - - if (ulpi_init(&ulpi_vp)) { - printf("Tegra ULPI viewport init failed\n"); - return -1; - } - - ulpi_set_vbus(&ulpi_vp, 1, 1); - ulpi_set_vbus_indicator(&ulpi_vp, 1, 1, 0); - - /* enable wakeup events */ - setbits_le32(&usbctlr->port_sc1, WKCN | WKDS | WKOC); - - /* Enable and wait for the phy clock to become valid in 100 ms */ - setbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); - for (loop_count = 100000; loop_count != 0; loop_count--) { - if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) - break; - udelay(1); - } - if (!loop_count) - return -1; - clrbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); - - return 0; -} -#else -static int init_ulpi_usb_controller(struct fdt_usb *config) -{ - printf("No code to set up ULPI controller, please enable" - "CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT"); - return -1; -} -#endif - -static void config_clock(const u32 timing[]) -{ - clock_start_pll(CLOCK_ID_USB, - timing[PARAM_DIVM], timing[PARAM_DIVN], timing[PARAM_DIVP], - timing[PARAM_CPCON], timing[PARAM_LFCON]); -} - -static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) -{ - const char *phy, *mode; - - config->reg = (struct usb_ctlr *)fdtdec_get_addr(blob, node, "reg"); - mode = fdt_getprop(blob, node, "dr_mode", NULL); - if (mode) { - if (0 == strcmp(mode, "host")) - config->dr_mode = DR_MODE_HOST; - else if (0 == strcmp(mode, "peripheral")) - config->dr_mode = DR_MODE_DEVICE; - else if (0 == strcmp(mode, "otg")) - config->dr_mode = DR_MODE_OTG; - else { - debug("%s: Cannot decode dr_mode '%s'\n", __func__, - mode); - return -FDT_ERR_NOTFOUND; - } - } else { - config->dr_mode = DR_MODE_HOST; - } - - phy = fdt_getprop(blob, node, "phy_type", NULL); - config->utmi = phy && 0 == strcmp("utmi", phy); - config->ulpi = phy && 0 == strcmp("ulpi", phy); - config->enabled = fdtdec_get_is_enabled(blob, node); - config->has_legacy_mode = fdtdec_get_bool(blob, node, - "nvidia,has-legacy-mode"); - if (config->has_legacy_mode) - port_addr_clear_csc = (u32) config->reg; - config->periph_id = clock_decode_periph_id(blob, node); - if (config->periph_id == PERIPH_ID_NONE) { - debug("%s: Missing/invalid peripheral ID\n", __func__); - return -FDT_ERR_NOTFOUND; - } - fdtdec_decode_gpio(blob, node, "nvidia,vbus-gpio", &config->vbus_gpio); - fdtdec_decode_gpio(blob, node, "nvidia,phy-reset-gpio", - &config->phy_reset_gpio); - debug("enabled=%d, legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, " - "vbus=%d, phy_reset=%d, dr_mode=%d\n", - config->enabled, config->has_legacy_mode, config->utmi, - config->ulpi, config->periph_id, config->vbus_gpio.gpio, - config->phy_reset_gpio.gpio, config->dr_mode); - - return 0; -} - -/* - * process_usb_nodes() - Process a list of USB nodes, adding them to our list - * of USB ports. - * @blob: fdt blob - * @node_list: list of nodes to process (any <=0 are ignored) - * @count: number of nodes to process - * - * Return: 0 - ok, -1 - error - */ -static int process_usb_nodes(const void *blob, int node_list[], int count) -{ - struct fdt_usb config; - int node, i; - int clk_done = 0; - - port_count = 0; - for (i = 0; i < count; i++) { - if (port_count == USB_PORTS_MAX) { - printf("tegrausb: Cannot register more than %d ports\n", - USB_PORTS_MAX); - return -1; - } - - debug("USB %d: ", i); - node = node_list[i]; - if (!node) - continue; - if (fdt_decode_usb(blob, node, &config)) { - debug("Cannot decode USB node %s\n", - fdt_get_name(blob, node, NULL)); - return -1; - } - if (!clk_done) { - config_clock(get_pll_timing()); - clk_done = 1; - } - config.initialized = 0; - - /* add new USB port to the list of available ports */ - port[port_count++] = config; - } - - return 0; -} - -int usb_process_devicetree(const void *blob) -{ - int node_list[USB_PORTS_MAX]; - int count, err = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(fdt_usb_controllers); i++) { - controller = &fdt_usb_controllers[i]; - - count = fdtdec_find_aliases_for_id(blob, "usb", - controller->compat, node_list, USB_PORTS_MAX); - if (count) { - err = process_usb_nodes(blob, node_list, count); - if (err) - printf("%s: Error processing USB node!\n", - __func__); - return err; - } - } - if (i == ARRAY_SIZE(fdt_usb_controllers)) - controller = NULL; - - return err; -} - -/** - * Start up the given port number (ports are numbered from 0 on each board). - * This returns values for the appropriate hccr and hcor addresses to use for - * USB EHCI operations. - * - * @param index port number to start - * @param hccr returns start address of EHCI HCCR registers - * @param hcor returns start address of EHCI HCOR registers - * @return 0 if ok, -1 on error (generally invalid port number) - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - struct fdt_usb *config; - struct usb_ctlr *usbctlr; - - if (index >= port_count) - return -1; - - config = &port[index]; - - /* skip init, if the port is already initialized */ - if (config->initialized) - goto success; - - if (config->utmi && init_utmi_usb_controller(config)) { - printf("tegrausb: Cannot init port %d\n", index); - return -1; - } - - if (config->ulpi && init_ulpi_usb_controller(config)) { - printf("tegrausb: Cannot init port %d\n", index); - return -1; - } - - set_host_mode(config); - - config->initialized = 1; - -success: - usbctlr = config->reg; - *hccr = (struct ehci_hccr *)&usbctlr->cap_length; - *hcor = (struct ehci_hcor *)&usbctlr->usb_cmd; - - if (controller->has_hostpc) { - /* Set to Host mode after Controller Reset was done */ - clrsetbits_le32(&usbctlr->usb_mode, USBMODE_CM_HC, - USBMODE_CM_HC); - /* Select UTMI parallel interface after setting host mode */ - if (config->utmi) { - clrsetbits_le32((char *)&usbctlr->usb_cmd + - HOSTPC1_DEVLC, PTS_MASK, - PTS_UTMI << PTS_SHIFT); - clrbits_le32((char *)&usbctlr->usb_cmd + - HOSTPC1_DEVLC, STS); - } - } - return 0; -} - -/* - * Bring down the specified USB controller - */ -int ehci_hcd_stop(int index) -{ - struct usb_ctlr *usbctlr; - - usbctlr = port[index].reg; - - /* Stop controller */ - writel(0, &usbctlr->usb_cmd); - udelay(1000); - - /* Initiate controller reset */ - writel(2, &usbctlr->usb_cmd); - udelay(1000); - - port[index].initialized = 0; - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-vct.c b/qemu/roms/u-boot/drivers/usb/host/ehci-vct.c deleted file mode 100644 index 512ad3fb7..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-vct.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * (C) Copyright 2009 Stefan Roese <sr@denx.de>, DENX Software Engineering - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> - -#include "ehci.h" - -int vct_ehci_hcd_init(u32 *hccr, u32 *hcor); - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - int ret; - u32 vct_hccr; - u32 vct_hcor; - - /* - * Init VCT specific stuff - */ - ret = vct_ehci_hcd_init(&vct_hccr, &vct_hcor); - if (ret) - return ret; - - *hccr = (struct ehci_hccr *)vct_hccr; - *hcor = (struct ehci_hcor *)vct_hcor; - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci.h b/qemu/roms/u-boot/drivers/usb/host/ehci.h deleted file mode 100644 index 093eb4b83..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci.h +++ /dev/null @@ -1,257 +0,0 @@ -/*- - * Copyright (c) 2007-2008, Juniper Networks, Inc. - * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> - * All rights reserved. - * - * 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 version 2 of - * the License. - * - * 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., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef USB_EHCI_H -#define USB_EHCI_H - -#include <usb.h> - -#if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 -#endif - -/* - * Register Space. - */ -struct ehci_hccr { - uint32_t cr_capbase; -#define HC_LENGTH(p) (((p) >> 0) & 0x00ff) -#define HC_VERSION(p) (((p) >> 16) & 0xffff) - uint32_t cr_hcsparams; -#define HCS_PPC(p) ((p) & (1 << 4)) -#define HCS_INDICATOR(p) ((p) & (1 << 16)) /* Port indicators */ -#define HCS_N_PORTS(p) (((p) >> 0) & 0xf) - uint32_t cr_hccparams; - uint8_t cr_hcsp_portrt[8]; -} __attribute__ ((packed, aligned(4))); - -struct ehci_hcor { - uint32_t or_usbcmd; -#define CMD_PARK (1 << 11) /* enable "park" */ -#define CMD_PARK_CNT(c) (((c) >> 8) & 3) /* how many transfers to park */ -#define CMD_ASE (1 << 5) /* async schedule enable */ -#define CMD_LRESET (1 << 7) /* partial reset */ -#define CMD_IAAD (1 << 5) /* "doorbell" interrupt */ -#define CMD_PSE (1 << 4) /* periodic schedule enable */ -#define CMD_RESET (1 << 1) /* reset HC not bus */ -#define CMD_RUN (1 << 0) /* start/stop HC */ - uint32_t or_usbsts; -#define STS_ASS (1 << 15) -#define STS_PSS (1 << 14) -#define STS_HALT (1 << 12) - uint32_t or_usbintr; -#define INTR_UE (1 << 0) /* USB interrupt enable */ -#define INTR_UEE (1 << 1) /* USB error interrupt enable */ -#define INTR_PCE (1 << 2) /* Port change detect enable */ -#define INTR_SEE (1 << 4) /* system error enable */ -#define INTR_AAE (1 << 5) /* Interrupt on async adavance enable */ - uint32_t or_frindex; - uint32_t or_ctrldssegment; - uint32_t or_periodiclistbase; - uint32_t or_asynclistaddr; - uint32_t _reserved_0_; - uint32_t or_burstsize; - uint32_t or_txfilltuning; -#define TXFIFO_THRESH_MASK (0x3f << 16) -#define TXFIFO_THRESH(p) ((p & 0x3f) << 16) - uint32_t _reserved_1_[6]; - uint32_t or_configflag; -#define FLAG_CF (1 << 0) /* true: we'll support "high speed" */ - uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS]; -#define PORTSC_PSPD(x) (((x) >> 26) & 0x3) -#define PORTSC_PSPD_FS 0x0 -#define PORTSC_PSPD_LS 0x1 -#define PORTSC_PSPD_HS 0x2 - uint32_t or_systune; -} __attribute__ ((packed, aligned(4))); - -#define USBMODE 0x68 /* USB Device mode */ -#define USBMODE_SDIS (1 << 3) /* Stream disable */ -#define USBMODE_BE (1 << 2) /* BE/LE endiannes select */ -#define USBMODE_CM_HC (3 << 0) /* host controller mode */ -#define USBMODE_CM_IDLE (0 << 0) /* idle state */ - -/* Interface descriptor */ -struct usb_linux_interface_descriptor { - unsigned char bLength; - unsigned char bDescriptorType; - unsigned char bInterfaceNumber; - unsigned char bAlternateSetting; - unsigned char bNumEndpoints; - unsigned char bInterfaceClass; - unsigned char bInterfaceSubClass; - unsigned char bInterfaceProtocol; - unsigned char iInterface; -} __attribute__ ((packed)); - -/* Configuration descriptor information.. */ -struct usb_linux_config_descriptor { - unsigned char bLength; - unsigned char bDescriptorType; - unsigned short wTotalLength; - unsigned char bNumInterfaces; - unsigned char bConfigurationValue; - unsigned char iConfiguration; - unsigned char bmAttributes; - unsigned char MaxPower; -} __attribute__ ((packed)); - -#if defined CONFIG_EHCI_DESC_BIG_ENDIAN -#define ehci_readl(x) (*((volatile u32 *)(x))) -#define ehci_writel(a, b) (*((volatile u32 *)(a)) = ((volatile u32)b)) -#else -#define ehci_readl(x) cpu_to_le32((*((volatile u32 *)(x)))) -#define ehci_writel(a, b) (*((volatile u32 *)(a)) = \ - cpu_to_le32(((volatile u32)b))) -#endif - -#if defined CONFIG_EHCI_MMIO_BIG_ENDIAN -#define hc32_to_cpu(x) be32_to_cpu((x)) -#define cpu_to_hc32(x) cpu_to_be32((x)) -#else -#define hc32_to_cpu(x) le32_to_cpu((x)) -#define cpu_to_hc32(x) cpu_to_le32((x)) -#endif - -#define EHCI_PS_WKOC_E (1 << 22) /* RW wake on over current */ -#define EHCI_PS_WKDSCNNT_E (1 << 21) /* RW wake on disconnect */ -#define EHCI_PS_WKCNNT_E (1 << 20) /* RW wake on connect */ -#define EHCI_PS_PO (1 << 13) /* RW port owner */ -#define EHCI_PS_PP (1 << 12) /* RW,RO port power */ -#define EHCI_PS_LS (3 << 10) /* RO line status */ -#define EHCI_PS_PR (1 << 8) /* RW port reset */ -#define EHCI_PS_SUSP (1 << 7) /* RW suspend */ -#define EHCI_PS_FPR (1 << 6) /* RW force port resume */ -#define EHCI_PS_OCC (1 << 5) /* RWC over current change */ -#define EHCI_PS_OCA (1 << 4) /* RO over current active */ -#define EHCI_PS_PEC (1 << 3) /* RWC port enable change */ -#define EHCI_PS_PE (1 << 2) /* RW port enable */ -#define EHCI_PS_CSC (1 << 1) /* RWC connect status change */ -#define EHCI_PS_CS (1 << 0) /* RO connect status */ -#define EHCI_PS_CLEAR (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC) - -#define EHCI_PS_IS_LOWSPEED(x) (((x) & EHCI_PS_LS) == (1 << 10)) - -/* - * Schedule Interface Space. - * - * IMPORTANT: Software must ensure that no interface data structure - * reachable by the EHCI host controller spans a 4K page boundary! - * - * Periodic transfers (i.e. isochronous and interrupt transfers) are - * not supported. - */ - -/* Queue Element Transfer Descriptor (qTD). */ -struct qTD { - /* this part defined by EHCI spec */ - uint32_t qt_next; /* see EHCI 3.5.1 */ -#define QT_NEXT_TERMINATE 1 - uint32_t qt_altnext; /* see EHCI 3.5.2 */ - uint32_t qt_token; /* see EHCI 3.5.3 */ -#define QT_TOKEN_DT(x) (((x) & 0x1) << 31) /* Data Toggle */ -#define QT_TOKEN_GET_DT(x) (((x) >> 31) & 0x1) -#define QT_TOKEN_TOTALBYTES(x) (((x) & 0x7fff) << 16) /* Total Bytes to Transfer */ -#define QT_TOKEN_GET_TOTALBYTES(x) (((x) >> 16) & 0x7fff) -#define QT_TOKEN_IOC(x) (((x) & 0x1) << 15) /* Interrupt On Complete */ -#define QT_TOKEN_CPAGE(x) (((x) & 0x7) << 12) /* Current Page */ -#define QT_TOKEN_CERR(x) (((x) & 0x3) << 10) /* Error Counter */ -#define QT_TOKEN_PID(x) (((x) & 0x3) << 8) /* PID Code */ -#define QT_TOKEN_PID_OUT 0x0 -#define QT_TOKEN_PID_IN 0x1 -#define QT_TOKEN_PID_SETUP 0x2 -#define QT_TOKEN_STATUS(x) (((x) & 0xff) << 0) /* Status */ -#define QT_TOKEN_GET_STATUS(x) (((x) >> 0) & 0xff) -#define QT_TOKEN_STATUS_ACTIVE 0x80 -#define QT_TOKEN_STATUS_HALTED 0x40 -#define QT_TOKEN_STATUS_DATBUFERR 0x20 -#define QT_TOKEN_STATUS_BABBLEDET 0x10 -#define QT_TOKEN_STATUS_XACTERR 0x08 -#define QT_TOKEN_STATUS_MISSEDUFRAME 0x04 -#define QT_TOKEN_STATUS_SPLITXSTATE 0x02 -#define QT_TOKEN_STATUS_PERR 0x01 -#define QT_BUFFER_CNT 5 - uint32_t qt_buffer[QT_BUFFER_CNT]; /* see EHCI 3.5.4 */ - uint32_t qt_buffer_hi[QT_BUFFER_CNT]; /* Appendix B */ - /* pad struct for 32 byte alignment */ - uint32_t unused[3]; -}; - -#define EHCI_PAGE_SIZE 4096 - -/* Queue Head (QH). */ -struct QH { - uint32_t qh_link; -#define QH_LINK_TERMINATE 1 -#define QH_LINK_TYPE_ITD 0 -#define QH_LINK_TYPE_QH 2 -#define QH_LINK_TYPE_SITD 4 -#define QH_LINK_TYPE_FSTN 6 - uint32_t qh_endpt1; -#define QH_ENDPT1_RL(x) (((x) & 0xf) << 28) /* NAK Count Reload */ -#define QH_ENDPT1_C(x) (((x) & 0x1) << 27) /* Control Endpoint Flag */ -#define QH_ENDPT1_MAXPKTLEN(x) (((x) & 0x7ff) << 16) /* Maximum Packet Length */ -#define QH_ENDPT1_H(x) (((x) & 0x1) << 15) /* Head of Reclamation List Flag */ -#define QH_ENDPT1_DTC(x) (((x) & 0x1) << 14) /* Data Toggle Control */ -#define QH_ENDPT1_DTC_IGNORE_QTD_TD 0x0 -#define QH_ENDPT1_DTC_DT_FROM_QTD 0x1 -#define QH_ENDPT1_EPS(x) (((x) & 0x3) << 12) /* Endpoint Speed */ -#define QH_ENDPT1_EPS_FS 0x0 -#define QH_ENDPT1_EPS_LS 0x1 -#define QH_ENDPT1_EPS_HS 0x2 -#define QH_ENDPT1_ENDPT(x) (((x) & 0xf) << 8) /* Endpoint Number */ -#define QH_ENDPT1_I(x) (((x) & 0x1) << 7) /* Inactivate on Next Transaction */ -#define QH_ENDPT1_DEVADDR(x) (((x) & 0x7f) << 0) /* Device Address */ - uint32_t qh_endpt2; -#define QH_ENDPT2_MULT(x) (((x) & 0x3) << 30) /* High-Bandwidth Pipe Multiplier */ -#define QH_ENDPT2_PORTNUM(x) (((x) & 0x7f) << 23) /* Port Number */ -#define QH_ENDPT2_HUBADDR(x) (((x) & 0x7f) << 16) /* Hub Address */ -#define QH_ENDPT2_UFCMASK(x) (((x) & 0xff) << 8) /* Split Completion Mask */ -#define QH_ENDPT2_UFSMASK(x) (((x) & 0xff) << 0) /* Interrupt Schedule Mask */ - uint32_t qh_curtd; - struct qTD qh_overlay; - /* - * Add dummy fill value to make the size of this struct - * aligned to 32 bytes - */ - union { - uint32_t fill[4]; - void *buffer; - }; -}; - -struct ehci_ctrl { - struct ehci_hccr *hccr; /* R/O registers, not need for volatile */ - struct ehci_hcor *hcor; - int rootdev; - uint16_t portreset; - struct QH qh_list __aligned(USB_DMA_MINALIGN); - struct QH periodic_queue __aligned(USB_DMA_MINALIGN); - uint32_t *periodic_list; - int ntds; -}; - -/* Low level init functions */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor); -int ehci_hcd_stop(int index); - -#endif /* USB_EHCI_H */ diff --git a/qemu/roms/u-boot/drivers/usb/host/isp116x-hcd.c b/qemu/roms/u-boot/drivers/usb/host/isp116x-hcd.c deleted file mode 100644 index 46e4cee1d..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/isp116x-hcd.c +++ /dev/null @@ -1,1329 +0,0 @@ -/* - * ISP116x HCD (Host Controller Driver) for u-boot. - * - * Copyright (C) 2006-2007 Rodolfo Giometti <giometti@linux.it> - * Copyright (C) 2006-2007 Eurotech S.p.A. <info@eurotech.it> - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Derived in part from the SL811 HCD driver "u-boot/drivers/usb/sl811_usb.c" - * (original copyright message follows): - * - * (C) Copyright 2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * This code is based on linux driver for sl811hs chip, source at - * drivers/usb/host/sl811.c: - * - * SL811 Host Controller Interface driver for USB. - * - * Copyright (c) 2003/06, Courage Co., Ltd. - * - * Based on: - * 1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap, - * Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, - * Adam Richter, Gregory P. Smith; - * 2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com> - * 3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn> - * - * [[GNU/GPL disclaimer]] - * - * and in part from AU1x00 OHCI HCD driver "u-boot/arch/mips/cpu/au1x00_usb_ohci.c" - * (original copyright message follows): - * - * URB OHCI HCD (Host Controller Driver) for USB on the AU1x00. - * - * (C) Copyright 2003 - * Gary Jennejohn, DENX Software Engineering <garyj@denx.de> - * - * [[GNU/GPL disclaimer]] - * - * Note: Part of this code has been derived from linux - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include <malloc.h> -#include <linux/list.h> - -/* - * ISP116x chips require certain delays between accesses to its - * registers. The following timing options exist. - * - * 1. Configure your memory controller (the best) - * 2. Use ndelay (easiest, poorest). For that, enable the following macro. - * - * Value is in microseconds. - */ -#ifdef ISP116X_HCD_USE_UDELAY -#define UDELAY 1 -#endif - -/* - * On some (slowly?) machines an extra delay after data packing into - * controller's FIFOs is required, * otherwise you may get the following - * error: - * - * uboot> usb start - * (Re)start USB... - * USB: scanning bus for devices... isp116x: isp116x_submit_job: CTL:TIMEOUT - * isp116x: isp116x_submit_job: ****** FIFO not ready! ****** - * - * USB device not responding, giving up (status=4) - * isp116x: isp116x_submit_job: ****** FIFO not empty! ****** - * isp116x: isp116x_submit_job: ****** FIFO not empty! ****** - * isp116x: isp116x_submit_job: ****** FIFO not empty! ****** - * 3 USB Device(s) found - * scanning bus for storage devices... 0 Storage Device(s) found - * - * Value is in milliseconds. - */ -#ifdef ISP116X_HCD_USE_EXTRA_DELAY -#define EXTRA_DELAY 2 -#endif - -/* - * Enable the following defines if you wish enable debugging messages. - */ -#undef DEBUG /* enable debugging messages */ -#undef TRACE /* enable tracing code */ -#undef VERBOSE /* verbose debugging messages */ - -#include "isp116x.h" - -#define DRIVER_VERSION "08 Jan 2007" -static const char hcd_name[] = "isp116x-hcd"; - -struct isp116x isp116x_dev; -struct isp116x_platform_data isp116x_board; -static int got_rhsc; /* root hub status change */ -struct usb_device *devgone; /* device which was disconnected */ -static int rh_devnum; /* address of Root Hub endpoint */ - -/* ------------------------------------------------------------------------- */ - -#define ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL)) -#define min_t(type,x,y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; }) - -/* ------------------------------------------------------------------------- */ - -static int isp116x_reset(struct isp116x *isp116x); - -/* --- Debugging functions ------------------------------------------------- */ - -#define isp116x_show_reg(d, r) { \ - if ((r) < 0x20) { \ - DBG("%-12s[%02x]: %08x", #r, \ - r, isp116x_read_reg32(d, r)); \ - } else { \ - DBG("%-12s[%02x]: %04x", #r, \ - r, isp116x_read_reg16(d, r)); \ - } \ -} - -#define isp116x_show_regs(d) { \ - isp116x_show_reg(d, HCREVISION); \ - isp116x_show_reg(d, HCCONTROL); \ - isp116x_show_reg(d, HCCMDSTAT); \ - isp116x_show_reg(d, HCINTSTAT); \ - isp116x_show_reg(d, HCINTENB); \ - isp116x_show_reg(d, HCFMINTVL); \ - isp116x_show_reg(d, HCFMREM); \ - isp116x_show_reg(d, HCFMNUM); \ - isp116x_show_reg(d, HCLSTHRESH); \ - isp116x_show_reg(d, HCRHDESCA); \ - isp116x_show_reg(d, HCRHDESCB); \ - isp116x_show_reg(d, HCRHSTATUS); \ - isp116x_show_reg(d, HCRHPORT1); \ - isp116x_show_reg(d, HCRHPORT2); \ - isp116x_show_reg(d, HCHWCFG); \ - isp116x_show_reg(d, HCDMACFG); \ - isp116x_show_reg(d, HCXFERCTR); \ - isp116x_show_reg(d, HCuPINT); \ - isp116x_show_reg(d, HCuPINTENB); \ - isp116x_show_reg(d, HCCHIPID); \ - isp116x_show_reg(d, HCSCRATCH); \ - isp116x_show_reg(d, HCITLBUFLEN); \ - isp116x_show_reg(d, HCATLBUFLEN); \ - isp116x_show_reg(d, HCBUFSTAT); \ - isp116x_show_reg(d, HCRDITL0LEN); \ - isp116x_show_reg(d, HCRDITL1LEN); \ -} - -#if defined(TRACE) - -static int isp116x_get_current_frame_number(struct usb_device *usb_dev) -{ - struct isp116x *isp116x = &isp116x_dev; - - return isp116x_read_reg32(isp116x, HCFMNUM); -} - -static void dump_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, char *str) -{ -#if defined(VERBOSE) - int i; -#endif - - DBG("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d stat:%#lx", - str, - isp116x_get_current_frame_number(dev), - usb_pipedevice(pipe), - usb_pipeendpoint(pipe), - usb_pipeout(pipe) ? 'O' : 'I', - usb_pipetype(pipe) < 2 ? - (usb_pipeint(pipe) ? - "INTR" : "ISOC") : - (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), len, dev->status); -#if defined(VERBOSE) - if (len > 0 && buffer) { - printf(__FILE__ ": data(%d):", len); - for (i = 0; i < 16 && i < len; i++) - printf(" %02x", ((__u8 *) buffer)[i]); - printf("%s\n", i < len ? "..." : ""); - } -#endif -} - -#define PTD_DIR_STR(ptd) ({char __c; \ - switch(PTD_GET_DIR(ptd)){ \ - case 0: __c = 's'; break; \ - case 1: __c = 'o'; break; \ - default: __c = 'i'; break; \ - }; __c;}) - -/* - Dump PTD info. The code documents the format - perfectly, right :) -*/ -static inline void dump_ptd(struct ptd *ptd) -{ -#if defined(VERBOSE) - int k; -#endif - - DBG("PTD(ext) : cc:%x %d%c%d %d,%d,%d t:%x %x%x%x", - PTD_GET_CC(ptd), - PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd), - PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), - PTD_GET_TOGGLE(ptd), - PTD_GET_ACTIVE(ptd), PTD_GET_SPD(ptd), PTD_GET_LAST(ptd)); -#if defined(VERBOSE) - printf("isp116x: %s: PTD(byte): ", __FUNCTION__); - for (k = 0; k < sizeof(struct ptd); ++k) - printf("%02x ", ((u8 *) ptd)[k]); - printf("\n"); -#endif -} - -static inline void dump_ptd_data(struct ptd *ptd, u8 * buf, int type) -{ -#if defined(VERBOSE) - int k; - - if (type == 0 /* 0ut data */ ) { - printf("isp116x: %s: out data: ", __FUNCTION__); - for (k = 0; k < PTD_GET_LEN(ptd); ++k) - printf("%02x ", ((u8 *) buf)[k]); - printf("\n"); - } - if (type == 1 /* 1n data */ ) { - printf("isp116x: %s: in data: ", __FUNCTION__); - for (k = 0; k < PTD_GET_COUNT(ptd); ++k) - printf("%02x ", ((u8 *) buf)[k]); - printf("\n"); - } - - if (PTD_GET_LAST(ptd)) - DBG("--- last PTD ---"); -#endif -} - -#else - -#define dump_msg(dev, pipe, buffer, len, str) do { } while (0) -#define dump_pkt(dev, pipe, buffer, len, setup, str, small) do {} while (0) - -#define dump_ptd(ptd) do {} while (0) -#define dump_ptd_data(ptd, buf, type) do {} while (0) - -#endif - -/* --- Virtual Root Hub ---------------------------------------------------- */ - -#include <usbroothubdes.h> - -/* - * Hub class-specific descriptor is constructed dynamically - */ - -/* --- Virtual root hub management functions ------------------------------- */ - -static int rh_check_port_status(struct isp116x *isp116x) -{ - u32 temp, ndp, i; - int res; - - res = -1; - temp = isp116x_read_reg32(isp116x, HCRHSTATUS); - ndp = (temp & RH_A_NDP); - for (i = 0; i < ndp; i++) { - temp = isp116x_read_reg32(isp116x, HCRHPORT1 + i); - /* check for a device disconnect */ - if (((temp & (RH_PS_PESC | RH_PS_CSC)) == - (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) { - res = i; - break; - } - } - return res; -} - -/* --- HC management functions --------------------------------------------- */ - -/* Write len bytes to fifo, pad till 32-bit boundary - */ -static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len) -{ - u8 *dp = (u8 *) buf; - u16 *dp2 = (u16 *) buf; - u16 w; - int quot = len % 4; - - if ((unsigned long)dp2 & 1) { - /* not aligned */ - for (; len > 1; len -= 2) { - w = *dp++; - w |= *dp++ << 8; - isp116x_raw_write_data16(isp116x, w); - } - if (len) - isp116x_write_data16(isp116x, (u16) * dp); - } else { - /* aligned */ - for (; len > 1; len -= 2) - isp116x_raw_write_data16(isp116x, *dp2++); - if (len) - isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2)); - } - if (quot == 1 || quot == 2) - isp116x_raw_write_data16(isp116x, 0); -} - -/* Read len bytes from fifo and then read till 32-bit boundary - */ -static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len) -{ - u8 *dp = (u8 *) buf; - u16 *dp2 = (u16 *) buf; - u16 w; - int quot = len % 4; - - if ((unsigned long)dp2 & 1) { - /* not aligned */ - for (; len > 1; len -= 2) { - w = isp116x_raw_read_data16(isp116x); - *dp++ = w & 0xff; - *dp++ = (w >> 8) & 0xff; - } - if (len) - *dp = 0xff & isp116x_read_data16(isp116x); - } else { - /* aligned */ - for (; len > 1; len -= 2) - *dp2++ = isp116x_raw_read_data16(isp116x); - if (len) - *(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x); - } - if (quot == 1 || quot == 2) - isp116x_raw_read_data16(isp116x); -} - -/* Write PTD's and data for scheduled transfers into the fifo ram. - * Fifo must be empty and ready */ -static void pack_fifo(struct isp116x *isp116x, struct usb_device *dev, - unsigned long pipe, struct ptd *ptd, int n, void *data, - int len) -{ - int buflen = n * sizeof(struct ptd) + len; - int i, done; - - DBG("--- pack buffer %p - %d bytes (fifo %d) ---", data, len, buflen); - - isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); - isp116x_write_reg16(isp116x, HCXFERCTR, buflen); - isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET); - - done = 0; - for (i = 0; i < n; i++) { - DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i])); - - dump_ptd(&ptd[i]); - isp116x_write_data16(isp116x, ptd[i].count); - isp116x_write_data16(isp116x, ptd[i].mps); - isp116x_write_data16(isp116x, ptd[i].len); - isp116x_write_data16(isp116x, ptd[i].faddr); - - dump_ptd_data(&ptd[i], (__u8 *) data + done, 0); - write_ptddata_to_fifo(isp116x, - (__u8 *) data + done, - PTD_GET_LEN(&ptd[i])); - - done += PTD_GET_LEN(&ptd[i]); - } -} - -/* Read the processed PTD's and data from fifo ram back to URBs' buffers. - * Fifo must be full and done */ -static int unpack_fifo(struct isp116x *isp116x, struct usb_device *dev, - unsigned long pipe, struct ptd *ptd, int n, void *data, - int len) -{ - int buflen = n * sizeof(struct ptd) + len; - int i, done, cc, ret; - - isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); - isp116x_write_reg16(isp116x, HCXFERCTR, buflen); - isp116x_write_addr(isp116x, HCATLPORT); - - ret = TD_CC_NOERROR; - done = 0; - for (i = 0; i < n; i++) { - DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i])); - - ptd[i].count = isp116x_read_data16(isp116x); - ptd[i].mps = isp116x_read_data16(isp116x); - ptd[i].len = isp116x_read_data16(isp116x); - ptd[i].faddr = isp116x_read_data16(isp116x); - dump_ptd(&ptd[i]); - - read_ptddata_from_fifo(isp116x, - (__u8 *) data + done, - PTD_GET_LEN(&ptd[i])); - dump_ptd_data(&ptd[i], (__u8 *) data + done, 1); - - done += PTD_GET_LEN(&ptd[i]); - - cc = PTD_GET_CC(&ptd[i]); - - /* Data underrun means basically that we had more buffer space than - * the function had data. It is perfectly normal but upper levels have - * to know how much we actually transferred. - */ - if (cc == TD_NOTACCESSED || - (cc != TD_CC_NOERROR && (ret == TD_CC_NOERROR || ret == TD_DATAUNDERRUN))) - ret = cc; - } - - DBG("--- unpack buffer %p - %d bytes (fifo %d) ---", data, len, buflen); - - return ret; -} - -/* Interrupt handling - */ -static int isp116x_interrupt(struct isp116x *isp116x) -{ - u16 irqstat; - u32 intstat; - int ret = 0; - - isp116x_write_reg16(isp116x, HCuPINTENB, 0); - irqstat = isp116x_read_reg16(isp116x, HCuPINT); - isp116x_write_reg16(isp116x, HCuPINT, irqstat); - DBG(">>>>>> irqstat %x <<<<<<", irqstat); - - if (irqstat & HCuPINT_ATL) { - DBG(">>>>>> HCuPINT_ATL <<<<<<"); - udelay(500); - ret = 1; - } - - if (irqstat & HCuPINT_OPR) { - intstat = isp116x_read_reg32(isp116x, HCINTSTAT); - isp116x_write_reg32(isp116x, HCINTSTAT, intstat); - DBG(">>>>>> HCuPINT_OPR %x <<<<<<", intstat); - - if (intstat & HCINT_UE) { - ERR("unrecoverable error, controller disabled"); - - /* FIXME: be optimistic, hope that bug won't repeat - * often. Make some non-interrupt context restart the - * controller. Count and limit the retries though; - * either hardware or software errors can go forever... - */ - isp116x_reset(isp116x); - ret = -1; - return -1; - } - - if (intstat & HCINT_RHSC) { - got_rhsc = 1; - ret = 1; - /* When root hub or any of its ports is going - to come out of suspend, it may take more - than 10ms for status bits to stabilize. */ - mdelay(20); - } - - if (intstat & HCINT_SO) { - ERR("schedule overrun"); - ret = -1; - } - - irqstat &= ~HCuPINT_OPR; - } - - return ret; -} - -/* With one PTD we can transfer almost 1K in one go; - * HC does the splitting into endpoint digestible transactions - */ -struct ptd ptd[1]; - -static inline int max_transfer_len(struct usb_device *dev, unsigned long pipe) -{ - unsigned mpck = usb_maxpacket(dev, pipe); - - /* One PTD can transfer 1023 bytes but try to always - * transfer multiples of endpoint buffer size - */ - return 1023 / mpck * mpck; -} - -/* Do an USB transfer - */ -static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe, - int dir, void *buffer, int len) -{ - struct isp116x *isp116x = &isp116x_dev; - int type = usb_pipetype(pipe); - int epnum = usb_pipeendpoint(pipe); - int max = usb_maxpacket(dev, pipe); - int dir_out = usb_pipeout(pipe); - int speed_low = (dev->speed == USB_SPEED_LOW); - int i, done = 0, stat, timeout, cc; - - /* 500 frames or 0.5s timeout when function is busy and NAKs transactions for a while */ - int retries = 500; - - DBG("------------------------------------------------"); - dump_msg(dev, pipe, buffer, len, "SUBMIT"); - DBG("------------------------------------------------"); - - if (len >= 1024) { - ERR("Too big job"); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - if (isp116x->disabled) { - ERR("EPIPE"); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - /* device pulled? Shortcut the action. */ - if (devgone == dev) { - ERR("ENODEV"); - dev->status = USB_ST_CRC_ERR; - return USB_ST_CRC_ERR; - } - - if (!max) { - ERR("pipesize for pipe %lx is zero", pipe); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - if (type == PIPE_ISOCHRONOUS) { - ERR("isochronous transfers not supported"); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - /* FIFO not empty? */ - if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL) { - ERR("****** FIFO not empty! ******"); - dev->status = USB_ST_BUF_ERR; - return -1; - } - - retry: - isp116x_write_reg32(isp116x, HCINTSTAT, 0xff); - - /* Prepare the PTD data */ - ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK | - PTD_TOGGLE(usb_gettoggle(dev, epnum, dir_out)); - ptd->mps = PTD_MPS(max) | PTD_SPD(speed_low) | PTD_EP(epnum) | PTD_LAST_MSK; - ptd->len = PTD_LEN(len) | PTD_DIR(dir); - ptd->faddr = PTD_FA(usb_pipedevice(pipe)); - -retry_same: - /* Pack data into FIFO ram */ - pack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len); -#ifdef EXTRA_DELAY - mdelay(EXTRA_DELAY); -#endif - - /* Start the data transfer */ - - /* Allow more time for a BULK device to react - some are slow */ - if (usb_pipebulk(pipe)) - timeout = 5000; - else - timeout = 100; - - /* Wait for it to complete */ - for (;;) { - /* Check whether the controller is done */ - stat = isp116x_interrupt(isp116x); - - if (stat < 0) { - dev->status = USB_ST_CRC_ERR; - break; - } - if (stat > 0) - break; - - /* Check the timeout */ - if (--timeout) - udelay(1); - else { - ERR("CTL:TIMEOUT "); - stat = USB_ST_CRC_ERR; - break; - } - } - - /* We got an Root Hub Status Change interrupt */ - if (got_rhsc) { - isp116x_show_regs(isp116x); - - got_rhsc = 0; - - /* Abuse timeout */ - timeout = rh_check_port_status(isp116x); - if (timeout >= 0) { - /* - * FIXME! NOTE! AAAARGH! - * This is potentially dangerous because it assumes - * that only one device is ever plugged in! - */ - devgone = dev; - } - } - - /* Ok, now we can read transfer status */ - - /* FIFO not ready? */ - if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE)) { - ERR("****** FIFO not ready! ******"); - dev->status = USB_ST_BUF_ERR; - return -1; - } - - /* Unpack data from FIFO ram */ - cc = unpack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len); - - i = PTD_GET_COUNT(ptd); - done += i; - buffer += i; - len -= i; - - /* There was some kind of real problem; Prepare the PTD again - * and retry from the failed transaction on - */ - if (cc && cc != TD_NOTACCESSED && cc != TD_DATAUNDERRUN) { - if (retries >= 100) { - retries -= 100; - /* The chip will have toggled the toggle bit for the failed - * transaction too. We have to toggle it back. - */ - usb_settoggle(dev, epnum, dir_out, !PTD_GET_TOGGLE(ptd)); - goto retry; - } - } - /* "Normal" errors; TD_NOTACCESSED would mean in effect that the function have NAKed - * the transactions from the first on for the whole frame. It may be busy and we retry - * with the same PTD. PTD_ACTIVE (and not TD_NOTACCESSED) would mean that some of the - * PTD didn't make it because the function was busy or the frame ended before the PTD - * finished. We prepare the rest of the data and try again. - */ - else if (cc == TD_NOTACCESSED || PTD_GET_ACTIVE(ptd) || (cc != TD_DATAUNDERRUN && PTD_GET_COUNT(ptd) < PTD_GET_LEN(ptd))) { - if (retries) { - --retries; - if (cc == TD_NOTACCESSED && PTD_GET_ACTIVE(ptd) && !PTD_GET_COUNT(ptd)) goto retry_same; - usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd)); - goto retry; - } - } - - if (cc != TD_CC_NOERROR && cc != TD_DATAUNDERRUN) { - DBG("****** completition code error %x ******", cc); - switch (cc) { - case TD_CC_BITSTUFFING: - dev->status = USB_ST_BIT_ERR; - break; - case TD_CC_STALL: - dev->status = USB_ST_STALLED; - break; - case TD_BUFFEROVERRUN: - case TD_BUFFERUNDERRUN: - dev->status = USB_ST_BUF_ERR; - break; - default: - dev->status = USB_ST_CRC_ERR; - } - return -cc; - } - else usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd)); - - dump_msg(dev, pipe, buffer, len, "SUBMIT(ret)"); - - dev->status = 0; - return done; -} - -/* Adapted from au1x00_usb_ohci.c - */ -static int isp116x_submit_rh_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *cmd) -{ - struct isp116x *isp116x = &isp116x_dev; - u32 tmp = 0; - - int leni = transfer_len; - int len = 0; - int stat = 0; - u32 datab[4]; - u8 *data_buf = (u8 *) datab; - u16 bmRType_bReq; - u16 wValue; - u16 wIndex; - u16 wLength; - - if (usb_pipeint(pipe)) { - INFO("Root-Hub submit IRQ: NOT implemented"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = swap_16(cmd->value); - wIndex = swap_16(cmd->index); - wLength = swap_16(cmd->length); - - DBG("--- HUB ----------------------------------------"); - DBG("submit rh urb, req=%x val=%#x index=%#x len=%d", - bmRType_bReq, wValue, wIndex, wLength); - dump_msg(dev, pipe, buffer, transfer_len, "RH"); - DBG("------------------------------------------------"); - - switch (bmRType_bReq) { - case RH_GET_STATUS: - DBG("RH_GET_STATUS"); - - *(__u16 *) data_buf = swap_16(1); - len = 2; - break; - - case RH_GET_STATUS | RH_INTERFACE: - DBG("RH_GET_STATUS | RH_INTERFACE"); - - *(__u16 *) data_buf = swap_16(0); - len = 2; - break; - - case RH_GET_STATUS | RH_ENDPOINT: - DBG("RH_GET_STATUS | RH_ENDPOINT"); - - *(__u16 *) data_buf = swap_16(0); - len = 2; - break; - - case RH_GET_STATUS | RH_CLASS: - DBG("RH_GET_STATUS | RH_CLASS"); - - tmp = isp116x_read_reg32(isp116x, HCRHSTATUS); - - *(__u32 *) data_buf = swap_32(tmp & ~(RH_HS_CRWE | RH_HS_DRWE)); - len = 4; - break; - - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - DBG("RH_GET_STATUS | RH_OTHER | RH_CLASS"); - - tmp = isp116x_read_reg32(isp116x, HCRHPORT1 + wIndex - 1); - *(__u32 *) data_buf = swap_32(tmp); - isp116x_show_regs(isp116x); - len = 4; - break; - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - DBG("RH_CLEAR_FEATURE | RH_ENDPOINT"); - - switch (wValue) { - case RH_ENDPOINT_STALL: - DBG("C_HUB_ENDPOINT_STALL"); - len = 0; - break; - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - DBG("RH_CLEAR_FEATURE | RH_CLASS"); - - switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - DBG("C_HUB_LOCAL_POWER"); - len = 0; - break; - - case RH_C_HUB_OVER_CURRENT: - DBG("C_HUB_OVER_CURRENT"); - isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC); - len = 0; - break; - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - DBG("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS"); - - switch (wValue) { - case RH_PORT_ENABLE: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_CCS); - len = 0; - break; - - case RH_PORT_SUSPEND: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_POCI); - len = 0; - break; - - case RH_PORT_POWER: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_LSDA); - len = 0; - break; - - case RH_C_PORT_CONNECTION: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_CSC); - len = 0; - break; - - case RH_C_PORT_ENABLE: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PESC); - len = 0; - break; - - case RH_C_PORT_SUSPEND: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PSSC); - len = 0; - break; - - case RH_C_PORT_OVER_CURRENT: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_POCI); - len = 0; - break; - - case RH_C_PORT_RESET: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PRSC); - len = 0; - break; - - default: - ERR("invalid wValue"); - stat = USB_ST_STALLED; - } - - isp116x_show_regs(isp116x); - - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - DBG("RH_SET_FEATURE | RH_OTHER | RH_CLASS"); - - switch (wValue) { - case RH_PORT_SUSPEND: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PSS); - len = 0; - break; - - case RH_PORT_RESET: - /* Spin until any current reset finishes */ - while (1) { - tmp = - isp116x_read_reg32(isp116x, - HCRHPORT1 + wIndex - 1); - if (!(tmp & RH_PS_PRS)) - break; - mdelay(1); - } - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PRS); - mdelay(10); - - len = 0; - break; - - case RH_PORT_POWER: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PPS); - len = 0; - break; - - case RH_PORT_ENABLE: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PES); - len = 0; - break; - - default: - ERR("invalid wValue"); - stat = USB_ST_STALLED; - } - - isp116x_show_regs(isp116x); - - break; - - case RH_SET_ADDRESS: - DBG("RH_SET_ADDRESS"); - - rh_devnum = wValue; - len = 0; - break; - - case RH_GET_DESCRIPTOR: - DBG("RH_GET_DESCRIPTOR: %x, %d", wValue, wLength); - - switch (wValue) { - case (USB_DT_DEVICE << 8): /* device descriptor */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_dev_des), - wLength)); - data_buf = root_hub_dev_des; - break; - - case (USB_DT_CONFIG << 8): /* configuration descriptor */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_config_des), - wLength)); - data_buf = root_hub_config_des; - break; - - case ((USB_DT_STRING << 8) | 0x00): /* string 0 descriptors */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_str_index0), - wLength)); - data_buf = root_hub_str_index0; - break; - - case ((USB_DT_STRING << 8) | 0x01): /* string 1 descriptors */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_str_index1), - wLength)); - data_buf = root_hub_str_index1; - break; - - default: - ERR("invalid wValue"); - stat = USB_ST_STALLED; - } - - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - DBG("RH_GET_DESCRIPTOR | RH_CLASS"); - - tmp = isp116x_read_reg32(isp116x, HCRHDESCA); - - data_buf[0] = 0x09; /* min length; */ - data_buf[1] = 0x29; - data_buf[2] = tmp & RH_A_NDP; - data_buf[3] = 0; - if (tmp & RH_A_PSM) /* per-port power switching? */ - data_buf[3] |= 0x01; - if (tmp & RH_A_NOCP) /* no overcurrent reporting? */ - data_buf[3] |= 0x10; - else if (tmp & RH_A_OCPM) /* per-port overcurrent rep? */ - data_buf[3] |= 0x08; - - /* Corresponds to data_buf[4-7] */ - datab[1] = 0; - data_buf[5] = (tmp & RH_A_POTPGT) >> 24; - - tmp = isp116x_read_reg32(isp116x, HCRHDESCB); - - data_buf[7] = tmp & RH_B_DR; - if (data_buf[2] < 7) - data_buf[8] = 0xff; - else { - data_buf[0] += 2; - data_buf[8] = (tmp & RH_B_DR) >> 8; - data_buf[10] = data_buf[9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, data_buf[0], wLength)); - break; - - case RH_GET_CONFIGURATION: - DBG("RH_GET_CONFIGURATION"); - - *(__u8 *) data_buf = 0x01; - len = 1; - break; - - case RH_SET_CONFIGURATION: - DBG("RH_SET_CONFIGURATION"); - - isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPSC); - len = 0; - break; - - default: - ERR("*** *** *** unsupported root hub command *** *** ***"); - stat = USB_ST_STALLED; - } - - len = min_t(int, len, leni); - if (buffer != data_buf) - memcpy(buffer, data_buf, len); - - dev->act_len = len; - dev->status = stat; - DBG("dev act_len %d, status %d", dev->act_len, dev->status); - - dump_msg(dev, pipe, buffer, transfer_len, "RH(ret)"); - - return stat; -} - -/* --- Transfer functions -------------------------------------------------- */ - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, int interval) -{ - DBG("dev=%p pipe=%#lx buf=%p size=%d int=%d", - dev, pipe, buffer, len, interval); - - return -1; -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, struct devrequest *setup) -{ - int devnum = usb_pipedevice(pipe); - int epnum = usb_pipeendpoint(pipe); - int max = max_transfer_len(dev, pipe); - int dir_in = usb_pipein(pipe); - int done, ret; - - /* Control message is for the HUB? */ - if (devnum == rh_devnum) - return isp116x_submit_rh_msg(dev, pipe, buffer, len, setup); - - /* Ok, no HUB message so send the message to the device */ - - /* Setup phase */ - DBG("--- SETUP PHASE --------------------------------"); - usb_settoggle(dev, epnum, 1, 0); - ret = isp116x_submit_job(dev, pipe, - PTD_DIR_SETUP, - setup, sizeof(struct devrequest)); - if (ret < 0) { - DBG("control setup phase error (ret = %d", ret); - return -1; - } - - /* Data phase */ - DBG("--- DATA PHASE ---------------------------------"); - done = 0; - usb_settoggle(dev, epnum, !dir_in, 1); - while (done < len) { - ret = isp116x_submit_job(dev, pipe, - dir_in ? PTD_DIR_IN : PTD_DIR_OUT, - (__u8 *) buffer + done, - max > len - done ? len - done : max); - if (ret < 0) { - DBG("control data phase error (ret = %d)", ret); - return -1; - } - done += ret; - - if (dir_in && ret < max) /* short packet */ - break; - } - - /* Status phase */ - DBG("--- STATUS PHASE -------------------------------"); - usb_settoggle(dev, epnum, !dir_in, 1); - ret = isp116x_submit_job(dev, pipe, - !dir_in ? PTD_DIR_IN : PTD_DIR_OUT, NULL, 0); - if (ret < 0) { - DBG("control status phase error (ret = %d", ret); - return -1; - } - - dev->act_len = done; - - dump_msg(dev, pipe, buffer, len, "DEV(ret)"); - - return done; -} - -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len) -{ - int dir_out = usb_pipeout(pipe); - int max = max_transfer_len(dev, pipe); - int done, ret; - - DBG("--- BULK ---------------------------------------"); - DBG("dev=%ld pipe=%ld buf=%p size=%d dir_out=%d", - usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out); - - done = 0; - while (done < len) { - ret = isp116x_submit_job(dev, pipe, - !dir_out ? PTD_DIR_IN : PTD_DIR_OUT, - (__u8 *) buffer + done, - max > len - done ? len - done : max); - if (ret < 0) { - DBG("error on bulk message (ret = %d)", ret); - return -1; - } - - done += ret; - - if (!dir_out && ret < max) /* short packet */ - break; - } - - dev->act_len = done; - - return 0; -} - -/* --- Basic functions ----------------------------------------------------- */ - -static int isp116x_sw_reset(struct isp116x *isp116x) -{ - int retries = 15; - int ret = 0; - - DBG(""); - - isp116x->disabled = 1; - - isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC); - isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR); - while (--retries) { - /* It usually resets within 1 ms */ - mdelay(1); - if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR)) - break; - } - if (!retries) { - ERR("software reset timeout"); - ret = -1; - } - return ret; -} - -static int isp116x_reset(struct isp116x *isp116x) -{ - unsigned long t; - u16 clkrdy = 0; - int ret, timeout = 15 /* ms */ ; - - DBG(""); - - ret = isp116x_sw_reset(isp116x); - if (ret) - return ret; - - for (t = 0; t < timeout; t++) { - clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY; - if (clkrdy) - break; - mdelay(1); - } - if (!clkrdy) { - ERR("clock not ready after %dms", timeout); - /* After sw_reset the clock won't report to be ready, if - H_WAKEUP pin is high. */ - ERR("please make sure that the H_WAKEUP pin is pulled low!"); - ret = -1; - } - return ret; -} - -static void isp116x_stop(struct isp116x *isp116x) -{ - u32 val; - - DBG(""); - - isp116x_write_reg16(isp116x, HCuPINTENB, 0); - - /* Switch off ports' power, some devices don't come up - after next 'start' without this */ - val = isp116x_read_reg32(isp116x, HCRHDESCA); - val &= ~(RH_A_NPS | RH_A_PSM); - isp116x_write_reg32(isp116x, HCRHDESCA, val); - isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS); - - isp116x_sw_reset(isp116x); -} - -/* - * Configure the chip. The chip must be successfully reset by now. - */ -static int isp116x_start(struct isp116x *isp116x) -{ - struct isp116x_platform_data *board = isp116x->board; - u32 val; - - DBG(""); - - /* Clear interrupt status and disable all interrupt sources */ - isp116x_write_reg16(isp116x, HCuPINT, 0xff); - isp116x_write_reg16(isp116x, HCuPINTENB, 0); - - isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE); - isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE); - - /* Hardware configuration */ - val = HCHWCFG_DBWIDTH(1); - if (board->sel15Kres) - val |= HCHWCFG_15KRSEL; - /* Remote wakeup won't work without working clock */ - if (board->remote_wakeup_enable) - val |= HCHWCFG_CLKNOTSTOP; - if (board->oc_enable) - val |= HCHWCFG_ANALOG_OC; - isp116x_write_reg16(isp116x, HCHWCFG, val); - - /* --- Root hub configuration */ - val = (25 << 24) & RH_A_POTPGT; - /* AN10003_1.pdf recommends RH_A_NPS (no power switching) to - be always set. Yet, instead, we request individual port - power switching. */ - val |= RH_A_PSM; - /* Report overcurrent per port */ - val |= RH_A_OCPM; - isp116x_write_reg32(isp116x, HCRHDESCA, val); - isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA); - - val = RH_B_PPCM; - isp116x_write_reg32(isp116x, HCRHDESCB, val); - isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB); - - val = 0; - if (board->remote_wakeup_enable) - val |= RH_HS_DRWE; - isp116x_write_reg32(isp116x, HCRHSTATUS, val); - isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS); - - isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf); - - /* Go operational */ - val = HCCONTROL_USB_OPER; - if (board->remote_wakeup_enable) - val |= HCCONTROL_RWE; - isp116x_write_reg32(isp116x, HCCONTROL, val); - - /* Disable ports to avoid race in device enumeration */ - isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); - isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS); - - isp116x_show_regs(isp116x); - - isp116x->disabled = 0; - - return 0; -} - -/* --- Init functions ------------------------------------------------------ */ - -int isp116x_check_id(struct isp116x *isp116x) -{ - int val; - - val = isp116x_read_reg16(isp116x, HCCHIPID); - if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) { - ERR("invalid chip ID %04x", val); - return -1; - } - - return 0; -} - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)) -{ - struct isp116x *isp116x = &isp116x_dev; - - DBG(""); - - got_rhsc = rh_devnum = 0; - - /* Init device registers addr */ - isp116x->addr_reg = (u16 *) ISP116X_HCD_ADDR; - isp116x->data_reg = (u16 *) ISP116X_HCD_DATA; - - /* Setup specific board settings */ -#ifdef ISP116X_HCD_SEL15kRES - isp116x_board.sel15Kres = 1; -#endif -#ifdef ISP116X_HCD_OC_ENABLE - isp116x_board.oc_enable = 1; -#endif -#ifdef ISP116X_HCD_REMOTE_WAKEUP_ENABLE - isp116x_board.remote_wakeup_enable = 1; -#endif - isp116x->board = &isp116x_board; - - /* Try to get ISP116x silicon chip ID */ - if (isp116x_check_id(isp116x) < 0) - return -1; - - isp116x->disabled = 1; - isp116x->sleeping = 0; - - isp116x_reset(isp116x); - isp116x_start(isp116x); - - return 0; -} - -int usb_lowlevel_stop(int index) -{ - struct isp116x *isp116x = &isp116x_dev; - - DBG(""); - - if (!isp116x->disabled) - isp116x_stop(isp116x); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/isp116x.h b/qemu/roms/u-boot/drivers/usb/host/isp116x.h deleted file mode 100644 index 5b7afaf42..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/isp116x.h +++ /dev/null @@ -1,476 +0,0 @@ -/* - * ISP116x register declarations and HCD data structures - * - * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it> - * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it> - * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee> - * Portions: - * Copyright (C) 2004 Lothar Wassmann - * Copyright (C) 2004 Psion Teklogix - * Copyright (C) 2004 David Brownell - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifdef DEBUG -#define DBG(fmt, args...) \ - printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) -#else -#define DBG(fmt, args...) do {} while (0) -#endif - -#ifdef VERBOSE -# define VDBG DBG -#else -# define VDBG(fmt, args...) do {} while (0) -#endif - -#define ERR(fmt, args...) \ - printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) -#define WARN(fmt, args...) \ - printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) -#define INFO(fmt, args...) \ - printf("isp116x: " fmt "\n" , ## args) - -/* ------------------------------------------------------------------------- */ - -/* us of 1ms frame */ -#define MAX_LOAD_LIMIT 850 - -/* Full speed: max # of bytes to transfer for a single urb - at a time must be < 1024 && must be multiple of 64. - 832 allows transfering 4kiB within 5 frames. */ -#define MAX_TRANSFER_SIZE_FULLSPEED 832 - -/* Low speed: there is no reason to schedule in very big - chunks; often the requested long transfers are for - string descriptors containing short strings. */ -#define MAX_TRANSFER_SIZE_LOWSPEED 64 - -/* Bytetime (us), a rough indication of how much time it - would take to transfer a byte of useful data over USB */ -#define BYTE_TIME_FULLSPEED 1 -#define BYTE_TIME_LOWSPEED 20 - -/* Buffer sizes */ -#define ISP116x_BUF_SIZE 4096 -#define ISP116x_ITL_BUFSIZE 0 -#define ISP116x_ATL_BUFSIZE ((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE)) - -#define ISP116x_WRITE_OFFSET 0x80 - -/* --- ISP116x registers/bits ---------------------------------------------- */ - -#define HCREVISION 0x00 -#define HCCONTROL 0x01 -#define HCCONTROL_HCFS (3 << 6) /* host controller - functional state */ -#define HCCONTROL_USB_RESET (0 << 6) -#define HCCONTROL_USB_RESUME (1 << 6) -#define HCCONTROL_USB_OPER (2 << 6) -#define HCCONTROL_USB_SUSPEND (3 << 6) -#define HCCONTROL_RWC (1 << 9) /* remote wakeup connected */ -#define HCCONTROL_RWE (1 << 10) /* remote wakeup enable */ -#define HCCMDSTAT 0x02 -#define HCCMDSTAT_HCR (1 << 0) /* host controller reset */ -#define HCCMDSTAT_SOC (3 << 16) /* scheduling overrun count */ -#define HCINTSTAT 0x03 -#define HCINT_SO (1 << 0) /* scheduling overrun */ -#define HCINT_WDH (1 << 1) /* writeback of done_head */ -#define HCINT_SF (1 << 2) /* start frame */ -#define HCINT_RD (1 << 3) /* resume detect */ -#define HCINT_UE (1 << 4) /* unrecoverable error */ -#define HCINT_FNO (1 << 5) /* frame number overflow */ -#define HCINT_RHSC (1 << 6) /* root hub status change */ -#define HCINT_OC (1 << 30) /* ownership change */ -#define HCINT_MIE (1 << 31) /* master interrupt enable */ -#define HCINTENB 0x04 -#define HCINTDIS 0x05 -#define HCFMINTVL 0x0d -#define HCFMREM 0x0e -#define HCFMNUM 0x0f -#define HCLSTHRESH 0x11 -#define HCRHDESCA 0x12 -#define RH_A_NDP (0x3 << 0) /* # downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* overcurrent protection - mode */ -#define RH_A_NOCP (1 << 12) /* no overcurrent protection */ -#define RH_A_POTPGT (0xff << 24) /* power on -> power good - time */ -#define HCRHDESCB 0x13 -#define RH_B_DR (0xffff << 0) /* device removable flags */ -#define RH_B_PPCM (0xffff << 16) /* port power control mask */ -#define HCRHSTATUS 0x14 -#define RH_HS_LPS (1 << 0) /* local power status */ -#define RH_HS_OCI (1 << 1) /* over current indicator */ -#define RH_HS_DRWE (1 << 15) /* device remote wakeup - enable */ -#define RH_HS_LPSC (1 << 16) /* local power status change */ -#define RH_HS_OCIC (1 << 17) /* over current indicator - change */ -#define RH_HS_CRWE (1 << 31) /* clear remote wakeup - enable */ -#define HCRHPORT1 0x15 -#define RH_PS_CCS (1 << 0) /* current connect status */ -#define RH_PS_PES (1 << 1) /* port enable status */ -#define RH_PS_PSS (1 << 2) /* port suspend status */ -#define RH_PS_POCI (1 << 3) /* port over current - indicator */ -#define RH_PS_PRS (1 << 4) /* port reset status */ -#define RH_PS_PPS (1 << 8) /* port power status */ -#define RH_PS_LSDA (1 << 9) /* low speed device attached */ -#define RH_PS_CSC (1 << 16) /* connect status change */ -#define RH_PS_PESC (1 << 17) /* port enable status change */ -#define RH_PS_PSSC (1 << 18) /* port suspend status - change */ -#define RH_PS_OCIC (1 << 19) /* over current indicator - change */ -#define RH_PS_PRSC (1 << 20) /* port reset status change */ -#define HCRHPORT_CLRMASK (0x1f << 16) -#define HCRHPORT2 0x16 -#define HCHWCFG 0x20 -#define HCHWCFG_15KRSEL (1 << 12) -#define HCHWCFG_CLKNOTSTOP (1 << 11) -#define HCHWCFG_ANALOG_OC (1 << 10) -#define HCHWCFG_DACK_MODE (1 << 8) -#define HCHWCFG_EOT_POL (1 << 7) -#define HCHWCFG_DACK_POL (1 << 6) -#define HCHWCFG_DREQ_POL (1 << 5) -#define HCHWCFG_DBWIDTH_MASK (0x03 << 3) -#define HCHWCFG_DBWIDTH(n) (((n) << 3) & HCHWCFG_DBWIDTH_MASK) -#define HCHWCFG_INT_POL (1 << 2) -#define HCHWCFG_INT_TRIGGER (1 << 1) -#define HCHWCFG_INT_ENABLE (1 << 0) -#define HCDMACFG 0x21 -#define HCDMACFG_BURST_LEN_MASK (0x03 << 5) -#define HCDMACFG_BURST_LEN(n) (((n) << 5) & HCDMACFG_BURST_LEN_MASK) -#define HCDMACFG_BURST_LEN_1 HCDMACFG_BURST_LEN(0) -#define HCDMACFG_BURST_LEN_4 HCDMACFG_BURST_LEN(1) -#define HCDMACFG_BURST_LEN_8 HCDMACFG_BURST_LEN(2) -#define HCDMACFG_DMA_ENABLE (1 << 4) -#define HCDMACFG_BUF_TYPE_MASK (0x07 << 1) -#define HCDMACFG_CTR_SEL (1 << 2) -#define HCDMACFG_ITLATL_SEL (1 << 1) -#define HCDMACFG_DMA_RW_SELECT (1 << 0) -#define HCXFERCTR 0x22 -#define HCuPINT 0x24 -#define HCuPINT_SOF (1 << 0) -#define HCuPINT_ATL (1 << 1) -#define HCuPINT_AIIEOT (1 << 2) -#define HCuPINT_OPR (1 << 4) -#define HCuPINT_SUSP (1 << 5) -#define HCuPINT_CLKRDY (1 << 6) -#define HCuPINTENB 0x25 -#define HCCHIPID 0x27 -#define HCCHIPID_MASK 0xff00 -#define HCCHIPID_MAGIC 0x6100 -#define HCSCRATCH 0x28 -#define HCSWRES 0x29 -#define HCSWRES_MAGIC 0x00f6 -#define HCITLBUFLEN 0x2a -#define HCATLBUFLEN 0x2b -#define HCBUFSTAT 0x2c -#define HCBUFSTAT_ITL0_FULL (1 << 0) -#define HCBUFSTAT_ITL1_FULL (1 << 1) -#define HCBUFSTAT_ATL_FULL (1 << 2) -#define HCBUFSTAT_ITL0_DONE (1 << 3) -#define HCBUFSTAT_ITL1_DONE (1 << 4) -#define HCBUFSTAT_ATL_DONE (1 << 5) -#define HCRDITL0LEN 0x2d -#define HCRDITL1LEN 0x2e -#define HCITLPORT 0x40 -#define HCATLPORT 0x41 - -/* PTD accessor macros. */ -#define PTD_GET_COUNT(p) (((p)->count & PTD_COUNT_MSK) >> 0) -#define PTD_COUNT(v) (((v) << 0) & PTD_COUNT_MSK) -#define PTD_GET_TOGGLE(p) (((p)->count & PTD_TOGGLE_MSK) >> 10) -#define PTD_TOGGLE(v) (((v) << 10) & PTD_TOGGLE_MSK) -#define PTD_GET_ACTIVE(p) (((p)->count & PTD_ACTIVE_MSK) >> 11) -#define PTD_ACTIVE(v) (((v) << 11) & PTD_ACTIVE_MSK) -#define PTD_GET_CC(p) (((p)->count & PTD_CC_MSK) >> 12) -#define PTD_CC(v) (((v) << 12) & PTD_CC_MSK) -#define PTD_GET_MPS(p) (((p)->mps & PTD_MPS_MSK) >> 0) -#define PTD_MPS(v) (((v) << 0) & PTD_MPS_MSK) -#define PTD_GET_SPD(p) (((p)->mps & PTD_SPD_MSK) >> 10) -#define PTD_SPD(v) (((v) << 10) & PTD_SPD_MSK) -#define PTD_GET_LAST(p) (((p)->mps & PTD_LAST_MSK) >> 11) -#define PTD_LAST(v) (((v) << 11) & PTD_LAST_MSK) -#define PTD_GET_EP(p) (((p)->mps & PTD_EP_MSK) >> 12) -#define PTD_EP(v) (((v) << 12) & PTD_EP_MSK) -#define PTD_GET_LEN(p) (((p)->len & PTD_LEN_MSK) >> 0) -#define PTD_LEN(v) (((v) << 0) & PTD_LEN_MSK) -#define PTD_GET_DIR(p) (((p)->len & PTD_DIR_MSK) >> 10) -#define PTD_DIR(v) (((v) << 10) & PTD_DIR_MSK) -#define PTD_GET_B5_5(p) (((p)->len & PTD_B5_5_MSK) >> 13) -#define PTD_B5_5(v) (((v) << 13) & PTD_B5_5_MSK) -#define PTD_GET_FA(p) (((p)->faddr & PTD_FA_MSK) >> 0) -#define PTD_FA(v) (((v) << 0) & PTD_FA_MSK) -#define PTD_GET_FMT(p) (((p)->faddr & PTD_FMT_MSK) >> 7) -#define PTD_FMT(v) (((v) << 7) & PTD_FMT_MSK) - -/* Hardware transfer status codes -- CC from ptd->count */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 - /* 0x0A, 0x0B reserved for hardware */ -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D - /* 0x0E, 0x0F reserved for HCD */ -#define TD_NOTACCESSED 0x0F - -/* ------------------------------------------------------------------------- */ - -#define LOG2_PERIODIC_SIZE 5 /* arbitrary; this matches OHCI */ -#define PERIODIC_SIZE (1 << LOG2_PERIODIC_SIZE) - -/* Philips transfer descriptor */ -struct ptd { - u16 count; -#define PTD_COUNT_MSK (0x3ff << 0) -#define PTD_TOGGLE_MSK (1 << 10) -#define PTD_ACTIVE_MSK (1 << 11) -#define PTD_CC_MSK (0xf << 12) - u16 mps; -#define PTD_MPS_MSK (0x3ff << 0) -#define PTD_SPD_MSK (1 << 10) -#define PTD_LAST_MSK (1 << 11) -#define PTD_EP_MSK (0xf << 12) - u16 len; -#define PTD_LEN_MSK (0x3ff << 0) -#define PTD_DIR_MSK (3 << 10) -#define PTD_DIR_SETUP (0) -#define PTD_DIR_OUT (1) -#define PTD_DIR_IN (2) -#define PTD_B5_5_MSK (1 << 13) - u16 faddr; -#define PTD_FA_MSK (0x7f << 0) -#define PTD_FMT_MSK (1 << 7) -} __attribute__ ((packed, aligned(2))); - -struct isp116x_ep { - struct usb_device *udev; - struct ptd ptd; - - u8 maxpacket; - u8 epnum; - u8 nextpid; - - u16 length; /* of current packet */ - unsigned char *data; /* to databuf */ - - u16 error_count; -}; - -/* URB struct */ -#define N_URB_TD 48 -#define URB_DEL 1 -typedef struct { - struct isp116x_ep *ed; - void *transfer_buffer; /* (in) associated data buffer */ - int actual_length; /* (return) actual transfer length */ - unsigned long pipe; /* (in) pipe information */ -#if 0 - int state; -#endif -} urb_priv_t; - -struct isp116x_platform_data { - /* Enable internal resistors on downstream ports */ - unsigned sel15Kres:1; - /* On-chip overcurrent detection */ - unsigned oc_enable:1; - /* Enable wakeup by devices on usb bus (e.g. wakeup - by attachment/detachment or by device activity - such as moving a mouse). When chosen, this option - prevents stopping internal clock, increasing - thereby power consumption in suspended state. */ - unsigned remote_wakeup_enable:1; -}; - -struct isp116x { - u16 *addr_reg; - u16 *data_reg; - - struct isp116x_platform_data *board; - - struct dentry *dentry; - unsigned long stat1, stat2, stat4, stat8, stat16; - - /* Status flags */ - unsigned disabled:1; - unsigned sleeping:1; - - /* Root hub registers */ - u32 rhdesca; - u32 rhdescb; - u32 rhstatus; - u32 rhport[2]; - - /* Schedule for the current frame */ - struct isp116x_ep *atl_active; - int atl_buflen; - int atl_bufshrt; - int atl_last_dir; - int atl_finishing; -}; - -/* ------------------------------------------------- */ - -/* Inter-io delay (ns). The chip is picky about access timings; it - * expects at least: - * 150ns delay between consecutive accesses to DATA_REG, - * 300ns delay between access to ADDR_REG and DATA_REG - * OE, WE MUST NOT be changed during these intervals - */ -#if defined(UDELAY) -#define isp116x_delay(h,d) udelay(d) -#else -#define isp116x_delay(h,d) do {} while (0) -#endif - -static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg) -{ - writew(reg & 0xff, isp116x->addr_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val) -{ - writew(val, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val) -{ - __raw_writew(val, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline u16 isp116x_read_data16(struct isp116x *isp116x) -{ - u16 val; - - val = readw(isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - return val; -} - -static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x) -{ - u16 val; - - val = __raw_readw(isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - return val; -} - -static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val) -{ - writew(val & 0xffff, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - writew(val >> 16, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline u32 isp116x_read_data32(struct isp116x *isp116x) -{ - u32 val; - - val = (u32) readw(isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - val |= ((u32) readw(isp116x->data_reg)) << 16; - isp116x_delay(isp116x, UDELAY); - return val; -} - -/* Let's keep register access functions out of line. Hint: - we wait at least 150 ns at every access. -*/ -static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg) -{ - isp116x_write_addr(isp116x, reg); - return isp116x_read_data16(isp116x); -} - -static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg) -{ - isp116x_write_addr(isp116x, reg); - return isp116x_read_data32(isp116x); -} - -static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg, - unsigned val) -{ - isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); - isp116x_write_data16(isp116x, (u16) (val & 0xffff)); -} - -static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg, - unsigned val) -{ - isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); - isp116x_write_data32(isp116x, (u32) val); -} - -/* --- USB HUB constants (not OHCI-specific; see hub.h) -------------------- */ - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 - -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci-at91.c b/qemu/roms/u-boot/drivers/usb/host/ohci-at91.c deleted file mode 100644 index c24505e78..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci-at91.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * (C) Copyright 2006 - * DENX Software Engineering <mk@denx.de> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> - -#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) - -#include <asm/io.h> -#include <asm/arch/hardware.h> -#include <asm/arch/at91_pmc.h> -#include <asm/arch/clk.h> - -int usb_cpu_init(void) -{ - at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; - -#ifdef CONFIG_USB_ATMEL_CLK_SEL_PLLB - /* Enable PLLB */ - writel(get_pllb_init(), &pmc->pllbr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB) - ; -#ifdef CONFIG_AT91SAM9N12 - writel(AT91_PMC_USBS_USB_PLLB | AT91_PMC_USB_DIV_2, &pmc->usb); -#endif -#elif defined(CONFIG_USB_ATMEL_CLK_SEL_UPLL) - /* Enable UPLL */ - writel(readl(&pmc->uckr) | AT91_PMC_UPLLEN | AT91_PMC_BIASEN, - &pmc->uckr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKU) != AT91_PMC_LOCKU) - ; - - /* Select PLLA as input clock of OHCI */ - writel(AT91_PMC_USBS_USB_UPLL | AT91_PMC_USBDIV_10, &pmc->usb); -#endif - - /* Enable USB host clock. */ -#ifdef CONFIG_SAMA5D3 - writel(1 << (ATMEL_ID_UHP - 32), &pmc->pcer1); -#else - writel(1 << ATMEL_ID_UHP, &pmc->pcer); -#endif - -#if defined(CONFIG_AT91SAM9261) || defined(CONFIG_AT91SAM9G10) - writel(ATMEL_PMC_UHP | AT91_PMC_HCK0, &pmc->scer); -#else - writel(ATMEL_PMC_UHP, &pmc->scer); -#endif - - return 0; -} - -int usb_cpu_stop(void) -{ - at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; - - /* Disable USB host clock. */ -#ifdef CONFIG_SAMA5D3 - writel(1 << (ATMEL_ID_UHP - 32), &pmc->pcdr1); -#else - writel(1 << ATMEL_ID_UHP, &pmc->pcdr); -#endif - -#if defined(CONFIG_AT91SAM9261) || defined(CONFIG_AT91SAM9G10) - writel(ATMEL_PMC_UHP | AT91_PMC_HCK0, &pmc->scdr); -#else - writel(ATMEL_PMC_UHP, &pmc->scdr); -#endif - -#ifdef CONFIG_USB_ATMEL_CLK_SEL_PLLB -#ifdef CONFIG_AT91SAM9N12 - writel(0, &pmc->usb); -#endif - /* Disable PLLB */ - writel(0, &pmc->pllbr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != 0) - ; -#elif defined(CONFIG_USB_ATMEL_CLK_SEL_UPLL) - /* Disable UPLL */ - writel(readl(&pmc->uckr) & (~AT91_PMC_UPLLEN), &pmc->uckr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKU) == AT91_PMC_LOCKU) - ; -#endif - - return 0; -} - -int usb_cpu_init_fail(void) -{ - return usb_cpu_stop(); -} - -#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */ diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci-da8xx.c b/qemu/roms/u-boot/drivers/usb/host/ohci-da8xx.c deleted file mode 100644 index 981662806..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci-da8xx.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2012 Sughosh Ganu <urwithsughosh@gmail.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> - -#include <asm/arch/da8xx-usb.h> - -int usb_cpu_init(void) -{ - /* enable psc for usb2.0 */ - lpsc_on(DAVINCI_LPSC_USB20); - - /* enable psc for usb1.0 */ - lpsc_on(DAVINCI_LPSC_USB11); - - /* start the on-chip usb phy and its pll */ - if (usb_phy_on()) - return 0; - - return 1; -} - -int usb_cpu_stop(void) -{ - usb_phy_off(); - - /* turn off the usb clock and assert the module reset */ - lpsc_disable(DAVINCI_LPSC_USB11); - lpsc_disable(DAVINCI_LPSC_USB20); - - return 0; -} - -int usb_cpu_init_fail(void) -{ - return usb_cpu_stop(); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci-hcd.c b/qemu/roms/u-boot/drivers/usb/host/ohci-hcd.c deleted file mode 100644 index dc0a4e317..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci-hcd.c +++ /dev/null @@ -1,1885 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200 and PCI bus. - * - * Interrupt support is added. Now, it has been tested - * on ULI1575 chip and works well with USB keyboard. - * - * (C) Copyright 2007 - * Zhang Wei, Freescale Semiconductor, Inc. <wei.zhang@freescale.com> - * - * (C) Copyright 2003 - * Gary Jennejohn, DENX Software Engineering <garyj@denx.de> - * - * Note: Much of this code has been derived from Linux 2.4 - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell - * - * Modified for the MP2USB by (C) Copyright 2005 Eric Benard - * ebenard@eukrea.com - based on s3c24x0's driver - * - * SPDX-License-Identifier: GPL-2.0+ - */ -/* - * IMPORTANT NOTES - * 1 - Read doc/README.generic_usb_ohci - * 2 - this driver is intended for use with USB Mass Storage Devices - * (BBB) and USB keyboard. There is NO support for Isochronous pipes! - * 2 - when running on a PQFP208 AT91RM9200, define CONFIG_AT91C_PQFP_UHPBUG - * to activate workaround for bug #41 or this driver will NOT work! - */ - -#include <common.h> -#include <asm/byteorder.h> - -#if defined(CONFIG_PCI_OHCI) -# include <pci.h> -#if !defined(CONFIG_PCI_OHCI_DEVNO) -#define CONFIG_PCI_OHCI_DEVNO 0 -#endif -#endif - -#include <malloc.h> -#include <usb.h> - -#include "ohci.h" - -#ifdef CONFIG_AT91RM9200 -#include <asm/arch/hardware.h> /* needed for AT91_USB_HOST_BASE */ -#endif - -#if defined(CONFIG_ARM920T) || \ - defined(CONFIG_S3C24X0) || \ - defined(CONFIG_440EP) || \ - defined(CONFIG_PCI_OHCI) || \ - defined(CONFIG_MPC5200) || \ - defined(CONFIG_SYS_OHCI_USE_NPS) -# define OHCI_USE_NPS /* force NoPowerSwitching mode */ -#endif - -#undef OHCI_VERBOSE_DEBUG /* not always helpful */ -#undef DEBUG -#undef SHOW_INFO -#undef OHCI_FILL_TRACE - -/* For initializing controller (mask in an HCFS mode too) */ -#define OHCI_CONTROL_INIT \ - (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE - -#define min_t(type, x, y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) - -#ifdef CONFIG_PCI_OHCI -static struct pci_device_id ohci_pci_ids[] = { - {0x10b9, 0x5237}, /* ULI1575 PCI OHCI module ids */ - {0x1033, 0x0035}, /* NEC PCI OHCI module ids */ - {0x1131, 0x1561}, /* Philips 1561 PCI OHCI module ids */ - /* Please add supported PCI OHCI controller ids here */ - {0, 0} -}; -#endif - -#ifdef CONFIG_PCI_EHCI_DEVNO -static struct pci_device_id ehci_pci_ids[] = { - {0x1131, 0x1562}, /* Philips 1562 PCI EHCI module ids */ - /* Please add supported PCI EHCI controller ids here */ - {0, 0} -}; -#endif - -#ifdef DEBUG -#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) -#else -#define dbg(format, arg...) do {} while (0) -#endif /* DEBUG */ -#define err(format, arg...) printf("ERROR: " format "\n", ## arg) -#ifdef SHOW_INFO -#define info(format, arg...) printf("INFO: " format "\n", ## arg) -#else -#define info(format, arg...) do {} while (0) -#endif - -#ifdef CONFIG_SYS_OHCI_BE_CONTROLLER -# define m16_swap(x) cpu_to_be16(x) -# define m32_swap(x) cpu_to_be32(x) -#else -# define m16_swap(x) cpu_to_le16(x) -# define m32_swap(x) cpu_to_le32(x) -#endif /* CONFIG_SYS_OHCI_BE_CONTROLLER */ - -/* global ohci_t */ -static ohci_t gohci; -/* this must be aligned to a 256 byte boundary */ -struct ohci_hcca ghcca[1]; -/* a pointer to the aligned storage */ -struct ohci_hcca *phcca; -/* this allocates EDs for all possible endpoints */ -struct ohci_device ohci_dev; -/* device which was disconnected */ -struct usb_device *devgone; - -static inline u32 roothub_a(struct ohci *hc) - { return ohci_readl(&hc->regs->roothub.a); } -static inline u32 roothub_b(struct ohci *hc) - { return ohci_readl(&hc->regs->roothub.b); } -static inline u32 roothub_status(struct ohci *hc) - { return ohci_readl(&hc->regs->roothub.status); } -static inline u32 roothub_portstatus(struct ohci *hc, int i) - { return ohci_readl(&hc->regs->roothub.portstatus[i]); } - -/* forward declaration */ -static int hc_interrupt(void); -static void td_submit_job(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *setup, urb_priv_t *urb, - int interval); - -/*-------------------------------------------------------------------------* - * URB support functions - *-------------------------------------------------------------------------*/ - -/* free HCD-private data associated with this URB */ - -static void urb_free_priv(urb_priv_t *urb) -{ - int i; - int last; - struct td *td; - - last = urb->length - 1; - if (last >= 0) { - for (i = 0; i <= last; i++) { - td = urb->td[i]; - if (td) { - td->usb_dev = NULL; - urb->td[i] = NULL; - } - } - } - free(urb); -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -static int sohci_get_current_frame_number(struct usb_device *dev); - -/* debug| print the main components of an URB - * small: 0) header + data packets 1) just header */ - -static void pkt_print(urb_priv_t *purb, struct usb_device *dev, - unsigned long pipe, void *buffer, int transfer_len, - struct devrequest *setup, char *str, int small) -{ - dbg("%s URB:[%4x] dev:%2lu,ep:%2lu-%c,type:%s,len:%d/%d stat:%#lx", - str, - sohci_get_current_frame_number(dev), - usb_pipedevice(pipe), - usb_pipeendpoint(pipe), - usb_pipeout(pipe)? 'O': 'I', - usb_pipetype(pipe) < 2 ? \ - (usb_pipeint(pipe)? "INTR": "ISOC"): \ - (usb_pipecontrol(pipe)? "CTRL": "BULK"), - (purb ? purb->actual_length : 0), - transfer_len, dev->status); -#ifdef OHCI_VERBOSE_DEBUG - if (!small) { - int i, len; - - if (usb_pipecontrol(pipe)) { - printf(__FILE__ ": cmd(8):"); - for (i = 0; i < 8 ; i++) - printf(" %02x", ((__u8 *) setup) [i]); - printf("\n"); - } - if (transfer_len > 0 && buffer) { - printf(__FILE__ ": data(%d/%d):", - (purb ? purb->actual_length : 0), - transfer_len); - len = usb_pipeout(pipe)? transfer_len: - (purb ? purb->actual_length : 0); - for (i = 0; i < 16 && i < len; i++) - printf(" %02x", ((__u8 *) buffer) [i]); - printf("%s\n", i < len? "...": ""); - } - } -#endif -} - -/* just for debugging; prints non-empty branches of the int ed tree - * inclusive iso eds */ -void ep_print_int_eds(ohci_t *ohci, char *str) -{ - int i, j; - __u32 *ed_p; - for (i = 0; i < 32; i++) { - j = 5; - ed_p = &(ohci->hcca->int_table [i]); - if (*ed_p == 0) - continue; - printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i); - while (*ed_p != 0 && j--) { - ed_t *ed = (ed_t *)m32_swap(ed_p); - printf(" ed: %4x;", ed->hwINFO); - ed_p = &ed->hwNextED; - } - printf("\n"); - } -} - -static void ohci_dump_intr_mask(char *label, __u32 mask) -{ - dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s", - label, - mask, - (mask & OHCI_INTR_MIE) ? " MIE" : "", - (mask & OHCI_INTR_OC) ? " OC" : "", - (mask & OHCI_INTR_RHSC) ? " RHSC" : "", - (mask & OHCI_INTR_FNO) ? " FNO" : "", - (mask & OHCI_INTR_UE) ? " UE" : "", - (mask & OHCI_INTR_RD) ? " RD" : "", - (mask & OHCI_INTR_SF) ? " SF" : "", - (mask & OHCI_INTR_WDH) ? " WDH" : "", - (mask & OHCI_INTR_SO) ? " SO" : "" - ); -} - -static void maybe_print_eds(char *label, __u32 value) -{ - ed_t *edp = (ed_t *)value; - - if (value) { - dbg("%s %08x", label, value); - dbg("%08x", edp->hwINFO); - dbg("%08x", edp->hwTailP); - dbg("%08x", edp->hwHeadP); - dbg("%08x", edp->hwNextED); - } -} - -static char *hcfs2string(int state) -{ - switch (state) { - case OHCI_USB_RESET: return "reset"; - case OHCI_USB_RESUME: return "resume"; - case OHCI_USB_OPER: return "operational"; - case OHCI_USB_SUSPEND: return "suspend"; - } - return "?"; -} - -/* dump control and status registers */ -static void ohci_dump_status(ohci_t *controller) -{ - struct ohci_regs *regs = controller->regs; - __u32 temp; - - temp = ohci_readl(®s->revision) & 0xff; - if (temp != 0x10) - dbg("spec %d.%d", (temp >> 4), (temp & 0x0f)); - - temp = ohci_readl(®s->control); - dbg("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, - (temp & OHCI_CTRL_RWE) ? " RWE" : "", - (temp & OHCI_CTRL_RWC) ? " RWC" : "", - (temp & OHCI_CTRL_IR) ? " IR" : "", - hcfs2string(temp & OHCI_CTRL_HCFS), - (temp & OHCI_CTRL_BLE) ? " BLE" : "", - (temp & OHCI_CTRL_CLE) ? " CLE" : "", - (temp & OHCI_CTRL_IE) ? " IE" : "", - (temp & OHCI_CTRL_PLE) ? " PLE" : "", - temp & OHCI_CTRL_CBSR - ); - - temp = ohci_readl(®s->cmdstatus); - dbg("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, - (temp & OHCI_SOC) >> 16, - (temp & OHCI_OCR) ? " OCR" : "", - (temp & OHCI_BLF) ? " BLF" : "", - (temp & OHCI_CLF) ? " CLF" : "", - (temp & OHCI_HCR) ? " HCR" : "" - ); - - ohci_dump_intr_mask("intrstatus", ohci_readl(®s->intrstatus)); - ohci_dump_intr_mask("intrenable", ohci_readl(®s->intrenable)); - - maybe_print_eds("ed_periodcurrent", - ohci_readl(®s->ed_periodcurrent)); - - maybe_print_eds("ed_controlhead", ohci_readl(®s->ed_controlhead)); - maybe_print_eds("ed_controlcurrent", - ohci_readl(®s->ed_controlcurrent)); - - maybe_print_eds("ed_bulkhead", ohci_readl(®s->ed_bulkhead)); - maybe_print_eds("ed_bulkcurrent", ohci_readl(®s->ed_bulkcurrent)); - - maybe_print_eds("donehead", ohci_readl(®s->donehead)); -} - -static void ohci_dump_roothub(ohci_t *controller, int verbose) -{ - __u32 temp, ndp, i; - - temp = roothub_a(controller); - ndp = (temp & RH_A_NDP); -#ifdef CONFIG_AT91C_PQFP_UHPBUG - ndp = (ndp == 2) ? 1:0; -#endif - if (verbose) { - dbg("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, - ((temp & RH_A_POTPGT) >> 24) & 0xff, - (temp & RH_A_NOCP) ? " NOCP" : "", - (temp & RH_A_OCPM) ? " OCPM" : "", - (temp & RH_A_DT) ? " DT" : "", - (temp & RH_A_NPS) ? " NPS" : "", - (temp & RH_A_PSM) ? " PSM" : "", - ndp - ); - temp = roothub_b(controller); - dbg("roothub.b: %08x PPCM=%04x DR=%04x", - temp, - (temp & RH_B_PPCM) >> 16, - (temp & RH_B_DR) - ); - temp = roothub_status(controller); - dbg("roothub.status: %08x%s%s%s%s%s%s", - temp, - (temp & RH_HS_CRWE) ? " CRWE" : "", - (temp & RH_HS_OCIC) ? " OCIC" : "", - (temp & RH_HS_LPSC) ? " LPSC" : "", - (temp & RH_HS_DRWE) ? " DRWE" : "", - (temp & RH_HS_OCI) ? " OCI" : "", - (temp & RH_HS_LPS) ? " LPS" : "" - ); - } - - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); - dbg("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", - i, - temp, - (temp & RH_PS_PRSC) ? " PRSC" : "", - (temp & RH_PS_OCIC) ? " OCIC" : "", - (temp & RH_PS_PSSC) ? " PSSC" : "", - (temp & RH_PS_PESC) ? " PESC" : "", - (temp & RH_PS_CSC) ? " CSC" : "", - - (temp & RH_PS_LSDA) ? " LSDA" : "", - (temp & RH_PS_PPS) ? " PPS" : "", - (temp & RH_PS_PRS) ? " PRS" : "", - (temp & RH_PS_POCI) ? " POCI" : "", - (temp & RH_PS_PSS) ? " PSS" : "", - - (temp & RH_PS_PES) ? " PES" : "", - (temp & RH_PS_CCS) ? " CCS" : "" - ); - } -} - -static void ohci_dump(ohci_t *controller, int verbose) -{ - dbg("OHCI controller usb-%s state", controller->slot_name); - - /* dumps some of the state we know about */ - ohci_dump_status(controller); - if (verbose) - ep_print_int_eds(controller, "hcca"); - dbg("hcca frame #%04x", controller->hcca->frame_no); - ohci_dump_roothub(controller, 1); -} -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------* - * Interface functions (URB) - *-------------------------------------------------------------------------*/ - -/* get a transfer request */ - -int sohci_submit_job(urb_priv_t *urb, struct devrequest *setup) -{ - ohci_t *ohci; - ed_t *ed; - urb_priv_t *purb_priv = urb; - int i, size = 0; - struct usb_device *dev = urb->dev; - unsigned long pipe = urb->pipe; - void *buffer = urb->transfer_buffer; - int transfer_len = urb->transfer_buffer_length; - int interval = urb->interval; - - ohci = &gohci; - - /* when controller's hung, permit only roothub cleanup attempts - * such as powering down ports */ - if (ohci->disabled) { - err("sohci_submit_job: EPIPE"); - return -1; - } - - /* we're about to begin a new transaction here so mark the - * URB unfinished */ - urb->finished = 0; - - /* every endpoint has a ed, locate and fill it */ - ed = ep_add_ed(dev, pipe, interval, 1); - if (!ed) { - err("sohci_submit_job: ENOMEM"); - return -1; - } - - /* for the private part of the URB we need the number of TDs (size) */ - switch (usb_pipetype(pipe)) { - case PIPE_BULK: /* one TD for every 4096 Byte */ - size = (transfer_len - 1) / 4096 + 1; - break; - case PIPE_CONTROL:/* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ - size = (transfer_len == 0)? 2: - (transfer_len - 1) / 4096 + 3; - break; - case PIPE_INTERRUPT: /* 1 TD */ - size = 1; - break; - } - - ed->purb = urb; - - if (size >= (N_URB_TD - 1)) { - err("need %d TDs, only have %d", size, N_URB_TD); - return -1; - } - purb_priv->pipe = pipe; - - /* fill the private part of the URB */ - purb_priv->length = size; - purb_priv->ed = ed; - purb_priv->actual_length = 0; - - /* allocate the TDs */ - /* note that td[0] was allocated in ep_add_ed */ - for (i = 0; i < size; i++) { - purb_priv->td[i] = td_alloc(dev); - if (!purb_priv->td[i]) { - purb_priv->length = i; - urb_free_priv(purb_priv); - err("sohci_submit_job: ENOMEM"); - return -1; - } - } - - if (ed->state == ED_NEW || (ed->state & ED_DEL)) { - urb_free_priv(purb_priv); - err("sohci_submit_job: EINVAL"); - return -1; - } - - /* link the ed into a chain if is not already */ - if (ed->state != ED_OPER) - ep_link(ohci, ed); - - /* fill the TDs and link it to the ed */ - td_submit_job(dev, pipe, buffer, transfer_len, - setup, purb_priv, interval); - - return 0; -} - -static inline int sohci_return_job(struct ohci *hc, urb_priv_t *urb) -{ - struct ohci_regs *regs = hc->regs; - - switch (usb_pipetype(urb->pipe)) { - case PIPE_INTERRUPT: - /* implicitly requeued */ - if (urb->dev->irq_handle && - (urb->dev->irq_act_len = urb->actual_length)) { - ohci_writel(OHCI_INTR_WDH, ®s->intrenable); - ohci_readl(®s->intrenable); /* PCI posting flush */ - urb->dev->irq_handle(urb->dev); - ohci_writel(OHCI_INTR_WDH, ®s->intrdisable); - ohci_readl(®s->intrdisable); /* PCI posting flush */ - } - urb->actual_length = 0; - td_submit_job( - urb->dev, - urb->pipe, - urb->transfer_buffer, - urb->transfer_buffer_length, - NULL, - urb, - urb->interval); - break; - case PIPE_CONTROL: - case PIPE_BULK: - break; - default: - return 0; - } - return 1; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -/* tell us the current USB frame number */ - -static int sohci_get_current_frame_number(struct usb_device *usb_dev) -{ - ohci_t *ohci = &gohci; - - return m16_swap(ohci->hcca->frame_no); -} -#endif - -/*-------------------------------------------------------------------------* - * ED handling functions - *-------------------------------------------------------------------------*/ - -/* search for the right branch to insert an interrupt ed into the int tree - * do some load ballancing; - * returns the branch and - * sets the interval to interval = 2^integer (ld (interval)) */ - -static int ep_int_ballance(ohci_t *ohci, int interval, int load) -{ - int i, branch = 0; - - /* search for the least loaded interrupt endpoint - * branch of all 32 branches - */ - for (i = 0; i < 32; i++) - if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) - branch = i; - - branch = branch % interval; - for (i = branch; i < 32; i += interval) - ohci->ohci_int_load [i] += load; - - return branch; -} - -/*-------------------------------------------------------------------------*/ - -/* 2^int( ld (inter)) */ - -static int ep_2_n_interval(int inter) -{ - int i; - for (i = 0; ((inter >> i) > 1) && (i < 5); i++); - return 1 << i; -} - -/*-------------------------------------------------------------------------*/ - -/* the int tree is a binary tree - * in order to process it sequentially the indexes of the branches have to - * be mapped the mapping reverses the bits of a word of num_bits length */ -static int ep_rev(int num_bits, int word) -{ - int i, wout = 0; - - for (i = 0; i < num_bits; i++) - wout |= (((word >> i) & 1) << (num_bits - i - 1)); - return wout; -} - -/*-------------------------------------------------------------------------* - * ED handling functions - *-------------------------------------------------------------------------*/ - -/* link an ed into one of the HC chains */ - -static int ep_link(ohci_t *ohci, ed_t *edi) -{ - volatile ed_t *ed = edi; - int int_branch; - int i; - int inter; - int interval; - int load; - __u32 *ed_p; - - ed->state = ED_OPER; - ed->int_interval = 0; - - switch (ed->type) { - case PIPE_CONTROL: - ed->hwNextED = 0; - if (ohci->ed_controltail == NULL) - ohci_writel(ed, &ohci->regs->ed_controlhead); - else - ohci->ed_controltail->hwNextED = - m32_swap((unsigned long)ed); - - ed->ed_prev = ohci->ed_controltail; - if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_CLE; - ohci_writel(ohci->hc_control, &ohci->regs->control); - } - ohci->ed_controltail = edi; - break; - - case PIPE_BULK: - ed->hwNextED = 0; - if (ohci->ed_bulktail == NULL) - ohci_writel(ed, &ohci->regs->ed_bulkhead); - else - ohci->ed_bulktail->hwNextED = - m32_swap((unsigned long)ed); - - ed->ed_prev = ohci->ed_bulktail; - if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_BLE; - ohci_writel(ohci->hc_control, &ohci->regs->control); - } - ohci->ed_bulktail = edi; - break; - - case PIPE_INTERRUPT: - load = ed->int_load; - interval = ep_2_n_interval(ed->int_period); - ed->int_interval = interval; - int_branch = ep_int_ballance(ohci, interval, load); - ed->int_branch = int_branch; - - for (i = 0; i < ep_rev(6, interval); i += inter) { - inter = 1; - for (ed_p = &(ohci->hcca->int_table[\ - ep_rev(5, i) + int_branch]); - (*ed_p != 0) && - (((ed_t *)ed_p)->int_interval >= interval); - ed_p = &(((ed_t *)ed_p)->hwNextED)) - inter = ep_rev(6, - ((ed_t *)ed_p)->int_interval); - ed->hwNextED = *ed_p; - *ed_p = m32_swap((unsigned long)ed); - } - break; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* scan the periodic table to find and unlink this ED */ -static void periodic_unlink(struct ohci *ohci, volatile struct ed *ed, - unsigned index, unsigned period) -{ - for (; index < NUM_INTS; index += period) { - __u32 *ed_p = &ohci->hcca->int_table [index]; - - /* ED might have been unlinked through another path */ - while (*ed_p != 0) { - if (((struct ed *) - m32_swap((unsigned long)ed_p)) == ed) { - *ed_p = ed->hwNextED; - break; - } - ed_p = &(((struct ed *) - m32_swap((unsigned long)ed_p))->hwNextED); - } - } -} - -/* unlink an ed from one of the HC chains. - * just the link to the ed is unlinked. - * the link from the ed still points to another operational ed or 0 - * so the HC can eventually finish the processing of the unlinked ed */ - -static int ep_unlink(ohci_t *ohci, ed_t *edi) -{ - volatile ed_t *ed = edi; - int i; - - ed->hwINFO |= m32_swap(OHCI_ED_SKIP); - - switch (ed->type) { - case PIPE_CONTROL: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_CLE; - ohci_writel(ohci->hc_control, - &ohci->regs->control); - } - ohci_writel(m32_swap(*((__u32 *)&ed->hwNextED)), - &ohci->regs->ed_controlhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_controltail == ed) { - ohci->ed_controltail = ed->ed_prev; - } else { - ((ed_t *)m32_swap( - *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; - } - break; - - case PIPE_BULK: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_BLE; - ohci_writel(ohci->hc_control, - &ohci->regs->control); - } - ohci_writel(m32_swap(*((__u32 *)&ed->hwNextED)), - &ohci->regs->ed_bulkhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_bulktail == ed) { - ohci->ed_bulktail = ed->ed_prev; - } else { - ((ed_t *)m32_swap( - *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; - } - break; - - case PIPE_INTERRUPT: - periodic_unlink(ohci, ed, 0, 1); - for (i = ed->int_branch; i < 32; i += ed->int_interval) - ohci->ohci_int_load[i] -= ed->int_load; - break; - } - ed->state = ED_UNLINK; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* add/reinit an endpoint; this should be done once at the - * usb_set_configuration command, but the USB stack is a little bit - * stateless so we do it at every transaction if the state of the ed - * is ED_NEW then a dummy td is added and the state is changed to - * ED_UNLINK in all other cases the state is left unchanged the ed - * info fields are setted anyway even though most of them should not - * change - */ -static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe, - int interval, int load) -{ - td_t *td; - ed_t *ed_ret; - volatile ed_t *ed; - - ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint(pipe) << 1) | - (usb_pipecontrol(pipe)? 0: usb_pipeout(pipe))]; - - if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { - err("ep_add_ed: pending delete"); - /* pending delete request */ - return NULL; - } - - if (ed->state == ED_NEW) { - /* dummy td; end of td list for ed */ - td = td_alloc(usb_dev); - ed->hwTailP = m32_swap((unsigned long)td); - ed->hwHeadP = ed->hwTailP; - ed->state = ED_UNLINK; - ed->type = usb_pipetype(pipe); - ohci_dev.ed_cnt++; - } - - ed->hwINFO = m32_swap(usb_pipedevice(pipe) - | usb_pipeendpoint(pipe) << 7 - | (usb_pipeisoc(pipe)? 0x8000: 0) - | (usb_pipecontrol(pipe)? 0: \ - (usb_pipeout(pipe)? 0x800: 0x1000)) - | (usb_dev->speed == USB_SPEED_LOW) << 13 - | usb_maxpacket(usb_dev, pipe) << 16); - - if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { - ed->int_period = interval; - ed->int_load = load; - } - - return ed_ret; -} - -/*-------------------------------------------------------------------------* - * TD handling functions - *-------------------------------------------------------------------------*/ - -/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ - -static void td_fill(ohci_t *ohci, unsigned int info, - void *data, int len, - struct usb_device *dev, int index, urb_priv_t *urb_priv) -{ - volatile td_t *td, *td_pt; -#ifdef OHCI_FILL_TRACE - int i; -#endif - - if (index > urb_priv->length) { - err("index > length"); - return; - } - /* use this td as the next dummy */ - td_pt = urb_priv->td [index]; - td_pt->hwNextTD = 0; - - /* fill the old dummy TD */ - td = urb_priv->td [index] = - (td_t *)(m32_swap(urb_priv->ed->hwTailP) & ~0xf); - - td->ed = urb_priv->ed; - td->next_dl_td = NULL; - td->index = index; - td->data = (__u32)data; -#ifdef OHCI_FILL_TRACE - if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) { - for (i = 0; i < len; i++) - printf("td->data[%d] %#2x ", i, ((unsigned char *)td->data)[i]); - printf("\n"); - } -#endif - if (!len) - data = 0; - - td->hwINFO = m32_swap(info); - td->hwCBP = m32_swap((unsigned long)data); - if (data) - td->hwBE = m32_swap((unsigned long)(data + len - 1)); - else - td->hwBE = 0; - - td->hwNextTD = m32_swap((unsigned long)td_pt); - - /* append to queue */ - td->ed->hwTailP = td->hwNextTD; -} - -/*-------------------------------------------------------------------------*/ - -/* prepare all TDs of a transfer */ - -static void td_submit_job(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *setup, urb_priv_t *urb, - int interval) -{ - ohci_t *ohci = &gohci; - int data_len = transfer_len; - void *data; - int cnt = 0; - __u32 info = 0; - unsigned int toggle = 0; - - /* OHCI handles the DATA-toggles itself, we just use the USB-toggle - * bits for reseting */ - if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { - toggle = TD_T_TOGGLE; - } else { - toggle = TD_T_DATA0; - usb_settoggle(dev, usb_pipeendpoint(pipe), - usb_pipeout(pipe), 1); - } - urb->td_cnt = 0; - if (data_len) - data = buffer; - else - data = 0; - - switch (usb_pipetype(pipe)) { - case PIPE_BULK: - info = usb_pipeout(pipe)? - TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; - while (data_len > 4096) { - td_fill(ohci, info | (cnt? TD_T_TOGGLE:toggle), - data, 4096, dev, cnt, urb); - data += 4096; data_len -= 4096; cnt++; - } - info = usb_pipeout(pipe)? - TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; - td_fill(ohci, info | (cnt? TD_T_TOGGLE:toggle), data, - data_len, dev, cnt, urb); - cnt++; - - if (!ohci->sleeping) { - /* start bulk list */ - ohci_writel(OHCI_BLF, &ohci->regs->cmdstatus); - } - break; - - case PIPE_CONTROL: - /* Setup phase */ - info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill(ohci, info, setup, 8, dev, cnt++, urb); - - /* Optional Data phase */ - if (data_len > 0) { - info = usb_pipeout(pipe)? - TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : - TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; - /* NOTE: mishandles transfers >8K, some >4K */ - td_fill(ohci, info, data, data_len, dev, cnt++, urb); - } - - /* Status phase */ - info = usb_pipeout(pipe)? - TD_CC | TD_DP_IN | TD_T_DATA1: - TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill(ohci, info, data, 0, dev, cnt++, urb); - - if (!ohci->sleeping) { - /* start Control list */ - ohci_writel(OHCI_CLF, &ohci->regs->cmdstatus); - } - break; - - case PIPE_INTERRUPT: - info = usb_pipeout(urb->pipe)? - TD_CC | TD_DP_OUT | toggle: - TD_CC | TD_R | TD_DP_IN | toggle; - td_fill(ohci, info, data, data_len, dev, cnt++, urb); - break; - } - if (urb->length != cnt) - dbg("TD LENGTH %d != CNT %d", urb->length, cnt); -} - -/*-------------------------------------------------------------------------* - * Done List handling functions - *-------------------------------------------------------------------------*/ - -/* calculate the transfer length and update the urb */ - -static void dl_transfer_length(td_t *td) -{ - __u32 tdBE, tdCBP; - urb_priv_t *lurb_priv = td->ed->purb; - - tdBE = m32_swap(td->hwBE); - tdCBP = m32_swap(td->hwCBP); - - if (!(usb_pipecontrol(lurb_priv->pipe) && - ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { - if (tdBE != 0) { - if (td->hwCBP == 0) - lurb_priv->actual_length += tdBE - td->data + 1; - else - lurb_priv->actual_length += tdCBP - td->data; - } - } -} - -/*-------------------------------------------------------------------------*/ -static void check_status(td_t *td_list) -{ - urb_priv_t *lurb_priv = td_list->ed->purb; - int urb_len = lurb_priv->length; - __u32 *phwHeadP = &td_list->ed->hwHeadP; - int cc; - - cc = TD_CC_GET(m32_swap(td_list->hwINFO)); - if (cc) { - err(" USB-error: %s (%x)", cc_to_string[cc], cc); - - if (*phwHeadP & m32_swap(0x1)) { - if (lurb_priv && - ((td_list->index + 1) < urb_len)) { - *phwHeadP = - (lurb_priv->td[urb_len - 1]->hwNextTD &\ - m32_swap(0xfffffff0)) | - (*phwHeadP & m32_swap(0x2)); - - lurb_priv->td_cnt += urb_len - - td_list->index - 1; - } else - *phwHeadP &= m32_swap(0xfffffff2); - } -#ifdef CONFIG_MPC5200 - td_list->hwNextTD = 0; -#endif - } -} - -/* replies to the request have to be on a FIFO basis so - * we reverse the reversed done-list */ -static td_t *dl_reverse_done_list(ohci_t *ohci) -{ - __u32 td_list_hc; - td_t *td_rev = NULL; - td_t *td_list = NULL; - - td_list_hc = m32_swap(ohci->hcca->done_head) & 0xfffffff0; - ohci->hcca->done_head = 0; - - while (td_list_hc) { - td_list = (td_t *)td_list_hc; - check_status(td_list); - td_list->next_dl_td = td_rev; - td_rev = td_list; - td_list_hc = m32_swap(td_list->hwNextTD) & 0xfffffff0; - } - return td_list; -} - -/*-------------------------------------------------------------------------*/ -/*-------------------------------------------------------------------------*/ - -static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status) -{ - if ((status & (ED_OPER | ED_UNLINK)) && (urb->state != URB_DEL)) - urb->finished = sohci_return_job(ohci, urb); - else - dbg("finish_urb: strange.., ED state %x, \n", status); -} - -/* - * Used to take back a TD from the host controller. This would normally be - * called from within dl_done_list, however it may be called directly if the - * HC no longer sees the TD and it has not appeared on the donelist (after - * two frames). This bug has been observed on ZF Micro systems. - */ -static int takeback_td(ohci_t *ohci, td_t *td_list) -{ - ed_t *ed; - int cc; - int stat = 0; - /* urb_t *urb; */ - urb_priv_t *lurb_priv; - __u32 tdINFO, edHeadP, edTailP; - - tdINFO = m32_swap(td_list->hwINFO); - - ed = td_list->ed; - lurb_priv = ed->purb; - - dl_transfer_length(td_list); - - lurb_priv->td_cnt++; - - /* error code of transfer */ - cc = TD_CC_GET(tdINFO); - if (cc) { - err("USB-error: %s (%x)", cc_to_string[cc], cc); - stat = cc_to_error[cc]; - } - - /* see if this done list makes for all TD's of current URB, - * and mark the URB finished if so */ - if (lurb_priv->td_cnt == lurb_priv->length) - finish_urb(ohci, lurb_priv, ed->state); - - dbg("dl_done_list: processing TD %x, len %x\n", - lurb_priv->td_cnt, lurb_priv->length); - - if (ed->state != ED_NEW && (!usb_pipeint(lurb_priv->pipe))) { - edHeadP = m32_swap(ed->hwHeadP) & 0xfffffff0; - edTailP = m32_swap(ed->hwTailP); - - /* unlink eds if they are not busy */ - if ((edHeadP == edTailP) && (ed->state == ED_OPER)) - ep_unlink(ohci, ed); - } - return stat; -} - -static int dl_done_list(ohci_t *ohci) -{ - int stat = 0; - td_t *td_list = dl_reverse_done_list(ohci); - - while (td_list) { - td_t *td_next = td_list->next_dl_td; - stat = takeback_td(ohci, td_list); - td_list = td_next; - } - return stat; -} - -/*-------------------------------------------------------------------------* - * Virtual Root Hub - *-------------------------------------------------------------------------*/ - -#include <usbroothubdes.h> - -/* Hub class-specific descriptor is constructed dynamically */ - -/*-------------------------------------------------------------------------*/ - -#define OK(x) len = (x); break -#ifdef DEBUG -#define WR_RH_STAT(x) {info("WR:status %#8x", (x)); ohci_writel((x), \ - &gohci.regs->roothub.status); } -#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, \ - (x)); ohci_writel((x), &gohci.regs->roothub.portstatus[wIndex-1]); } -#else -#define WR_RH_STAT(x) ohci_writel((x), &gohci.regs->roothub.status) -#define WR_RH_PORTSTAT(x) ohci_writel((x), \ - &gohci.regs->roothub.portstatus[wIndex-1]) -#endif -#define RD_RH_STAT roothub_status(&gohci) -#define RD_RH_PORTSTAT roothub_portstatus(&gohci, wIndex-1) - -/* request to virtual root hub */ - -int rh_check_port_status(ohci_t *controller) -{ - __u32 temp, ndp, i; - int res; - - res = -1; - temp = roothub_a(controller); - ndp = (temp & RH_A_NDP); -#ifdef CONFIG_AT91C_PQFP_UHPBUG - ndp = (ndp == 2) ? 1:0; -#endif - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); - /* check for a device disconnect */ - if (((temp & (RH_PS_PESC | RH_PS_CSC)) == - (RH_PS_PESC | RH_PS_CSC)) && - ((temp & RH_PS_CCS) == 0)) { - res = i; - break; - } - } - return res; -} - -static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, struct devrequest *cmd) -{ - void *data = buffer; - int leni = transfer_len; - int len = 0; - int stat = 0; - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - ALLOC_ALIGN_BUFFER(__u8, databuf, 16, sizeof(u32)); - -#ifdef DEBUG -pkt_print(NULL, dev, pipe, buffer, transfer_len, - cmd, "SUB(rh)", usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (usb_pipeint(pipe)) { - info("Root-Hub submit IRQ: NOT implemented"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = le16_to_cpu(cmd->value); - wIndex = le16_to_cpu(cmd->index); - wLength = le16_to_cpu(cmd->length); - - info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", - dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); - - switch (bmRType_bReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ - - case RH_GET_STATUS: - *(u16 *)databuf = cpu_to_le16(1); - OK(2); - case RH_GET_STATUS | RH_INTERFACE: - *(u16 *)databuf = cpu_to_le16(0); - OK(2); - case RH_GET_STATUS | RH_ENDPOINT: - *(u16 *)databuf = cpu_to_le16(0); - OK(2); - case RH_GET_STATUS | RH_CLASS: - *(u32 *)databuf = cpu_to_le32( - RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); - OK(4); - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - *(u32 *)databuf = cpu_to_le32(RD_RH_PORTSTAT); - OK(4); - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - switch (wValue) { - case (RH_ENDPOINT_STALL): - OK(0); - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - OK(0); - case (RH_C_HUB_OVER_CURRENT): - WR_RH_STAT(RH_HS_OCIC); - OK(0); - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_ENABLE): WR_RH_PORTSTAT(RH_PS_CCS); OK(0); - case (RH_PORT_SUSPEND): WR_RH_PORTSTAT(RH_PS_POCI); OK(0); - case (RH_PORT_POWER): WR_RH_PORTSTAT(RH_PS_LSDA); OK(0); - case (RH_C_PORT_CONNECTION): WR_RH_PORTSTAT(RH_PS_CSC); OK(0); - case (RH_C_PORT_ENABLE): WR_RH_PORTSTAT(RH_PS_PESC); OK(0); - case (RH_C_PORT_SUSPEND): WR_RH_PORTSTAT(RH_PS_PSSC); OK(0); - case (RH_C_PORT_OVER_CURRENT):WR_RH_PORTSTAT(RH_PS_OCIC); OK(0); - case (RH_C_PORT_RESET): WR_RH_PORTSTAT(RH_PS_PRSC); OK(0); - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT(RH_PS_PSS); OK(0); - case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT(RH_PS_PRS); - OK(0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT(RH_PS_PPS); - mdelay(100); - OK(0); - case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT(RH_PS_PES); - OK(0); - } - break; - - case RH_SET_ADDRESS: - gohci.rh.devnum = wValue; - OK(0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_dev_des), - wLength)); - databuf = root_hub_dev_des; OK(len); - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_config_des), - wLength)); - databuf = root_hub_config_des; OK(len); - case (0x03): /* string descriptors */ - if (wValue == 0x0300) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index0), - wLength)); - databuf = root_hub_str_index0; - OK(len); - } - if (wValue == 0x0301) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index1), - wLength)); - databuf = root_hub_str_index1; - OK(len); - } - default: - stat = USB_ST_STALLED; - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - { - __u32 temp = roothub_a(&gohci); - - databuf[0] = 9; /* min length; */ - databuf[1] = 0x29; - databuf[2] = temp & RH_A_NDP; -#ifdef CONFIG_AT91C_PQFP_UHPBUG - databuf[2] = (databuf[2] == 2) ? 1 : 0; -#endif - databuf[3] = 0; - if (temp & RH_A_PSM) /* per-port power switching? */ - databuf[3] |= 0x1; - if (temp & RH_A_NOCP) /* no overcurrent reporting? */ - databuf[3] |= 0x10; - else if (temp & RH_A_OCPM)/* per-port overcurrent reporting? */ - databuf[3] |= 0x8; - - databuf[4] = 0; - databuf[5] = (temp & RH_A_POTPGT) >> 24; - databuf[6] = 0; - temp = roothub_b(&gohci); - databuf[7] = temp & RH_B_DR; - if (databuf[2] < 7) { - databuf[8] = 0xff; - } else { - databuf[0] += 2; - databuf[8] = (temp & RH_B_DR) >> 8; - databuf[10] = databuf[9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, databuf[0], wLength)); - OK(len); - } - - case RH_GET_CONFIGURATION: - databuf[0] = 0x01; - OK(1); - - case RH_SET_CONFIGURATION: - WR_RH_STAT(0x10000); - OK(0); - - default: - dbg("unsupported root hub command"); - stat = USB_ST_STALLED; - } - -#ifdef DEBUG - ohci_dump_roothub(&gohci, 1); -#else - mdelay(1); -#endif - - len = min_t(int, len, leni); - if (data != databuf) - memcpy(data, databuf, len); - dev->act_len = len; - dev->status = stat; - -#ifdef DEBUG - pkt_print(NULL, dev, pipe, buffer, - transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); -#else - mdelay(1); -#endif - - return stat; -} - -/*-------------------------------------------------------------------------*/ - -/* common code for handling submit messages - used for all but root hub */ -/* accesses. */ -int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, int interval) -{ - int stat = 0; - int maxsize = usb_maxpacket(dev, pipe); - int timeout; - urb_priv_t *urb; - - urb = malloc(sizeof(urb_priv_t)); - memset(urb, 0, sizeof(urb_priv_t)); - - urb->dev = dev; - urb->pipe = pipe; - urb->transfer_buffer = buffer; - urb->transfer_buffer_length = transfer_len; - urb->interval = interval; - - /* device pulled? Shortcut the action. */ - if (devgone == dev) { - dev->status = USB_ST_CRC_ERR; - return 0; - } - -#ifdef DEBUG - urb->actual_length = 0; - pkt_print(urb, dev, pipe, buffer, transfer_len, - setup, "SUB", usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (!maxsize) { - err("submit_common_message: pipesize for pipe %lx is zero", - pipe); - return -1; - } - - if (sohci_submit_job(urb, setup) < 0) { - err("sohci_submit_job failed"); - return -1; - } - -#if 0 - mdelay(10); - /* ohci_dump_status(&gohci); */ -#endif - - timeout = USB_TIMEOUT_MS(pipe); - - /* wait for it to complete */ - for (;;) { - /* check whether the controller is done */ - stat = hc_interrupt(); - if (stat < 0) { - stat = USB_ST_CRC_ERR; - break; - } - - /* NOTE: since we are not interrupt driven in U-Boot and always - * handle only one URB at a time, we cannot assume the - * transaction finished on the first successful return from - * hc_interrupt().. unless the flag for current URB is set, - * meaning that all TD's to/from device got actually - * transferred and processed. If the current URB is not - * finished we need to re-iterate this loop so as - * hc_interrupt() gets called again as there needs to be some - * more TD's to process still */ - if ((stat >= 0) && (stat != 0xff) && (urb->finished)) { - /* 0xff is returned for an SF-interrupt */ - break; - } - - if (--timeout) { - mdelay(1); - if (!urb->finished) - dbg("*"); - - } else { - err("CTL:TIMEOUT "); - dbg("submit_common_msg: TO status %x\n", stat); - urb->finished = 1; - stat = USB_ST_CRC_ERR; - break; - } - } - - dev->status = stat; - dev->act_len = urb->actual_length; - -#ifdef DEBUG - pkt_print(urb, dev, pipe, buffer, transfer_len, - setup, "RET(ctlr)", usb_pipein(pipe)); -#else - mdelay(1); -#endif - - /* free TDs in urb_priv */ - if (!usb_pipeint(pipe)) - urb_free_priv(urb); - return 0; -} - -/* submit routines called from usb.c */ -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len) -{ - info("submit_bulk_msg"); - return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup) -{ - int maxsize = usb_maxpacket(dev, pipe); - - info("submit_control_msg"); -#ifdef DEBUG - pkt_print(NULL, dev, pipe, buffer, transfer_len, - setup, "SUB", usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (!maxsize) { - err("submit_control_message: pipesize for pipe %lx is zero", - pipe); - return -1; - } - if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) { - gohci.rh.dev = dev; - /* root hub - redirect */ - return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len, - setup); - } - - return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0); -} - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, int interval) -{ - info("submit_int_msg"); - return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, - interval); -} - -/*-------------------------------------------------------------------------* - * HC functions - *-------------------------------------------------------------------------*/ - -/* reset the HC and BUS */ - -static int hc_reset(ohci_t *ohci) -{ -#ifdef CONFIG_PCI_EHCI_DEVNO - pci_dev_t pdev; -#endif - int timeout = 30; - int smm_timeout = 50; /* 0,5 sec */ - - dbg("%s\n", __FUNCTION__); - -#ifdef CONFIG_PCI_EHCI_DEVNO - /* - * Some multi-function controllers (e.g. ISP1562) allow root hub - * resetting via EHCI registers only. - */ - pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVNO); - if (pdev != -1) { - u32 base; - int timeout = 1000; - - pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base); - base += EHCI_USBCMD_OFF; - ohci_writel(ohci_readl(base) | EHCI_USBCMD_HCRESET, base); - - while (ohci_readl(base) & EHCI_USBCMD_HCRESET) { - if (timeout-- <= 0) { - printf("USB RootHub reset timed out!"); - break; - } - udelay(1); - } - } else - printf("No EHCI func at %d index!\n", CONFIG_PCI_EHCI_DEVNO); -#endif - if (ohci_readl(&ohci->regs->control) & OHCI_CTRL_IR) { - /* SMM owns the HC, request ownership */ - ohci_writel(OHCI_OCR, &ohci->regs->cmdstatus); - info("USB HC TakeOver from SMM"); - while (ohci_readl(&ohci->regs->control) & OHCI_CTRL_IR) { - mdelay(10); - if (--smm_timeout == 0) { - err("USB HC TakeOver failed!"); - return -1; - } - } - } - - /* Disable HC interrupts */ - ohci_writel(OHCI_INTR_MIE, &ohci->regs->intrdisable); - - dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;\n", - ohci->slot_name, - ohci_readl(&ohci->regs->control)); - - /* Reset USB (needed by some controllers) */ - ohci->hc_control = 0; - ohci_writel(ohci->hc_control, &ohci->regs->control); - - /* HC Reset requires max 10 us delay */ - ohci_writel(OHCI_HCR, &ohci->regs->cmdstatus); - while ((ohci_readl(&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { - if (--timeout == 0) { - err("USB HC reset timed out!"); - return -1; - } - udelay(1); - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* Start an OHCI controller, set the BUS operational - * enable interrupts - * connect the virtual root hub */ - -static int hc_start(ohci_t *ohci) -{ - __u32 mask; - unsigned int fminterval; - - ohci->disabled = 1; - - /* Tell the controller where the control and bulk lists are - * The lists are empty now. */ - - ohci_writel(0, &ohci->regs->ed_controlhead); - ohci_writel(0, &ohci->regs->ed_bulkhead); - - ohci_writel((__u32)ohci->hcca, - &ohci->regs->hcca); /* reset clears this */ - - fminterval = 0x2edf; - ohci_writel((fminterval * 9) / 10, &ohci->regs->periodicstart); - fminterval |= ((((fminterval - 210) * 6) / 7) << 16); - ohci_writel(fminterval, &ohci->regs->fminterval); - ohci_writel(0x628, &ohci->regs->lsthresh); - - /* start controller operations */ - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; - ohci->disabled = 0; - ohci_writel(ohci->hc_control, &ohci->regs->control); - - /* disable all interrupts */ - mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | - OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | - OHCI_INTR_OC | OHCI_INTR_MIE); - ohci_writel(mask, &ohci->regs->intrdisable); - /* clear all interrupts */ - mask &= ~OHCI_INTR_MIE; - ohci_writel(mask, &ohci->regs->intrstatus); - /* Choose the interrupts we care about now - but w/o MIE */ - mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; - ohci_writel(mask, &ohci->regs->intrenable); - -#ifdef OHCI_USE_NPS - /* required for AMD-756 and some Mac platforms */ - ohci_writel((roothub_a(ohci) | RH_A_NPS) & ~RH_A_PSM, - &ohci->regs->roothub.a); - ohci_writel(RH_HS_LPSC, &ohci->regs->roothub.status); -#endif /* OHCI_USE_NPS */ - - /* POTPGT delay is bits 24-31, in 2 ms units. */ - mdelay((roothub_a(ohci) >> 23) & 0x1fe); - - /* connect the virtual root hub */ - ohci->rh.devnum = 0; - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* an interrupt happens */ - -static int hc_interrupt(void) -{ - ohci_t *ohci = &gohci; - struct ohci_regs *regs = ohci->regs; - int ints; - int stat = -1; - - if ((ohci->hcca->done_head != 0) && - !(m32_swap(ohci->hcca->done_head) & 0x01)) { - ints = OHCI_INTR_WDH; - } else { - ints = ohci_readl(®s->intrstatus); - if (ints == ~(u32)0) { - ohci->disabled++; - err("%s device removed!", ohci->slot_name); - return -1; - } else { - ints &= ohci_readl(®s->intrenable); - if (ints == 0) { - dbg("hc_interrupt: returning..\n"); - return 0xff; - } - } - } - - /* dbg("Interrupt: %x frame: %x", ints, - le16_to_cpu(ohci->hcca->frame_no)); */ - - if (ints & OHCI_INTR_RHSC) - stat = 0xff; - - if (ints & OHCI_INTR_UE) { - ohci->disabled++; - err("OHCI Unrecoverable Error, controller usb-%s disabled", - ohci->slot_name); - /* e.g. due to PCI Master/Target Abort */ - -#ifdef DEBUG - ohci_dump(ohci, 1); -#else - mdelay(1); -#endif - /* FIXME: be optimistic, hope that bug won't repeat often. */ - /* Make some non-interrupt context restart the controller. */ - /* Count and limit the retries though; either hardware or */ - /* software errors can go forever... */ - hc_reset(ohci); - return -1; - } - - if (ints & OHCI_INTR_WDH) { - mdelay(1); - ohci_writel(OHCI_INTR_WDH, ®s->intrdisable); - (void)ohci_readl(®s->intrdisable); /* flush */ - stat = dl_done_list(&gohci); - ohci_writel(OHCI_INTR_WDH, ®s->intrenable); - (void)ohci_readl(®s->intrdisable); /* flush */ - } - - if (ints & OHCI_INTR_SO) { - dbg("USB Schedule overrun\n"); - ohci_writel(OHCI_INTR_SO, ®s->intrenable); - stat = -1; - } - - /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ - if (ints & OHCI_INTR_SF) { - unsigned int frame = m16_swap(ohci->hcca->frame_no) & 1; - mdelay(1); - ohci_writel(OHCI_INTR_SF, ®s->intrdisable); - if (ohci->ed_rm_list[frame] != NULL) - ohci_writel(OHCI_INTR_SF, ®s->intrenable); - stat = 0xff; - } - - ohci_writel(ints, ®s->intrstatus); - return stat; -} - -/*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------------------*/ - -/* De-allocate all resources.. */ - -static void hc_release_ohci(ohci_t *ohci) -{ - dbg("USB HC release ohci usb-%s", ohci->slot_name); - - if (!ohci->disabled) - hc_reset(ohci); -} - -/*-------------------------------------------------------------------------*/ - -/* - * low level initalisation routine, called from usb.c - */ -static char ohci_inited = 0; - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ -#ifdef CONFIG_PCI_OHCI - pci_dev_t pdev; -#endif - -#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT - /* cpu dependant init */ - if (usb_cpu_init()) - return -1; -#endif - -#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT - /* board dependant init */ - if (board_usb_init(index, USB_INIT_HOST)) - return -1; -#endif - memset(&gohci, 0, sizeof(ohci_t)); - - /* align the storage */ - if ((__u32)&ghcca[0] & 0xff) { - err("HCCA not aligned!!"); - return -1; - } - phcca = &ghcca[0]; - info("aligned ghcca %p", phcca); - memset(&ohci_dev, 0, sizeof(struct ohci_device)); - if ((__u32)&ohci_dev.ed[0] & 0x7) { - err("EDs not aligned!!"); - return -1; - } - memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1)); - if ((__u32)gtd & 0x7) { - err("TDs not aligned!!"); - return -1; - } - ptd = gtd; - gohci.hcca = phcca; - memset(phcca, 0, sizeof(struct ohci_hcca)); - - gohci.disabled = 1; - gohci.sleeping = 0; - gohci.irq = -1; -#ifdef CONFIG_PCI_OHCI - pdev = pci_find_devices(ohci_pci_ids, CONFIG_PCI_OHCI_DEVNO); - - if (pdev != -1) { - u16 vid, did; - u32 base; - pci_read_config_word(pdev, PCI_VENDOR_ID, &vid); - pci_read_config_word(pdev, PCI_DEVICE_ID, &did); - printf("OHCI pci controller (%04x, %04x) found @(%d:%d:%d)\n", - vid, did, (pdev >> 16) & 0xff, - (pdev >> 11) & 0x1f, (pdev >> 8) & 0x7); - pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base); - printf("OHCI regs address 0x%08x\n", base); - gohci.regs = (struct ohci_regs *)base; - } else - return -1; -#else - gohci.regs = (struct ohci_regs *)CONFIG_SYS_USB_OHCI_REGS_BASE; -#endif - - gohci.flags = 0; - gohci.slot_name = CONFIG_SYS_USB_OHCI_SLOT_NAME; - - if (hc_reset (&gohci) < 0) { - hc_release_ohci (&gohci); - err ("can't reset usb-%s", gohci.slot_name); -#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT - /* board dependant cleanup */ - board_usb_cleanup(index, USB_INIT_HOST); -#endif - -#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT - /* cpu dependant cleanup */ - usb_cpu_init_fail(); -#endif - return -1; - } - - if (hc_start(&gohci) < 0) { - err("can't start usb-%s", gohci.slot_name); - hc_release_ohci(&gohci); - /* Initialization failed */ -#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT - /* board dependant cleanup */ - usb_board_stop(); -#endif - -#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT - /* cpu dependant cleanup */ - usb_cpu_stop(); -#endif - return -1; - } - -#ifdef DEBUG - ohci_dump(&gohci, 1); -#else - mdelay(1); -#endif - ohci_inited = 1; - return 0; -} - -int usb_lowlevel_stop(int index) -{ - /* this gets called really early - before the controller has */ - /* even been initialized! */ - if (!ohci_inited) - return 0; - /* TODO release any interrupts, etc. */ - /* call hc_release_ohci() here ? */ - hc_reset(&gohci); - -#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT - /* board dependant cleanup */ - if (usb_board_stop()) - return -1; -#endif - -#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT - /* cpu dependant cleanup */ - if (usb_cpu_stop()) - return -1; -#endif - /* This driver is no longer initialised. It needs a new low-level - * init (board/cpu) before it can be used again. */ - ohci_inited = 0; - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.c b/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.c deleted file mode 100644 index 3c659c60c..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.c +++ /dev/null @@ -1,1691 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB on the S3C2400. - * - * (C) Copyright 2003 - * Gary Jennejohn, DENX Software Engineering <garyj@denx.de> - * - * Note: Much of this code has been derived from Linux 2.4 - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell - * - * SPDX-License-Identifier: GPL-2.0+ - */ -/* - * IMPORTANT NOTES - * 1 - this driver is intended for use with USB Mass Storage Devices - * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes! - */ - -#include <common.h> -/* #include <pci.h> no PCI on the S3C24X0 */ - -#if defined(CONFIG_USB_OHCI) && defined(CONFIG_S3C24X0) - -#include <asm/arch/s3c24x0_cpu.h> -#include <asm/io.h> -#include <malloc.h> -#include <usb.h> -#include "ohci-s3c24xx.h" - -#define OHCI_USE_NPS /* force NoPowerSwitching mode */ -#undef OHCI_VERBOSE_DEBUG /* not always helpful */ - - -/* For initializing controller (mask in an HCFS mode too) */ -#define OHCI_CONTROL_INIT \ - (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE - -#define min_t(type, x, y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; }) - -#undef DEBUG -#ifdef DEBUG -#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) -#else -#define dbg(format, arg...) do {} while(0) -#endif /* DEBUG */ -#define err(format, arg...) printf("ERROR: " format "\n", ## arg) -#undef SHOW_INFO -#ifdef SHOW_INFO -#define info(format, arg...) printf("INFO: " format "\n", ## arg) -#else -#define info(format, arg...) do {} while(0) -#endif - -#define m16_swap(x) swap_16(x) -#define m32_swap(x) swap_32(x) - -/* global struct ohci */ -static struct ohci gohci; -/* this must be aligned to a 256 byte boundary */ -struct ohci_hcca ghcca[1]; -/* a pointer to the aligned storage */ -struct ohci_hcca *phcca; -/* this allocates EDs for all possible endpoints */ -struct ohci_device ohci_dev; -/* urb_priv */ -struct urb_priv urb_priv; -/* RHSC flag */ -int got_rhsc; -/* device which was disconnected */ -struct usb_device *devgone; -/* flag guarding URB transation */ -int urb_finished = 0; - -/*-------------------------------------------------------------------------*/ - -/* AMD-756 (D2 rev) reports corrupt register contents in some cases. - * The erratum (#4) description is incorrect. AMD's workaround waits - * till some bits (mostly reserved) are clear; ok for all revs. - */ -#define OHCI_QUIRK_AMD756 0xabcd -#define read_roothub(hc, register, mask) ({ \ - u32 temp = readl (&hc->regs->roothub.register); \ - if (hc->flags & OHCI_QUIRK_AMD756) \ - while (temp & mask) \ - temp = readl (&hc->regs->roothub.register); \ - temp; }) - -static u32 roothub_a(struct ohci *hc) -{ - return read_roothub(hc, a, 0xfc0fe000); -} -static inline u32 roothub_b(struct ohci *hc) -{ - return readl(&hc->regs->roothub.b); -} -static inline u32 roothub_status(struct ohci *hc) -{ - return readl(&hc->regs->roothub.status); -} -static u32 roothub_portstatus(struct ohci *hc, int i) -{ - return read_roothub(hc, portstatus[i], 0xffe0fce0); -} - -/* forward declaration */ -static int hc_interrupt(void); -static void td_submit_job(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *setup, struct urb_priv *urb, - int interval); - -/*-------------------------------------------------------------------------* - * URB support functions - *-------------------------------------------------------------------------*/ - -/* free HCD-private data associated with this URB */ - -static void urb_free_priv(struct urb_priv *urb) -{ - int i; - int last; - struct td *td; - - last = urb->length - 1; - if (last >= 0) { - for (i = 0; i <= last; i++) { - td = urb->td[i]; - if (td) { - td->usb_dev = NULL; - urb->td[i] = NULL; - } - } - } -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -static int sohci_get_current_frame_number(struct usb_device *dev); - -/* debug| print the main components of an URB - * small: 0) header + data packets 1) just header */ - -static void pkt_print(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, char *str, - int small) -{ - struct urb_priv *purb = &urb_priv; - - dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx", - str, - sohci_get_current_frame_number(dev), - usb_pipedevice(pipe), - usb_pipeendpoint(pipe), - usb_pipeout(pipe) ? 'O' : 'I', - usb_pipetype(pipe) < 2 ? - (usb_pipeint(pipe) ? "INTR" : "ISOC") : - (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), - purb->actual_length, transfer_len, dev->status); -#ifdef OHCI_VERBOSE_DEBUG - if (!small) { - int i, len; - - if (usb_pipecontrol(pipe)) { - printf(__FILE__ ": cmd(8):"); - for (i = 0; i < 8; i++) - printf(" %02x", ((__u8 *) setup)[i]); - printf("\n"); - } - if (transfer_len > 0 && buffer) { - printf(__FILE__ ": data(%d/%d):", - purb->actual_length, transfer_len); - len = usb_pipeout(pipe) ? - transfer_len : purb->actual_length; - for (i = 0; i < 16 && i < len; i++) - printf(" %02x", ((__u8 *) buffer)[i]); - printf("%s\n", i < len ? "..." : ""); - } - } -#endif -} - -/* just for debugging; prints non-empty branches of the - int ed tree inclusive iso eds*/ -void ep_print_int_eds(struct ohci *ohci, char *str) -{ - int i, j; - __u32 *ed_p; - for (i = 0; i < 32; i++) { - j = 5; - ed_p = &(ohci->hcca->int_table[i]); - if (*ed_p == 0) - continue; - printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i); - while (*ed_p != 0 && j--) { - struct ed *ed = (struct ed *) m32_swap(ed_p); - printf(" ed: %4x;", ed->hwINFO); - ed_p = &ed->hwNextED; - } - printf("\n"); - } -} - -static void ohci_dump_intr_mask(char *label, __u32 mask) -{ - dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s", - label, - mask, - (mask & OHCI_INTR_MIE) ? " MIE" : "", - (mask & OHCI_INTR_OC) ? " OC" : "", - (mask & OHCI_INTR_RHSC) ? " RHSC" : "", - (mask & OHCI_INTR_FNO) ? " FNO" : "", - (mask & OHCI_INTR_UE) ? " UE" : "", - (mask & OHCI_INTR_RD) ? " RD" : "", - (mask & OHCI_INTR_SF) ? " SF" : "", - (mask & OHCI_INTR_WDH) ? " WDH" : "", - (mask & OHCI_INTR_SO) ? " SO" : ""); -} - -static void maybe_print_eds(char *label, __u32 value) -{ - struct ed *edp = (struct ed *) value; - - if (value) { - dbg("%s %08x", label, value); - dbg("%08x", edp->hwINFO); - dbg("%08x", edp->hwTailP); - dbg("%08x", edp->hwHeadP); - dbg("%08x", edp->hwNextED); - } -} - -static char *hcfs2string(int state) -{ - switch (state) { - case OHCI_USB_RESET: - return "reset"; - case OHCI_USB_RESUME: - return "resume"; - case OHCI_USB_OPER: - return "operational"; - case OHCI_USB_SUSPEND: - return "suspend"; - } - return "?"; -} - -/* dump control and status registers */ -static void ohci_dump_status(struct ohci *controller) -{ - struct ohci_regs *regs = controller->regs; - __u32 temp; - - temp = readl(®s->revision) & 0xff; - if (temp != 0x10) - dbg("spec %d.%d", (temp >> 4), (temp & 0x0f)); - - temp = readl(®s->control); - dbg("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, - (temp & OHCI_CTRL_RWE) ? " RWE" : "", - (temp & OHCI_CTRL_RWC) ? " RWC" : "", - (temp & OHCI_CTRL_IR) ? " IR" : "", - hcfs2string(temp & OHCI_CTRL_HCFS), - (temp & OHCI_CTRL_BLE) ? " BLE" : "", - (temp & OHCI_CTRL_CLE) ? " CLE" : "", - (temp & OHCI_CTRL_IE) ? " IE" : "", - (temp & OHCI_CTRL_PLE) ? " PLE" : "", temp & OHCI_CTRL_CBSR); - - temp = readl(®s->cmdstatus); - dbg("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, - (temp & OHCI_SOC) >> 16, - (temp & OHCI_OCR) ? " OCR" : "", - (temp & OHCI_BLF) ? " BLF" : "", - (temp & OHCI_CLF) ? " CLF" : "", (temp & OHCI_HCR) ? " HCR" : ""); - - ohci_dump_intr_mask("intrstatus", readl(®s->intrstatus)); - ohci_dump_intr_mask("intrenable", readl(®s->intrenable)); - - maybe_print_eds("ed_periodcurrent", readl(®s->ed_periodcurrent)); - - maybe_print_eds("ed_controlhead", readl(®s->ed_controlhead)); - maybe_print_eds("ed_controlcurrent", readl(®s->ed_controlcurrent)); - - maybe_print_eds("ed_bulkhead", readl(®s->ed_bulkhead)); - maybe_print_eds("ed_bulkcurrent", readl(®s->ed_bulkcurrent)); - - maybe_print_eds("donehead", readl(®s->donehead)); -} - -static void ohci_dump_roothub(struct ohci *controller, int verbose) -{ - __u32 temp, ndp, i; - - temp = roothub_a(controller); - ndp = (temp & RH_A_NDP); - - if (verbose) { - dbg("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, - ((temp & RH_A_POTPGT) >> 24) & 0xff, - (temp & RH_A_NOCP) ? " NOCP" : "", - (temp & RH_A_OCPM) ? " OCPM" : "", - (temp & RH_A_DT) ? " DT" : "", - (temp & RH_A_NPS) ? " NPS" : "", - (temp & RH_A_PSM) ? " PSM" : "", ndp); - temp = roothub_b(controller); - dbg("roothub.b: %08x PPCM=%04x DR=%04x", - temp, (temp & RH_B_PPCM) >> 16, (temp & RH_B_DR) - ); - temp = roothub_status(controller); - dbg("roothub.status: %08x%s%s%s%s%s%s", - temp, - (temp & RH_HS_CRWE) ? " CRWE" : "", - (temp & RH_HS_OCIC) ? " OCIC" : "", - (temp & RH_HS_LPSC) ? " LPSC" : "", - (temp & RH_HS_DRWE) ? " DRWE" : "", - (temp & RH_HS_OCI) ? " OCI" : "", - (temp & RH_HS_LPS) ? " LPS" : ""); - } - - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); - dbg("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", - i, - temp, - (temp & RH_PS_PRSC) ? " PRSC" : "", - (temp & RH_PS_OCIC) ? " OCIC" : "", - (temp & RH_PS_PSSC) ? " PSSC" : "", - (temp & RH_PS_PESC) ? " PESC" : "", - (temp & RH_PS_CSC) ? " CSC" : "", - (temp & RH_PS_LSDA) ? " LSDA" : "", - (temp & RH_PS_PPS) ? " PPS" : "", - (temp & RH_PS_PRS) ? " PRS" : "", - (temp & RH_PS_POCI) ? " POCI" : "", - (temp & RH_PS_PSS) ? " PSS" : "", - (temp & RH_PS_PES) ? " PES" : "", - (temp & RH_PS_CCS) ? " CCS" : ""); - } -} - -static void ohci_dump(struct ohci *controller, int verbose) -{ - dbg("OHCI controller usb-%s state", controller->slot_name); - - /* dumps some of the state we know about */ - ohci_dump_status(controller); - if (verbose) - ep_print_int_eds(controller, "hcca"); - dbg("hcca frame #%04x", controller->hcca->frame_no); - ohci_dump_roothub(controller, 1); -} - -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------* - * Interface functions (URB) - *-------------------------------------------------------------------------*/ - -/* get a transfer request */ - -int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, int interval) -{ - struct ohci *ohci; - struct ed *ed; - struct urb_priv *purb_priv; - int i, size = 0; - - ohci = &gohci; - - /* when controller's hung, permit only roothub cleanup attempts - * such as powering down ports */ - if (ohci->disabled) { - err("sohci_submit_job: EPIPE"); - return -1; - } - - /* if we have an unfinished URB from previous transaction let's - * fail and scream as quickly as possible so as not to corrupt - * further communication */ - if (!urb_finished) { - err("sohci_submit_job: URB NOT FINISHED"); - return -1; - } - /* we're about to begin a new transaction here - so mark the URB unfinished */ - urb_finished = 0; - - /* every endpoint has a ed, locate and fill it */ - ed = ep_add_ed(dev, pipe); - if (!ed) { - err("sohci_submit_job: ENOMEM"); - return -1; - } - - /* for the private part of the URB we need the number of TDs (size) */ - switch (usb_pipetype(pipe)) { - case PIPE_BULK: - /* one TD for every 4096 Byte */ - size = (transfer_len - 1) / 4096 + 1; - break; - case PIPE_CONTROL: - /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ - size = (transfer_len == 0) ? 2 : (transfer_len - 1) / 4096 + 3; - break; - } - - if (size >= (N_URB_TD - 1)) { - err("need %d TDs, only have %d", size, N_URB_TD); - return -1; - } - purb_priv = &urb_priv; - purb_priv->pipe = pipe; - - /* fill the private part of the URB */ - purb_priv->length = size; - purb_priv->ed = ed; - purb_priv->actual_length = 0; - - /* allocate the TDs */ - /* note that td[0] was allocated in ep_add_ed */ - for (i = 0; i < size; i++) { - purb_priv->td[i] = td_alloc(dev); - if (!purb_priv->td[i]) { - purb_priv->length = i; - urb_free_priv(purb_priv); - err("sohci_submit_job: ENOMEM"); - return -1; - } - } - - if (ed->state == ED_NEW || (ed->state & ED_DEL)) { - urb_free_priv(purb_priv); - err("sohci_submit_job: EINVAL"); - return -1; - } - - /* link the ed into a chain if is not already */ - if (ed->state != ED_OPER) - ep_link(ohci, ed); - - /* fill the TDs and link it to the ed */ - td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, - interval); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -/* tell us the current USB frame number */ - -static int sohci_get_current_frame_number(struct usb_device *usb_dev) -{ - struct ohci *ohci = &gohci; - - return m16_swap(ohci->hcca->frame_no); -} -#endif - -/*-------------------------------------------------------------------------* - * ED handling functions - *-------------------------------------------------------------------------*/ - -/* link an ed into one of the HC chains */ - -static int ep_link(struct ohci *ohci, struct ed *edi) -{ - struct ed *ed = edi; - - ed->state = ED_OPER; - - switch (ed->type) { - case PIPE_CONTROL: - ed->hwNextED = 0; - if (ohci->ed_controltail == NULL) { - writel((u32)ed, &ohci->regs->ed_controlhead); - } else { - ohci->ed_controltail->hwNextED = (__u32) m32_swap(ed); - } - ed->ed_prev = ohci->ed_controltail; - if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_CLE; - writel(ohci->hc_control, &ohci->regs->control); - } - ohci->ed_controltail = edi; - break; - - case PIPE_BULK: - ed->hwNextED = 0; - if (ohci->ed_bulktail == NULL) { - writel((u32)ed, &ohci->regs->ed_bulkhead); - } else { - ohci->ed_bulktail->hwNextED = (__u32) m32_swap(ed); - } - ed->ed_prev = ohci->ed_bulktail; - if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_BLE; - writel(ohci->hc_control, &ohci->regs->control); - } - ohci->ed_bulktail = edi; - break; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* unlink an ed from one of the HC chains. - * just the link to the ed is unlinked. - * the link from the ed still points to another operational ed or 0 - * so the HC can eventually finish the processing of the unlinked ed */ - -static int ep_unlink(struct ohci *ohci, struct ed *ed) -{ - struct ed *next; - ed->hwINFO |= m32_swap(OHCI_ED_SKIP); - - switch (ed->type) { - case PIPE_CONTROL: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_CLE; - writel(ohci->hc_control, &ohci->regs->control); - } - writel(m32_swap(*((__u32 *) &ed->hwNextED)), - &ohci->regs->ed_controlhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_controltail == ed) { - ohci->ed_controltail = ed->ed_prev; - } else { - next = (struct ed *)m32_swap(*((__u32 *)&ed->hwNextED)); - next->ed_prev = ed->ed_prev; - } - break; - - case PIPE_BULK: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_BLE; - writel(ohci->hc_control, &ohci->regs->control); - } - writel(m32_swap(*((__u32 *) &ed->hwNextED)), - &ohci->regs->ed_bulkhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_bulktail == ed) { - ohci->ed_bulktail = ed->ed_prev; - } else { - next = (struct ed *)m32_swap(*((__u32 *)&ed->hwNextED)); - next->ed_prev = ed->ed_prev; - } - break; - } - ed->state = ED_UNLINK; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* add/reinit an endpoint; this should be done once at the usb_set_configuration - * command, but the USB stack is a little bit stateless so we do it at every - * transaction. If the state of the ed is ED_NEW then a dummy td is added and - * the state is changed to ED_UNLINK. In all other cases the state is left - * unchanged. The ed info fields are setted anyway even though most of them - * should not change */ - -static struct ed *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe) -{ - struct td *td; - struct ed *ed_ret; - struct ed *ed; - - ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint(pipe) << 1) | - (usb_pipecontrol(pipe) ? 0 : - usb_pipeout(pipe))]; - - if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { - err("ep_add_ed: pending delete"); - /* pending delete request */ - return NULL; - } - - if (ed->state == ED_NEW) { - ed->hwINFO = m32_swap(OHCI_ED_SKIP); /* skip ed */ - /* dummy td; end of td list for ed */ - td = td_alloc(usb_dev); - ed->hwTailP = (__u32) m32_swap(td); - ed->hwHeadP = ed->hwTailP; - ed->state = ED_UNLINK; - ed->type = usb_pipetype(pipe); - ohci_dev.ed_cnt++; - } - - ed->hwINFO = m32_swap(usb_pipedevice(pipe) - | usb_pipeendpoint(pipe) << 7 - | (usb_pipeisoc(pipe) ? 0x8000 : 0) - | (usb_pipecontrol(pipe) ? 0 : - (usb_pipeout(pipe) ? 0x800 : 0x1000)) - | (usb_dev->speed == USB_SPEED_LOW) << 13 | - usb_maxpacket(usb_dev, pipe) << 16); - - return ed_ret; -} - -/*-------------------------------------------------------------------------* - * TD handling functions - *-------------------------------------------------------------------------*/ - -/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ - -static void td_fill(struct ohci *ohci, unsigned int info, void *data, int len, - struct usb_device *dev, int index, - struct urb_priv *urb_priv) -{ - struct td *td, *td_pt; -#ifdef OHCI_FILL_TRACE - int i; -#endif - - if (index > urb_priv->length) { - err("index > length"); - return; - } - /* use this td as the next dummy */ - td_pt = urb_priv->td[index]; - td_pt->hwNextTD = 0; - - /* fill the old dummy TD */ - td = urb_priv->td[index] = - (struct td *) (m32_swap(urb_priv->ed->hwTailP) & ~0xf); - - td->ed = urb_priv->ed; - td->next_dl_td = NULL; - td->index = index; - td->data = (__u32) data; -#ifdef OHCI_FILL_TRACE - if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) { - for (i = 0; i < len; i++) - printf("td->data[%d] %#2x ", i, - ((unsigned char *)td->data)[i]); - printf("\n"); - } -#endif - if (!len) - data = 0; - - td->hwINFO = (__u32) m32_swap(info); - td->hwCBP = (__u32) m32_swap(data); - if (data) - td->hwBE = (__u32) m32_swap(data + len - 1); - else - td->hwBE = 0; - td->hwNextTD = (__u32) m32_swap(td_pt); - - /* append to queue */ - td->ed->hwTailP = td->hwNextTD; -} - -/*-------------------------------------------------------------------------*/ - -/* prepare all TDs of a transfer */ - -static void td_submit_job(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *setup, struct urb_priv *urb, - int interval) -{ - struct ohci *ohci = &gohci; - int data_len = transfer_len; - void *data; - int cnt = 0; - __u32 info = 0; - unsigned int toggle = 0; - - /* OHCI handles the DATA-toggles itself, we just - use the USB-toggle bits for reseting */ - if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { - toggle = TD_T_TOGGLE; - } else { - toggle = TD_T_DATA0; - usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), - 1); - } - urb->td_cnt = 0; - if (data_len) - data = buffer; - else - data = 0; - - switch (usb_pipetype(pipe)) { - case PIPE_BULK: - info = usb_pipeout(pipe) ? TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN; - while (data_len > 4096) { - td_fill(ohci, info | (cnt ? TD_T_TOGGLE : toggle), data, - 4096, dev, cnt, urb); - data += 4096; - data_len -= 4096; - cnt++; - } - info = usb_pipeout(pipe) ? - TD_CC | TD_DP_OUT : - TD_CC | TD_R | TD_DP_IN; - td_fill(ohci, info | (cnt ? TD_T_TOGGLE : toggle), data, - data_len, dev, cnt, urb); - cnt++; - - if (!ohci->sleeping) - /* start bulk list */ - writel(OHCI_BLF, &ohci->regs->cmdstatus); - break; - - case PIPE_CONTROL: - info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill(ohci, info, setup, 8, dev, cnt++, urb); - if (data_len > 0) { - info = usb_pipeout(pipe) ? - TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : - TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; - /* NOTE: mishandles transfers >8K, some >4K */ - td_fill(ohci, info, data, data_len, dev, cnt++, urb); - } - info = usb_pipeout(pipe) ? - TD_CC | TD_DP_IN | TD_T_DATA1 : - TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill(ohci, info, data, 0, dev, cnt++, urb); - if (!ohci->sleeping) - /* start Control list */ - writel(OHCI_CLF, &ohci->regs->cmdstatus); - break; - } - if (urb->length != cnt) - dbg("TD LENGTH %d != CNT %d", urb->length, cnt); -} - -/*-------------------------------------------------------------------------* - * Done List handling functions - *-------------------------------------------------------------------------*/ - - -/* calculate the transfer length and update the urb */ - -static void dl_transfer_length(struct td *td) -{ - __u32 tdBE, tdCBP; - struct urb_priv *lurb_priv = &urb_priv; - - tdBE = m32_swap(td->hwBE); - tdCBP = m32_swap(td->hwCBP); - - if (!(usb_pipecontrol(lurb_priv->pipe) && - ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { - if (tdBE != 0) { - if (td->hwCBP == 0) - lurb_priv->actual_length += tdBE - td->data + 1; - else - lurb_priv->actual_length += tdCBP - td->data; - } - } -} - -/*-------------------------------------------------------------------------*/ - -/* replies to the request have to be on a FIFO basis so - * we reverse the reversed done-list */ - -static struct td *dl_reverse_done_list(struct ohci *ohci) -{ - __u32 td_list_hc; - __u32 tmp; - struct td *td_rev = NULL; - struct td *td_list = NULL; - struct urb_priv *lurb_priv = NULL; - - td_list_hc = m32_swap(ohci->hcca->done_head) & 0xfffffff0; - ohci->hcca->done_head = 0; - - while (td_list_hc) { - td_list = (struct td *) td_list_hc; - - if (TD_CC_GET(m32_swap(td_list->hwINFO))) { - lurb_priv = &urb_priv; - dbg(" USB-error/status: %x : %p", - TD_CC_GET(m32_swap(td_list->hwINFO)), td_list); - if (td_list->ed->hwHeadP & m32_swap(0x1)) { - if (lurb_priv && - ((td_list->index+1) < lurb_priv->length)) { - tmp = lurb_priv->length - 1; - td_list->ed->hwHeadP = - (lurb_priv->td[tmp]->hwNextTD & - m32_swap(0xfffffff0)) | - (td_list->ed->hwHeadP & - m32_swap(0x2)); - lurb_priv->td_cnt += lurb_priv->length - - td_list->index - 1; - } else - td_list->ed->hwHeadP &= - m32_swap(0xfffffff2); - } - } - - td_list->next_dl_td = td_rev; - td_rev = td_list; - td_list_hc = m32_swap(td_list->hwNextTD) & 0xfffffff0; - } - - return td_list; -} - -/*-------------------------------------------------------------------------*/ - -/* td done list */ -static int dl_done_list(struct ohci *ohci, struct td *td_list) -{ - struct td *td_list_next = NULL; - struct ed *ed; - int cc = 0; - int stat = 0; - /* urb_t *urb; */ - struct urb_priv *lurb_priv; - __u32 tdINFO, edHeadP, edTailP; - - while (td_list) { - td_list_next = td_list->next_dl_td; - - lurb_priv = &urb_priv; - tdINFO = m32_swap(td_list->hwINFO); - - ed = td_list->ed; - - dl_transfer_length(td_list); - - /* error code of transfer */ - cc = TD_CC_GET(tdINFO); - if (cc != 0) { - dbg("ConditionCode %#x", cc); - stat = cc_to_error[cc]; - } - - /* see if this done list makes for all TD's of current URB, - * and mark the URB finished if so */ - if (++(lurb_priv->td_cnt) == lurb_priv->length) { - if ((ed->state & (ED_OPER | ED_UNLINK))) - urb_finished = 1; - else - dbg("dl_done_list: strange.., ED state %x, " - "ed->state\n"); - } else - dbg("dl_done_list: processing TD %x, len %x\n", - lurb_priv->td_cnt, lurb_priv->length); - - if (ed->state != ED_NEW) { - edHeadP = m32_swap(ed->hwHeadP) & 0xfffffff0; - edTailP = m32_swap(ed->hwTailP); - - /* unlink eds if they are not busy */ - if ((edHeadP == edTailP) && (ed->state == ED_OPER)) - ep_unlink(ohci, ed); - } - - td_list = td_list_next; - } - return stat; -} - -/*-------------------------------------------------------------------------* - * Virtual Root Hub - *-------------------------------------------------------------------------*/ - -#include <usbroothubdes.h> - -/* Hub class-specific descriptor is constructed dynamically */ - - -/*-------------------------------------------------------------------------*/ - -#define OK(x) len = (x); break -#ifdef DEBUG -#define WR_RH_STAT(x) \ -{ \ - info("WR:status %#8x", (x)); \ - writel((x), &gohci.regs->roothub.status); \ -} -#define WR_RH_PORTSTAT(x) \ -{ \ - info("WR:portstatus[%d] %#8x", wIndex-1, (x)); \ - writel((x), &gohci.regs->roothub.portstatus[wIndex-1]); \ -} -#else -#define WR_RH_STAT(x) \ - writel((x), &gohci.regs->roothub.status) -#define WR_RH_PORTSTAT(x)\ - writel((x), &gohci.regs->roothub.portstatus[wIndex-1]) -#endif -#define RD_RH_STAT roothub_status(&gohci) -#define RD_RH_PORTSTAT roothub_portstatus(&gohci, wIndex-1) - -/* request to virtual root hub */ - -int rh_check_port_status(struct ohci *controller) -{ - __u32 temp, ndp, i; - int res; - - res = -1; - temp = roothub_a(controller); - ndp = (temp & RH_A_NDP); - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); - /* check for a device disconnect */ - if (((temp & (RH_PS_PESC | RH_PS_CSC)) == - (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) { - res = i; - break; - } - } - return res; -} - -static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *cmd) -{ - void *data = buffer; - int leni = transfer_len; - int len = 0; - int stat = 0; - union { - __u32 word[4]; - __u16 hword[8]; - __u8 byte[16]; - } datab; - __u8 *data_buf = datab.byte; - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - -#ifdef DEBUG - urb_priv.actual_length = 0; - pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", - usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (usb_pipeint(pipe)) { - info("Root-Hub submit IRQ: NOT implemented"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = m16_swap(cmd->value); - wIndex = m16_swap(cmd->index); - wLength = m16_swap(cmd->length); - - info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", - dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); - - switch (bmRType_bReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ - - case RH_GET_STATUS: - datab.hword[0] = m16_swap(1); - OK(2); - case RH_GET_STATUS | RH_INTERFACE: - datab.hword[0] = m16_swap(0); - OK(2); - case RH_GET_STATUS | RH_ENDPOINT: - datab.hword[0] = m16_swap(0); - OK(2); - case RH_GET_STATUS | RH_CLASS: - datab.word[0] = - m32_swap(RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); - OK(4); - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - datab.word[0] = m32_swap(RD_RH_PORTSTAT); - OK(4); - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - switch (wValue) { - case (RH_ENDPOINT_STALL): - OK(0); - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - OK(0); - case (RH_C_HUB_OVER_CURRENT): - WR_RH_STAT(RH_HS_OCIC); - OK(0); - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_ENABLE): - WR_RH_PORTSTAT(RH_PS_CCS); - OK(0); - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT(RH_PS_POCI); - OK(0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT(RH_PS_LSDA); - OK(0); - case (RH_C_PORT_CONNECTION): - WR_RH_PORTSTAT(RH_PS_CSC); - OK(0); - case (RH_C_PORT_ENABLE): - WR_RH_PORTSTAT(RH_PS_PESC); - OK(0); - case (RH_C_PORT_SUSPEND): - WR_RH_PORTSTAT(RH_PS_PSSC); - OK(0); - case (RH_C_PORT_OVER_CURRENT): - WR_RH_PORTSTAT(RH_PS_OCIC); - OK(0); - case (RH_C_PORT_RESET): - WR_RH_PORTSTAT(RH_PS_PRSC); - OK(0); - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT(RH_PS_PSS); - OK(0); - case (RH_PORT_RESET): /* BUG IN HUP CODE ******** */ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT(RH_PS_PRS); - OK(0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT(RH_PS_PPS); - OK(0); - case (RH_PORT_ENABLE): /* BUG IN HUP CODE ******** */ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT(RH_PS_PES); - OK(0); - } - break; - - case RH_SET_ADDRESS: - gohci.rh.devnum = wValue; - OK(0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_dev_des), wLength)); - data_buf = root_hub_dev_des; - OK(len); - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_config_des), - wLength)); - data_buf = root_hub_config_des; - OK(len); - case (0x03): /* string descriptors */ - if (wValue == 0x0300) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index0), - wLength)); - data_buf = root_hub_str_index0; - OK(len); - } - if (wValue == 0x0301) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index1), - wLength)); - data_buf = root_hub_str_index1; - OK(len); - } - default: - stat = USB_ST_STALLED; - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - { - __u32 temp = roothub_a(&gohci); - - data_buf[0] = 9; /* min length; */ - data_buf[1] = 0x29; - data_buf[2] = temp & RH_A_NDP; - data_buf[3] = 0; - if (temp & RH_A_PSM) - /* per-port power switching? */ - data_buf[3] |= 0x1; - if (temp & RH_A_NOCP) - /* no overcurrent reporting? */ - data_buf[3] |= 0x10; - else if (temp & RH_A_OCPM) - /* per-port overcurrent reporting? */ - data_buf[3] |= 0x8; - - /* corresponds to data_buf[4-7] */ - datab.word[1] = 0; - data_buf[5] = (temp & RH_A_POTPGT) >> 24; - temp = roothub_b(&gohci); - data_buf[7] = temp & RH_B_DR; - if (data_buf[2] < 7) { - data_buf[8] = 0xff; - } else { - data_buf[0] += 2; - data_buf[8] = (temp & RH_B_DR) >> 8; - data_buf[10] = data_buf[9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, data_buf[0], wLength)); - OK(len); - } - - case RH_GET_CONFIGURATION: - *(__u8 *) data_buf = 0x01; - OK(1); - - case RH_SET_CONFIGURATION: - WR_RH_STAT(0x10000); - OK(0); - - default: - dbg("unsupported root hub command"); - stat = USB_ST_STALLED; - } - -#ifdef DEBUG - ohci_dump_roothub(&gohci, 1); -#else - mdelay(1); -#endif - - len = min_t(int, len, leni); - if (data != data_buf) - memcpy(data, data_buf, len); - dev->act_len = len; - dev->status = stat; - -#ifdef DEBUG - if (transfer_len) - urb_priv.actual_length = transfer_len; - pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", - 0 /*usb_pipein(pipe) */); -#else - mdelay(1); -#endif - - return stat; -} - -/*-------------------------------------------------------------------------*/ - -/* common code for handling submit messages - used for all but root hub */ -/* accesses. */ -int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, int interval) -{ - int stat = 0; - int maxsize = usb_maxpacket(dev, pipe); - int timeout; - - /* device pulled? Shortcut the action. */ - if (devgone == dev) { - dev->status = USB_ST_CRC_ERR; - return 0; - } -#ifdef DEBUG - urb_priv.actual_length = 0; - pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", - usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (!maxsize) { - err("submit_common_message: pipesize for pipe %lx is zero", - pipe); - return -1; - } - - if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < - 0) { - err("sohci_submit_job failed"); - return -1; - } - - mdelay(10); - /* ohci_dump_status(&gohci); */ - - /* allow more time for a BULK device to react - some are slow */ -#define BULK_TO 5000 /* timeout in milliseconds */ - if (usb_pipebulk(pipe)) - timeout = BULK_TO; - else - timeout = 100; - - /* wait for it to complete */ - for (;;) { - /* check whether the controller is done */ - stat = hc_interrupt(); - - if (stat < 0) { - stat = USB_ST_CRC_ERR; - break; - } - - /* NOTE: since we are not interrupt driven in U-Boot and always - * handle only one URB at a time, we cannot assume the - * transaction finished on the first successful return from - * hc_interrupt().. unless the flag for current URB is set, - * meaning that all TD's to/from device got actually - * transferred and processed. If the current URB is not - * finished we need to re-iterate this loop so as - * hc_interrupt() gets called again as there needs to be some - * more TD's to process still */ - if ((stat >= 0) && (stat != 0xff) && (urb_finished)) { - /* 0xff is returned for an SF-interrupt */ - break; - } - - if (--timeout) { - mdelay(1); - if (!urb_finished) - dbg("\%"); - - } else { - err("CTL:TIMEOUT "); - dbg("submit_common_msg: TO status %x\n", stat); - stat = USB_ST_CRC_ERR; - urb_finished = 1; - break; - } - } - -#if 0 - /* we got an Root Hub Status Change interrupt */ - if (got_rhsc) { -#ifdef DEBUG - ohci_dump_roothub(&gohci, 1); -#endif - got_rhsc = 0; - /* abuse timeout */ - timeout = rh_check_port_status(&gohci); - if (timeout >= 0) { -#if 0 /* this does nothing useful, but leave it here - in case that changes */ - /* the called routine adds 1 to the passed value */ - usb_hub_port_connect_change(gohci.rh.dev, timeout - 1); -#endif - /* - * XXX - * This is potentially dangerous because it assumes - * that only one device is ever plugged in! - */ - devgone = dev; - } - } -#endif - - dev->status = stat; - dev->act_len = transfer_len; - -#ifdef DEBUG - pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", - usb_pipein(pipe)); -#else - mdelay(1); -#endif - - /* free TDs in urb_priv */ - urb_free_priv(&urb_priv); - return 0; -} - -/* submit routines called from usb.c */ -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len) -{ - info("submit_bulk_msg"); - return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup) -{ - int maxsize = usb_maxpacket(dev, pipe); - - info("submit_control_msg"); -#ifdef DEBUG - urb_priv.actual_length = 0; - pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", - usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (!maxsize) { - err("submit_control_message: pipesize for pipe %lx is zero", - pipe); - return -1; - } - if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) { - gohci.rh.dev = dev; - /* root hub - redirect */ - return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len, - setup); - } - - return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0); -} - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, int interval) -{ - info("submit_int_msg"); - return -1; -} - -/*-------------------------------------------------------------------------* - * HC functions - *-------------------------------------------------------------------------*/ - -/* reset the HC and BUS */ - -static int hc_reset(struct ohci *ohci) -{ - int timeout = 30; - int smm_timeout = 50; /* 0,5 sec */ - - if (readl(&ohci->regs->control) & OHCI_CTRL_IR) { - /* SMM owns the HC - request ownership */ - writel(OHCI_OCR, &ohci->regs->cmdstatus); - info("USB HC TakeOver from SMM"); - while (readl(&ohci->regs->control) & OHCI_CTRL_IR) { - mdelay(10); - if (--smm_timeout == 0) { - err("USB HC TakeOver failed!"); - return -1; - } - } - } - - /* Disable HC interrupts */ - writel(OHCI_INTR_MIE, &ohci->regs->intrdisable); - - dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;", - ohci->slot_name, readl(&ohci->regs->control)); - - /* Reset USB (needed by some controllers) */ - writel(0, &ohci->regs->control); - - /* HC Reset requires max 10 us delay */ - writel(OHCI_HCR, &ohci->regs->cmdstatus); - while ((readl(&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { - if (--timeout == 0) { - err("USB HC reset timed out!"); - return -1; - } - udelay(1); - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* Start an OHCI controller, set the BUS operational - * enable interrupts - * connect the virtual root hub */ - -static int hc_start(struct ohci *ohci) -{ - __u32 mask; - unsigned int fminterval; - - ohci->disabled = 1; - - /* Tell the controller where the control and bulk lists are - * The lists are empty now. */ - - writel(0, &ohci->regs->ed_controlhead); - writel(0, &ohci->regs->ed_bulkhead); - - /* a reset clears this */ - writel((__u32) ohci->hcca, &ohci->regs->hcca); - - fminterval = 0x2edf; - writel((fminterval * 9) / 10, &ohci->regs->periodicstart); - fminterval |= ((((fminterval - 210) * 6) / 7) << 16); - writel(fminterval, &ohci->regs->fminterval); - writel(0x628, &ohci->regs->lsthresh); - - /* start controller operations */ - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; - ohci->disabled = 0; - writel(ohci->hc_control, &ohci->regs->control); - - /* disable all interrupts */ - mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | - OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | - OHCI_INTR_OC | OHCI_INTR_MIE); - writel(mask, &ohci->regs->intrdisable); - /* clear all interrupts */ - mask &= ~OHCI_INTR_MIE; - writel(mask, &ohci->regs->intrstatus); - /* Choose the interrupts we care about now - but w/o MIE */ - mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; - writel(mask, &ohci->regs->intrenable); - -#ifdef OHCI_USE_NPS - /* required for AMD-756 and some Mac platforms */ - writel((roothub_a(ohci) | RH_A_NPS) & ~RH_A_PSM, - &ohci->regs->roothub.a); - writel(RH_HS_LPSC, &ohci->regs->roothub.status); -#endif /* OHCI_USE_NPS */ - - /* POTPGT delay is bits 24-31, in 2 ms units. */ - mdelay((roothub_a(ohci) >> 23) & 0x1fe); - - /* connect the virtual root hub */ - ohci->rh.devnum = 0; - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* an interrupt happens */ - -static int hc_interrupt(void) -{ - struct ohci *ohci = &gohci; - struct ohci_regs *regs = ohci->regs; - int ints; - int stat = -1; - - if ((ohci->hcca->done_head != 0) && - !(m32_swap(ohci->hcca->done_head) & 0x01)) { - - ints = OHCI_INTR_WDH; - - } else { - ints = readl(®s->intrstatus); - if (ints == ~(u32) 0) { - ohci->disabled++; - err("%s device removed!", ohci->slot_name); - return -1; - } - ints &= readl(®s->intrenable); - if (ints == 0) { - dbg("hc_interrupt: returning..\n"); - return 0xff; - } - } - - /* dbg("Interrupt: %x frame: %x", ints, - le16_to_cpu(ohci->hcca->frame_no)); */ - - if (ints & OHCI_INTR_RHSC) { - got_rhsc = 1; - stat = 0xff; - } - - if (ints & OHCI_INTR_UE) { - ohci->disabled++; - err("OHCI Unrecoverable Error, controller usb-%s disabled", - ohci->slot_name); - /* e.g. due to PCI Master/Target Abort */ - -#ifdef DEBUG - ohci_dump(ohci, 1); -#else - mdelay(1); -#endif - /* FIXME: be optimistic, hope that bug won't repeat often. */ - /* Make some non-interrupt context restart the controller. */ - /* Count and limit the retries though; either hardware or */ - /* software errors can go forever... */ - hc_reset(ohci); - return -1; - } - - if (ints & OHCI_INTR_WDH) { - mdelay(1); - - writel(OHCI_INTR_WDH, ®s->intrdisable); - stat = dl_done_list(&gohci, dl_reverse_done_list(&gohci)); - writel(OHCI_INTR_WDH, ®s->intrenable); - } - - if (ints & OHCI_INTR_SO) { - dbg("USB Schedule overrun\n"); - writel(OHCI_INTR_SO, ®s->intrenable); - stat = -1; - } - - /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ - if (ints & OHCI_INTR_SF) { - unsigned int frame = m16_swap(ohci->hcca->frame_no) & 1; - mdelay(1); - writel(OHCI_INTR_SF, ®s->intrdisable); - if (ohci->ed_rm_list[frame] != NULL) - writel(OHCI_INTR_SF, ®s->intrenable); - stat = 0xff; - } - - writel(ints, ®s->intrstatus); - return stat; -} - -/*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------------------*/ - -/* De-allocate all resources.. */ - -static void hc_release_ohci(struct ohci *ohci) -{ - dbg("USB HC release ohci usb-%s", ohci->slot_name); - - if (!ohci->disabled) - hc_reset(ohci); -} - -/*-------------------------------------------------------------------------*/ - -/* - * low level initalisation routine, called from usb.c - */ -static char ohci_inited = 0; - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); - - /* - * Set the 48 MHz UPLL clocking. Values are taken from - * "PLL value selection guide", 6-23, s3c2400_UM.pdf. - */ - clk_power->upllcon = ((40 << 12) + (1 << 4) + 2); - gpio->misccr |= 0x8; /* 1 = use pads related USB for USB host */ - - /* - * Enable USB host clock. - */ - clk_power->clkcon |= (1 << 4); - - memset(&gohci, 0, sizeof(struct ohci)); - memset(&urb_priv, 0, sizeof(struct urb_priv)); - - /* align the storage */ - if ((__u32) &ghcca[0] & 0xff) { - err("HCCA not aligned!!"); - return -1; - } - phcca = &ghcca[0]; - info("aligned ghcca %p", phcca); - memset(&ohci_dev, 0, sizeof(struct ohci_device)); - if ((__u32) &ohci_dev.ed[0] & 0x7) { - err("EDs not aligned!!"); - return -1; - } - memset(gtd, 0, sizeof(struct td) * (NUM_TD + 1)); - if ((__u32) gtd & 0x7) { - err("TDs not aligned!!"); - return -1; - } - ptd = gtd; - gohci.hcca = phcca; - memset(phcca, 0, sizeof(struct ohci_hcca)); - - gohci.disabled = 1; - gohci.sleeping = 0; - gohci.irq = -1; - gohci.regs = (struct ohci_regs *)S3C24X0_USB_HOST_BASE; - - gohci.flags = 0; - gohci.slot_name = "s3c2400"; - - if (hc_reset(&gohci) < 0) { - hc_release_ohci(&gohci); - /* Initialization failed */ - clk_power->clkcon &= ~(1 << 4); - return -1; - } - - /* FIXME this is a second HC reset; why?? */ - gohci.hc_control = OHCI_USB_RESET; - writel(gohci.hc_control, &gohci.regs->control); - mdelay(10); - - if (hc_start(&gohci) < 0) { - err("can't start usb-%s", gohci.slot_name); - hc_release_ohci(&gohci); - /* Initialization failed */ - clk_power->clkcon &= ~(1 << 4); - return -1; - } -#ifdef DEBUG - ohci_dump(&gohci, 1); -#else - mdelay(1); -#endif - ohci_inited = 1; - urb_finished = 1; - - return 0; -} - -int usb_lowlevel_stop(int index) -{ - struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - - /* this gets called really early - before the controller has */ - /* even been initialized! */ - if (!ohci_inited) - return 0; - /* TODO release any interrupts, etc. */ - /* call hc_release_ohci() here ? */ - hc_reset(&gohci); - /* may not want to do this */ - clk_power->clkcon &= ~(1 << 4); - return 0; -} - -#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_S3C24X0) */ - -#if defined(CONFIG_USB_OHCI_NEW) && \ - defined(CONFIG_SYS_USB_OHCI_CPU_INIT) && \ - defined(CONFIG_S3C24X0) - -int usb_cpu_init(void) -{ - struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); - - /* - * Set the 48 MHz UPLL clocking. Values are taken from - * "PLL value selection guide", 6-23, s3c2400_UM.pdf. - */ - writel((40 << 12) + (1 << 4) + 2, &clk_power->upllcon); - /* 1 = use pads related USB for USB host */ - writel(readl(&gpio->misccr) | 0x8, &gpio->misccr); - - /* - * Enable USB host clock. - */ - writel(readl(&clk_power->clkcon) | (1 << 4), &clk_power->clkcon); - - return 0; -} - -int usb_cpu_stop(void) -{ - struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - /* may not want to do this */ - writel(readl(&clk_power->clkcon) & ~(1 << 4), &clk_power->clkcon); - return 0; -} - -int usb_cpu_init_fail(void) -{ - struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - writel(readl(&clk_power->clkcon) & ~(1 << 4), &clk_power->clkcon); - return 0; -} - -#endif /* defined(CONFIG_USB_OHCI_NEW) && \ - defined(CONFIG_SYS_USB_OHCI_CPU_INIT) && \ - defined(CONFIG_S3C24X0) */ diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.h b/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.h deleted file mode 100644 index f272d7885..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.h +++ /dev/null @@ -1,409 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net> - * - * usb-ohci.h - */ - - -static int cc_to_error[16] = { - -/* mapping of the OHCI CC status to error codes */ - /* No Error */ 0, - /* CRC Error */ USB_ST_CRC_ERR, - /* Bit Stuff */ USB_ST_BIT_ERR, - /* Data Togg */ USB_ST_CRC_ERR, - /* Stall */ USB_ST_STALLED, - /* DevNotResp */ -1, - /* PIDCheck */ USB_ST_BIT_ERR, - /* UnExpPID */ USB_ST_BIT_ERR, - /* DataOver */ USB_ST_BUF_ERR, - /* DataUnder */ USB_ST_BUF_ERR, - /* reservd */ -1, - /* reservd */ -1, - /* BufferOver */ USB_ST_BUF_ERR, - /* BuffUnder */ USB_ST_BUF_ERR, - /* Not Access */ -1, - /* Not Access */ -1 -}; - -/* ED States */ -#define ED_NEW 0x00 -#define ED_UNLINK 0x01 -#define ED_OPER 0x02 -#define ED_DEL 0x04 -#define ED_URB_DEL 0x08 - -/* usb_ohci_ed */ -struct ed { - __u32 hwINFO; - __u32 hwTailP; - __u32 hwHeadP; - __u32 hwNextED; - - struct ed *ed_prev; - __u8 int_period; - __u8 int_branch; - __u8 int_load; - __u8 int_interval; - __u8 state; - __u8 type; - __u16 last_iso; - struct ed *ed_rm_list; - - struct usb_device *usb_dev; - __u32 unused[3]; -} __attribute__ ((aligned(16))); - -/* TD info field */ -#define TD_CC 0xf0000000 -#define TD_CC_GET(td_p) (((td_p) >> 28) & 0x0f) -#define TD_CC_SET(td_p, cc) \ - {(td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)} -#define TD_EC 0x0C000000 -#define TD_T 0x03000000 -#define TD_T_DATA0 0x02000000 -#define TD_T_DATA1 0x03000000 -#define TD_T_TOGGLE 0x00000000 -#define TD_R 0x00040000 -#define TD_DI 0x00E00000 -#define TD_DI_SET(X) (((X) & 0x07)<< 21) -#define TD_DP 0x00180000 -#define TD_DP_SETUP 0x00000000 -#define TD_DP_IN 0x00100000 -#define TD_DP_OUT 0x00080000 - -#define TD_ISO 0x00010000 -#define TD_DEL 0x00020000 - -/* CC Codes */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D -#define TD_NOTACCESSED 0x0F - - -#define MAXPSW 1 - -struct td { - __u32 hwINFO; - __u32 hwCBP; /* Current Buffer Pointer */ - __u32 hwNextTD; /* Next TD Pointer */ - __u32 hwBE; /* Memory Buffer End Pointer */ - - __u8 unused; - __u8 index; - struct ed *ed; - struct td *next_dl_td; - struct usb_device *usb_dev; - int transfer_len; - __u32 data; - - __u32 unused2[2]; -} __attribute__ ((aligned(32))); - -#define OHCI_ED_SKIP (1 << 14) - -/* - * The HCCA (Host Controller Communications Area) is a 256 byte - * structure defined in the OHCI spec. that the host controller is - * told the base address of. It must be 256-byte aligned. - */ - -#define NUM_INTS 32 /* part of the OHCI standard */ -struct ohci_hcca { - __u32 int_table[NUM_INTS]; /* Interrupt ED table */ - __u16 frame_no; /* current frame number */ - __u16 pad1; /* set to 0 on each frame_no change */ - __u32 done_head; /* info returned for an interrupt */ - u8 reserved_for_hc[116]; -} __attribute__ ((aligned(256))); - -/* - * Maximum number of root hub ports. - */ -#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ - -/* - * This is the structure of the OHCI controller's memory mapped I/O - * region. This is Memory Mapped I/O. You must use the readl() and - * writel() macros defined in asm/io.h to access these!! - */ -struct ohci_regs { - /* control and status registers */ - __u32 revision; - __u32 control; - __u32 cmdstatus; - __u32 intrstatus; - __u32 intrenable; - __u32 intrdisable; - /* memory pointers */ - __u32 hcca; - __u32 ed_periodcurrent; - __u32 ed_controlhead; - __u32 ed_controlcurrent; - __u32 ed_bulkhead; - __u32 ed_bulkcurrent; - __u32 donehead; - /* frame counters */ - __u32 fminterval; - __u32 fmremaining; - __u32 fmnumber; - __u32 periodicstart; - __u32 lsthresh; - /* Root hub ports */ - struct ohci_roothub_regs { - __u32 a; - __u32 b; - __u32 status; - __u32 portstatus[MAX_ROOT_PORTS]; - } roothub; -} __attribute__ ((aligned(32))); - -/* OHCI CONTROL AND STATUS REGISTER MASKS */ - -/* - * HcControl (control) register masks - */ -#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ -#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ -#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ -#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ -#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ -#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ -#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ - -/* pre-shifted values for HCFS */ -# define OHCI_USB_RESET (0 << 6) -# define OHCI_USB_RESUME (1 << 6) -# define OHCI_USB_OPER (2 << 6) -# define OHCI_USB_SUSPEND (3 << 6) - -/* - * HcCommandStatus (cmdstatus) register masks - */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_CLF (1 << 1) /* control list filled */ -#define OHCI_BLF (1 << 2) /* bulk list filled */ -#define OHCI_OCR (1 << 3) /* ownership change request */ -#define OHCI_SOC (3 << 16) /* scheduling overrun count */ - -/* - * masks used with interrupt registers: - * HcInterruptStatus (intrstatus) - * HcInterruptEnable (intrenable) - * HcInterruptDisable (intrdisable) - */ -#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ -#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ -#define OHCI_INTR_SF (1 << 2) /* start frame */ -#define OHCI_INTR_RD (1 << 3) /* resume detect */ -#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ -#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ -#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ -#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ - -/* Virtual Root HUB */ -struct virt_root_hub { - int devnum; /* Address of Root Hub endpoint */ - void *dev; /* was urb */ - void *int_addr; - int send; - int interval; -}; - -/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 - -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - - -/* OHCI ROOT HUB REGISTER MASKS */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status */ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -/* urb */ -#define N_URB_TD 48 -struct urb_priv { - struct ed *ed; - __u16 length; /* number of tds associated with this request */ - __u16 td_cnt; /* number of tds already serviced */ - int state; - unsigned long pipe; - int actual_length; - struct td *td[N_URB_TD]; /* list pointer to all corresponding TDs - associated with this request */ -}; -#define URB_DEL 1 - -/* - * This is the full ohci controller description - * - * Note how the "proper" USB information is just - * a subset of what the full implementation needs. (Linus) - */ - - -struct ohci { - struct ohci_hcca *hcca; /* hcca */ - /*dma_addr_t hcca_dma; */ - - int irq; - int disabled; /* e.g. got a UE, we're hung */ - int sleeping; - unsigned long flags; /* for HC bugs */ - - struct ohci_regs *regs; /* OHCI controller's memory */ - - struct ed *ed_rm_list[2]; /* lists of all endpoints to be removed */ - struct ed *ed_bulktail; /* last endpoint of bulk list */ - struct ed *ed_controltail; /* last endpoint of control list */ - int intrstatus; - __u32 hc_control; /* copy of the hc control reg */ - struct usb_device *dev[32]; - struct virt_root_hub rh; - - const char *slot_name; -}; - -#define NUM_EDS 8 /* num of preallocated endpoint descriptors */ - -struct ohci_device { - struct ed ed[NUM_EDS]; - int ed_cnt; -}; - -/* hcd */ -/* endpoint */ -static int ep_link(struct ohci *ohci, struct ed *ed); -static int ep_unlink(struct ohci *ohci, struct ed *ed); -static struct ed *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe); - -/*-------------------------------------------------------------------------*/ - -/* we need more TDs than EDs */ -#define NUM_TD 64 - -/* +1 so we can align the storage */ -struct td gtd[NUM_TD + 1]; - -/* pointers to aligned storage */ -struct td *ptd; - -/* TDs ... */ -static inline struct td *td_alloc(struct usb_device *usb_dev) -{ - int i; - struct td *td; - - td = NULL; - for (i = 0; i < NUM_TD; i++) { - if (ptd[i].usb_dev == NULL) { - td = &ptd[i]; - td->usb_dev = usb_dev; - break; - } - } - - return td; -} - -static inline void ed_free(struct ed *ed) -{ - ed->usb_dev = NULL; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci.h b/qemu/roms/u-boot/drivers/usb/host/ohci.h deleted file mode 100644 index 9a4a2c247..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci.h +++ /dev/null @@ -1,491 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net> - * - * usb-ohci.h - */ - -/* - * e.g. PCI controllers need this - */ -#ifdef CONFIG_SYS_OHCI_SWAP_REG_ACCESS -# define ohci_readl(a) __swap_32(*((volatile u32 *)(a))) -# define ohci_writel(a, b) (*((volatile u32 *)(b)) = __swap_32((volatile u32)a)) -#else -# define ohci_readl(a) (*((volatile u32 *)(a))) -# define ohci_writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a)) -#endif /* CONFIG_SYS_OHCI_SWAP_REG_ACCESS */ - -/* functions for doing board or CPU specific setup/cleanup */ -int usb_board_stop(void); - -int usb_cpu_init(void); -int usb_cpu_stop(void); -int usb_cpu_init_fail(void); - -static int cc_to_error[16] = { - -/* mapping of the OHCI CC status to error codes */ - /* No Error */ 0, - /* CRC Error */ USB_ST_CRC_ERR, - /* Bit Stuff */ USB_ST_BIT_ERR, - /* Data Togg */ USB_ST_CRC_ERR, - /* Stall */ USB_ST_STALLED, - /* DevNotResp */ -1, - /* PIDCheck */ USB_ST_BIT_ERR, - /* UnExpPID */ USB_ST_BIT_ERR, - /* DataOver */ USB_ST_BUF_ERR, - /* DataUnder */ USB_ST_BUF_ERR, - /* reservd */ -1, - /* reservd */ -1, - /* BufferOver */ USB_ST_BUF_ERR, - /* BuffUnder */ USB_ST_BUF_ERR, - /* Not Access */ -1, - /* Not Access */ -1 -}; - -static const char *cc_to_string[16] = { - "No Error", - "CRC: Last data packet from endpoint contained a CRC error.", - "BITSTUFFING: Last data packet from endpoint contained a bit " \ - "stuffing violation", - "DATATOGGLEMISMATCH: Last packet from endpoint had data toggle PID\n" \ - "that did not match the expected value.", - "STALL: TD was moved to the Done Queue because the endpoint returned" \ - " a STALL PID", - "DEVICENOTRESPONDING: Device did not respond to token (IN) or did\n" \ - "not provide a handshake (OUT)", - "PIDCHECKFAILURE: Check bits on PID from endpoint failed on data PID\n"\ - "(IN) or handshake (OUT)", - "UNEXPECTEDPID: Receive PID was not valid when encountered or PID\n" \ - "value is not defined.", - "DATAOVERRUN: The amount of data returned by the endpoint exceeded\n" \ - "either the size of the maximum data packet allowed\n" \ - "from the endpoint (found in MaximumPacketSize field\n" \ - "of ED) or the remaining buffer size.", - "DATAUNDERRUN: The endpoint returned less than MaximumPacketSize\n" \ - "and that amount was not sufficient to fill the\n" \ - "specified buffer", - "reserved1", - "reserved2", - "BUFFEROVERRUN: During an IN, HC received data from endpoint faster\n" \ - "than it could be written to system memory", - "BUFFERUNDERRUN: During an OUT, HC could not retrieve data from\n" \ - "system memory fast enough to keep up with data USB " \ - "data rate.", - "NOT ACCESSED: This code is set by software before the TD is placed" \ - "on a list to be processed by the HC.(1)", - "NOT ACCESSED: This code is set by software before the TD is placed" \ - "on a list to be processed by the HC.(2)", -}; - -/* ED States */ - -#define ED_NEW 0x00 -#define ED_UNLINK 0x01 -#define ED_OPER 0x02 -#define ED_DEL 0x04 -#define ED_URB_DEL 0x08 - -/* usb_ohci_ed */ -struct ed { - __u32 hwINFO; - __u32 hwTailP; - __u32 hwHeadP; - __u32 hwNextED; - - struct ed *ed_prev; - __u8 int_period; - __u8 int_branch; - __u8 int_load; - __u8 int_interval; - __u8 state; - __u8 type; - __u16 last_iso; - struct ed *ed_rm_list; - - struct usb_device *usb_dev; - void *purb; - __u32 unused[2]; -} __attribute__((aligned(16))); -typedef struct ed ed_t; - - -/* TD info field */ -#define TD_CC 0xf0000000 -#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) -#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) -#define TD_EC 0x0C000000 -#define TD_T 0x03000000 -#define TD_T_DATA0 0x02000000 -#define TD_T_DATA1 0x03000000 -#define TD_T_TOGGLE 0x00000000 -#define TD_R 0x00040000 -#define TD_DI 0x00E00000 -#define TD_DI_SET(X) (((X) & 0x07)<< 21) -#define TD_DP 0x00180000 -#define TD_DP_SETUP 0x00000000 -#define TD_DP_IN 0x00100000 -#define TD_DP_OUT 0x00080000 - -#define TD_ISO 0x00010000 -#define TD_DEL 0x00020000 - -/* CC Codes */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D -#define TD_NOTACCESSED 0x0F - - -#define MAXPSW 1 - -struct td { - __u32 hwINFO; - __u32 hwCBP; /* Current Buffer Pointer */ - __u32 hwNextTD; /* Next TD Pointer */ - __u32 hwBE; /* Memory Buffer End Pointer */ - -/* #ifndef CONFIG_MPC5200 /\* this seems wrong *\/ */ - __u16 hwPSW[MAXPSW]; -/* #endif */ - __u8 unused; - __u8 index; - struct ed *ed; - struct td *next_dl_td; - struct usb_device *usb_dev; - int transfer_len; - __u32 data; - - __u32 unused2[2]; -} __attribute__((aligned(32))); -typedef struct td td_t; - -#define OHCI_ED_SKIP (1 << 14) - -/* - * The HCCA (Host Controller Communications Area) is a 256 byte - * structure defined in the OHCI spec. that the host controller is - * told the base address of. It must be 256-byte aligned. - */ - -#define NUM_INTS 32 /* part of the OHCI standard */ -struct ohci_hcca { - __u32 int_table[NUM_INTS]; /* Interrupt ED table */ -#if defined(CONFIG_MPC5200) - __u16 pad1; /* set to 0 on each frame_no change */ - __u16 frame_no; /* current frame number */ -#else - __u16 frame_no; /* current frame number */ - __u16 pad1; /* set to 0 on each frame_no change */ -#endif - __u32 done_head; /* info returned for an interrupt */ - u8 reserved_for_hc[116]; -} __attribute__((aligned(256))); - - -/* - * Maximum number of root hub ports. - */ -#ifndef CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS -# error "CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS undefined!" -#endif - -/* - * This is the structure of the OHCI controller's memory mapped I/O - * region. This is Memory Mapped I/O. You must use the ohci_readl() and - * ohci_writel() macros defined in this file to access these!! - */ -struct ohci_regs { - /* control and status registers */ - __u32 revision; - __u32 control; - __u32 cmdstatus; - __u32 intrstatus; - __u32 intrenable; - __u32 intrdisable; - /* memory pointers */ - __u32 hcca; - __u32 ed_periodcurrent; - __u32 ed_controlhead; - __u32 ed_controlcurrent; - __u32 ed_bulkhead; - __u32 ed_bulkcurrent; - __u32 donehead; - /* frame counters */ - __u32 fminterval; - __u32 fmremaining; - __u32 fmnumber; - __u32 periodicstart; - __u32 lsthresh; - /* Root hub ports */ - struct ohci_roothub_regs { - __u32 a; - __u32 b; - __u32 status; - __u32 portstatus[CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS]; - } roothub; -} __attribute__((aligned(32))); - -/* Some EHCI controls */ -#define EHCI_USBCMD_OFF 0x20 -#define EHCI_USBCMD_HCRESET (1 << 1) - -/* OHCI CONTROL AND STATUS REGISTER MASKS */ - -/* - * HcControl (control) register masks - */ -#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ -#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ -#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ -#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ -#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ -#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ -#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ - -/* pre-shifted values for HCFS */ -# define OHCI_USB_RESET (0 << 6) -# define OHCI_USB_RESUME (1 << 6) -# define OHCI_USB_OPER (2 << 6) -# define OHCI_USB_SUSPEND (3 << 6) - -/* - * HcCommandStatus (cmdstatus) register masks - */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_CLF (1 << 1) /* control list filled */ -#define OHCI_BLF (1 << 2) /* bulk list filled */ -#define OHCI_OCR (1 << 3) /* ownership change request */ -#define OHCI_SOC (3 << 16) /* scheduling overrun count */ - -/* - * masks used with interrupt registers: - * HcInterruptStatus (intrstatus) - * HcInterruptEnable (intrenable) - * HcInterruptDisable (intrdisable) - */ -#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ -#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ -#define OHCI_INTR_SF (1 << 2) /* start frame */ -#define OHCI_INTR_RD (1 << 3) /* resume detect */ -#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ -#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ -#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ -#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ - - -/* Virtual Root HUB */ -struct virt_root_hub { - int devnum; /* Address of Root Hub endpoint */ - void *dev; /* was urb */ - void *int_addr; - int send; - int interval; -}; - -/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 - -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - - -/* OHCI ROOT HUB REGISTER MASKS */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status*/ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -/* urb */ -#define N_URB_TD 48 -typedef struct -{ - ed_t *ed; - __u16 length; /* number of tds associated with this request */ - __u16 td_cnt; /* number of tds already serviced */ - struct usb_device *dev; - int state; - unsigned long pipe; - void *transfer_buffer; - int transfer_buffer_length; - int interval; - int actual_length; - int finished; - td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */ -} urb_priv_t; -#define URB_DEL 1 - -/* - * This is the full ohci controller description - * - * Note how the "proper" USB information is just - * a subset of what the full implementation needs. (Linus) - */ - - -typedef struct ohci { - struct ohci_hcca *hcca; /* hcca */ - /*dma_addr_t hcca_dma;*/ - - int irq; - int disabled; /* e.g. got a UE, we're hung */ - int sleeping; - unsigned long flags; /* for HC bugs */ - - struct ohci_regs *regs; /* OHCI controller's memory */ - - int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/ - ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */ - ed_t *ed_bulktail; /* last endpoint of bulk list */ - ed_t *ed_controltail; /* last endpoint of control list */ - int intrstatus; - __u32 hc_control; /* copy of the hc control reg */ - struct usb_device *dev[32]; - struct virt_root_hub rh; - - const char *slot_name; -} ohci_t; - -#define NUM_EDS 8 /* num of preallocated endpoint descriptors */ - -struct ohci_device { - ed_t ed[NUM_EDS]; - int ed_cnt; -}; - -/* hcd */ -/* endpoint */ -static int ep_link(ohci_t * ohci, ed_t * ed); -static int ep_unlink(ohci_t * ohci, ed_t * ed); -static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe, - int interval, int load); - -/*-------------------------------------------------------------------------*/ - -/* we need more TDs than EDs */ -#define NUM_TD 64 - -/* +1 so we can align the storage */ -td_t gtd[NUM_TD+1]; -/* pointers to aligned storage */ -td_t *ptd; - -/* TDs ... */ -static inline struct td * -td_alloc (struct usb_device *usb_dev) -{ - int i; - struct td *td; - - td = NULL; - for (i = 0; i < NUM_TD; i++) - { - if (ptd[i].usb_dev == NULL) - { - td = &ptd[i]; - td->usb_dev = usb_dev; - break; - } - } - - return td; -} - -static inline void -ed_free (struct ed *ed) -{ - ed->usb_dev = NULL; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/r8a66597-hcd.c b/qemu/roms/u-boot/drivers/usb/host/r8a66597-hcd.c deleted file mode 100644 index dfe5423b8..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/r8a66597-hcd.c +++ /dev/null @@ -1,832 +0,0 @@ -/* - * R8A66597 HCD (Host Controller Driver) for u-boot - * - * Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.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; version 2 of the License. - * - * 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include <common.h> -#include <usb.h> -#include <asm/io.h> - -#include "r8a66597.h" - -#ifdef R8A66597_DEBUG -#define R8A66597_DPRINT printf -#else -#define R8A66597_DPRINT(...) -#endif - -static const char hcd_name[] = "r8a66597_hcd"; -static struct r8a66597 gr8a66597; - -static void get_hub_data(struct usb_device *dev, u16 *hub_devnum, u16 *hubport) -{ - int i; - - *hub_devnum = 0; - *hubport = 0; - - /* check a device connected to root_hub */ - if ((dev->parent && dev->parent->devnum == 1) || - (dev->devnum == 1)) - return; - - for (i = 0; i < USB_MAXCHILDREN; i++) { - if (dev->parent->children[i] == dev) { - *hub_devnum = (u8)dev->parent->devnum; - *hubport = i; - return; - } - } - - printf("get_hub_data error.\n"); -} - -static void set_devadd(struct r8a66597 *r8a66597, u8 r8a66597_address, - struct usb_device *dev, int port) -{ - u16 val, usbspd, upphub, hubport; - unsigned long devadd_reg = get_devadd_addr(r8a66597_address); - - get_hub_data(dev, &upphub, &hubport); - usbspd = r8a66597->speed; - val = (upphub << 11) | (hubport << 8) | (usbspd << 6) | (port & 0x0001); - r8a66597_write(r8a66597, val, devadd_reg); -} - -static int r8a66597_clock_enable(struct r8a66597 *r8a66597) -{ - u16 tmp; - int i = 0; - -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) - do { - r8a66597_write(r8a66597, SCKE, SYSCFG0); - tmp = r8a66597_read(r8a66597, SYSCFG0); - if (i++ > 1000) { - printf("register access fail.\n"); - return -1; - } - } while ((tmp & SCKE) != SCKE); - r8a66597_write(r8a66597, 0x04, 0x02); -#else - do { - r8a66597_write(r8a66597, USBE, SYSCFG0); - tmp = r8a66597_read(r8a66597, SYSCFG0); - if (i++ > 1000) { - printf("register access fail.\n"); - return -1; - } - } while ((tmp & USBE) != USBE); - r8a66597_bclr(r8a66597, USBE, SYSCFG0); - r8a66597_mdfy(r8a66597, CONFIG_R8A66597_XTAL, XTAL, SYSCFG0); - - i = 0; - r8a66597_bset(r8a66597, XCKE, SYSCFG0); - do { - udelay(1000); - tmp = r8a66597_read(r8a66597, SYSCFG0); - if (i++ > 500) { - printf("register access fail.\n"); - return -1; - } - } while ((tmp & SCKE) != SCKE); -#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */ - - return 0; -} - -static void r8a66597_clock_disable(struct r8a66597 *r8a66597) -{ - r8a66597_bclr(r8a66597, SCKE, SYSCFG0); - udelay(1); -#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597) - r8a66597_bclr(r8a66597, PLLC, SYSCFG0); - r8a66597_bclr(r8a66597, XCKE, SYSCFG0); - r8a66597_bclr(r8a66597, USBE, SYSCFG0); -#endif -} - -static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port) -{ - u16 val; - - val = port ? DRPD : DCFM | DRPD; - r8a66597_bset(r8a66597, val, get_syscfg_reg(port)); - r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port)); - - r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port)); -} - -static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port) -{ - u16 val, tmp; - - r8a66597_write(r8a66597, 0, get_intenb_reg(port)); - r8a66597_write(r8a66597, 0, get_intsts_reg(port)); - - r8a66597_port_power(r8a66597, port, 0); - - do { - tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS; - udelay(640); - } while (tmp == EDGESTS); - - val = port ? DRPD : DCFM | DRPD; - r8a66597_bclr(r8a66597, val, get_syscfg_reg(port)); - r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port)); -} - -static int enable_controller(struct r8a66597 *r8a66597) -{ - int ret, port; - - ret = r8a66597_clock_enable(r8a66597); - if (ret < 0) - return ret; - - r8a66597_bset(r8a66597, CONFIG_R8A66597_LDRV & LDRV, PINCFG); - r8a66597_bset(r8a66597, USBE, SYSCFG0); - - r8a66597_bset(r8a66597, INTL, SOFCFG); - r8a66597_write(r8a66597, 0, INTENB0); - r8a66597_write(r8a66597, 0, INTENB1); - r8a66597_write(r8a66597, 0, INTENB2); - - r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, CFIFOSEL); - r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, D0FIFOSEL); - r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, D1FIFOSEL); - r8a66597_bset(r8a66597, TRNENSEL, SOFCFG); - - for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) - r8a66597_enable_port(r8a66597, port); - - return 0; -} - -static void disable_controller(struct r8a66597 *r8a66597) -{ - int i; - - if (!(r8a66597_read(r8a66597, SYSCFG0) & USBE)) - return; - - r8a66597_write(r8a66597, 0, INTENB0); - r8a66597_write(r8a66597, 0, INTSTS0); - - r8a66597_write(r8a66597, 0, D0FIFOSEL); - r8a66597_write(r8a66597, 0, D1FIFOSEL); - r8a66597_write(r8a66597, 0, DCPCFG); - r8a66597_write(r8a66597, 0x40, DCPMAXP); - r8a66597_write(r8a66597, 0, DCPCTR); - - for (i = 0; i <= 10; i++) - r8a66597_write(r8a66597, 0, get_devadd_addr(i)); - for (i = 1; i <= 5; i++) { - r8a66597_write(r8a66597, 0, get_pipetre_addr(i)); - r8a66597_write(r8a66597, 0, get_pipetrn_addr(i)); - } - for (i = 1; i < R8A66597_MAX_NUM_PIPE; i++) { - r8a66597_write(r8a66597, 0, get_pipectr_addr(i)); - r8a66597_write(r8a66597, i, PIPESEL); - r8a66597_write(r8a66597, 0, PIPECFG); - r8a66597_write(r8a66597, 0, PIPEBUF); - r8a66597_write(r8a66597, 0, PIPEMAXP); - r8a66597_write(r8a66597, 0, PIPEPERI); - } - - for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++) - r8a66597_disable_port(r8a66597, i); - - r8a66597_clock_disable(r8a66597); -} - -static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg, - u16 mask, u16 loop) -{ - u16 tmp; - int i = 0; - - do { - tmp = r8a66597_read(r8a66597, reg); - if (i++ > 1000000) { - printf("register%lx, loop %x is timeout\n", reg, loop); - break; - } - } while ((tmp & mask) != loop); -} - -static void pipe_buffer_setting(struct r8a66597 *r8a66597, - struct usb_device *dev, unsigned long pipe) -{ - u16 val = 0; - u16 pipenum, bufnum, maxpacket; - - if (usb_pipein(pipe)) { - pipenum = BULK_IN_PIPENUM; - bufnum = BULK_IN_BUFNUM; - maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)]; - } else { - pipenum = BULK_OUT_PIPENUM; - bufnum = BULK_OUT_BUFNUM; - maxpacket = dev->epmaxpacketout[usb_pipeendpoint(pipe)]; - } - - if (r8a66597->pipe_config & (1 << pipenum)) - return; - r8a66597->pipe_config |= (1 << pipenum); - - r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(pipenum)); - r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(pipenum)); - r8a66597_write(r8a66597, pipenum, PIPESEL); - - /* FIXME: This driver support bulk transfer only. */ - if (!usb_pipein(pipe)) - val |= R8A66597_DIR; - else - val |= R8A66597_SHTNAK; - val |= R8A66597_BULK | R8A66597_DBLB | usb_pipeendpoint(pipe); - r8a66597_write(r8a66597, val, PIPECFG); - - r8a66597_write(r8a66597, (8 << 10) | bufnum, PIPEBUF); - r8a66597_write(r8a66597, make_devsel(usb_pipedevice(pipe)) | - maxpacket, PIPEMAXP); - r8a66597_write(r8a66597, 0, PIPEPERI); - r8a66597_write(r8a66597, SQCLR, get_pipectr_addr(pipenum)); -} - -static int send_setup_packet(struct r8a66597 *r8a66597, struct usb_device *dev, - struct devrequest *setup) -{ - int i; - unsigned short *p = (unsigned short *)setup; - unsigned long setup_addr = USBREQ; - u16 intsts1; - int timeout = 3000; - u16 devsel = setup->request == USB_REQ_SET_ADDRESS ? 0 : dev->devnum; - - r8a66597_write(r8a66597, make_devsel(devsel) | - (8 << dev->maxpacketsize), DCPMAXP); - r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1); - - for (i = 0; i < 4; i++) { - r8a66597_write(r8a66597, le16_to_cpu(p[i]), setup_addr); - setup_addr += 2; - } - r8a66597_write(r8a66597, ~0x0001, BRDYSTS); - r8a66597_write(r8a66597, SUREQ, DCPCTR); - - while (1) { - intsts1 = r8a66597_read(r8a66597, INTSTS1); - if (intsts1 & SACK) - break; - if (intsts1 & SIGN) { - printf("setup packet send error\n"); - return -1; - } - if (timeout-- < 0) { - printf("setup packet timeout\n"); - return -1; - } - udelay(500); - } - - return 0; -} - -static int send_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev, - unsigned long pipe, void *buffer, int transfer_len) -{ - u16 tmp, bufsize; - u16 *buf; - size_t size; - - R8A66597_DPRINT("%s\n", __func__); - - r8a66597_mdfy(r8a66597, MBW | BULK_OUT_PIPENUM, - MBW | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, BULK_OUT_PIPENUM); - tmp = r8a66597_read(r8a66597, CFIFOCTR); - if ((tmp & FRDY) == 0) { - printf("%s FRDY is not set (%x)\n", __func__, tmp); - return -1; - } - - /* prepare parameters */ - bufsize = dev->epmaxpacketout[usb_pipeendpoint(pipe)]; - buf = (u16 *)(buffer + dev->act_len); - size = min((int)bufsize, transfer_len - dev->act_len); - - /* write fifo */ - r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS); - if (buffer) { - r8a66597_write_fifo(r8a66597, CFIFO, buf, size); - r8a66597_write(r8a66597, BVAL, CFIFOCTR); - } - - /* update parameters */ - dev->act_len += size; - - r8a66597_mdfy(r8a66597, PID_BUF, PID, - get_pipectr_addr(BULK_OUT_PIPENUM)); - - while (!(r8a66597_read(r8a66597, BEMPSTS) & (1 << BULK_OUT_PIPENUM))) - if (ctrlc()) - return -1; - r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS); - - if (dev->act_len >= transfer_len) - r8a66597_mdfy(r8a66597, PID_NAK, PID, - get_pipectr_addr(BULK_OUT_PIPENUM)); - - return 0; -} - -static int receive_bulk_packet(struct r8a66597 *r8a66597, - struct usb_device *dev, - unsigned long pipe, - void *buffer, int transfer_len) -{ - u16 tmp; - u16 *buf; - const u16 pipenum = BULK_IN_PIPENUM; - int rcv_len; - int maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)]; - - R8A66597_DPRINT("%s\n", __func__); - - /* prepare */ - if (dev->act_len == 0) { - r8a66597_mdfy(r8a66597, PID_NAK, PID, - get_pipectr_addr(pipenum)); - r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS); - - r8a66597_write(r8a66597, TRCLR, get_pipetre_addr(pipenum)); - r8a66597_write(r8a66597, - (transfer_len + maxpacket - 1) / maxpacket, - get_pipetrn_addr(pipenum)); - r8a66597_bset(r8a66597, TRENB, get_pipetre_addr(pipenum)); - - r8a66597_mdfy(r8a66597, PID_BUF, PID, - get_pipectr_addr(pipenum)); - } - - r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum); - - while (!(r8a66597_read(r8a66597, BRDYSTS) & (1 << pipenum))) - if (ctrlc()) - return -1; - r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS); - - tmp = r8a66597_read(r8a66597, CFIFOCTR); - if ((tmp & FRDY) == 0) { - printf("%s FRDY is not set. (%x)\n", __func__, tmp); - return -1; - } - - buf = (u16 *)(buffer + dev->act_len); - rcv_len = tmp & DTLN; - dev->act_len += rcv_len; - - if (buffer) { - if (rcv_len == 0) - r8a66597_write(r8a66597, BCLR, CFIFOCTR); - else - r8a66597_read_fifo(r8a66597, CFIFO, buf, rcv_len); - } - - return 0; -} - -static int receive_control_packet(struct r8a66597 *r8a66597, - struct usb_device *dev, - void *buffer, int transfer_len) -{ - u16 tmp; - int rcv_len; - - /* FIXME: limit transfer size : 64byte or less */ - - r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); - r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); - r8a66597_bset(r8a66597, SQSET, DCPCTR); - r8a66597_write(r8a66597, BCLR, CFIFOCTR); - r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR); - - while (!(r8a66597_read(r8a66597, BRDYSTS) & 0x0001)) - if (ctrlc()) - return -1; - r8a66597_write(r8a66597, ~0x0001, BRDYSTS); - - r8a66597_mdfy(r8a66597, MBW, MBW | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); - - tmp = r8a66597_read(r8a66597, CFIFOCTR); - if ((tmp & FRDY) == 0) { - printf("%s FRDY is not set. (%x)\n", __func__, tmp); - return -1; - } - - rcv_len = tmp & DTLN; - dev->act_len += rcv_len; - - r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR); - - if (buffer) { - if (rcv_len == 0) - r8a66597_write(r8a66597, BCLR, DCPCTR); - else - r8a66597_read_fifo(r8a66597, CFIFO, buffer, rcv_len); - } - - return 0; -} - -static int send_status_packet(struct r8a66597 *r8a66597, - unsigned long pipe) -{ - r8a66597_bset(r8a66597, SQSET, DCPCTR); - r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR); - - if (usb_pipein(pipe)) { - r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG); - r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); - r8a66597_write(r8a66597, ~BEMP0, BEMPSTS); - r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR); - } else { - r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); - r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); - r8a66597_write(r8a66597, BCLR, CFIFOCTR); - } - r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR); - - while (!(r8a66597_read(r8a66597, BEMPSTS) & 0x0001)) - if (ctrlc()) - return -1; - - return 0; -} - -static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port) -{ - int count = R8A66597_MAX_SAMPLING; - unsigned short syssts, old_syssts; - - R8A66597_DPRINT("%s\n", __func__); - - old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST); - while (count > 0) { - mdelay(R8A66597_RH_POLL_TIME); - - syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST); - if (syssts == old_syssts) { - count--; - } else { - count = R8A66597_MAX_SAMPLING; - old_syssts = syssts; - } - } -} - -static void r8a66597_bus_reset(struct r8a66597 *r8a66597, int port) -{ - mdelay(10); - r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, get_dvstctr_reg(port)); - mdelay(50); - r8a66597_mdfy(r8a66597, UACT, USBRST | UACT, get_dvstctr_reg(port)); - mdelay(50); -} - -static int check_usb_device_connecting(struct r8a66597 *r8a66597) -{ - int timeout = 10000; /* 100usec * 10000 = 1sec */ - int i; - - for (i = 0; i < 5; i++) { - /* check a usb cable connect */ - while (!(r8a66597_read(r8a66597, INTSTS1) & ATTCH)) { - if (timeout-- < 0) { - printf("%s timeout.\n", __func__); - return -1; - } - udelay(100); - } - - /* check a data line */ - r8a66597_check_syssts(r8a66597, 0); - - r8a66597_bus_reset(r8a66597, 0); - r8a66597->speed = get_rh_usb_speed(r8a66597, 0); - - if (!(r8a66597_read(r8a66597, INTSTS1) & DTCH)) { - r8a66597->port_change = USB_PORT_STAT_C_CONNECTION; - r8a66597->port_status = USB_PORT_STAT_CONNECTION | - USB_PORT_STAT_ENABLE; - return 0; /* success */ - } - - R8A66597_DPRINT("USB device has detached. retry = %d\n", i); - r8a66597_write(r8a66597, ~DTCH, INTSTS1); - } - - return -1; /* fail */ -} - -/* based on usb_ohci.c */ -#define min_t(type, x, y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; }) -/*-------------------------------------------------------------------------* - * Virtual Root Hub - *-------------------------------------------------------------------------*/ - -#include <usbroothubdes.h> - -static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, struct devrequest *cmd) -{ - struct r8a66597 *r8a66597 = &gr8a66597; - int leni = transfer_len; - int len = 0; - int stat = 0; - __u16 bmRType_bReq; - __u16 wValue; - __u16 wLength; - unsigned char data[32]; - - R8A66597_DPRINT("%s\n", __func__); - - if (usb_pipeint(pipe)) { - printf("Root-Hub submit IRQ: NOT implemented"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = cpu_to_le16 (cmd->value); - wLength = cpu_to_le16 (cmd->length); - - switch (bmRType_bReq) { - case RH_GET_STATUS: - *(__u16 *)buffer = cpu_to_le16(1); - len = 2; - break; - case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *)buffer = cpu_to_le16(0); - len = 2; - break; - case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *)buffer = cpu_to_le16(0); - len = 2; - break; - case RH_GET_STATUS | RH_CLASS: - *(__u32 *)buffer = cpu_to_le32(0); - len = 4; - break; - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - *(__u32 *)buffer = cpu_to_le32(r8a66597->port_status | - (r8a66597->port_change << 16)); - len = 4; - break; - case RH_CLEAR_FEATURE | RH_ENDPOINT: - case RH_CLEAR_FEATURE | RH_CLASS: - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case RH_C_PORT_CONNECTION: - r8a66597->port_change &= ~USB_PORT_STAT_C_CONNECTION; - break; - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - break; - case (RH_PORT_RESET): - r8a66597_bus_reset(r8a66597, 0); - break; - case (RH_PORT_POWER): - break; - case (RH_PORT_ENABLE): - break; - } - break; - case RH_SET_ADDRESS: - gr8a66597.rh_devnum = wValue; - break; - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_dev_des), - wLength)); - memcpy(buffer, root_hub_dev_des, len); - break; - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_config_des), - wLength)); - memcpy(buffer, root_hub_config_des, len); - break; - case (0x03): /* string descriptors */ - if (wValue == 0x0300) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index0), - wLength)); - memcpy(buffer, root_hub_str_index0, len); - } - if (wValue == 0x0301) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index1), - wLength)); - memcpy(buffer, root_hub_str_index1, len); - } - break; - default: - stat = USB_ST_STALLED; - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - { - __u32 temp = 0x00000001; - - data[0] = 9; /* min length; */ - data[1] = 0x29; - data[2] = temp & RH_A_NDP; - data[3] = 0; - if (temp & RH_A_PSM) - data[3] |= 0x1; - if (temp & RH_A_NOCP) - data[3] |= 0x10; - else if (temp & RH_A_OCPM) - data[3] |= 0x8; - - /* corresponds to data[4-7] */ - data[5] = (temp & RH_A_POTPGT) >> 24; - data[7] = temp & RH_B_DR; - if (data[2] < 7) { - data[8] = 0xff; - } else { - data[0] += 2; - data[8] = (temp & RH_B_DR) >> 8; - data[10] = data[9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, data[0], wLength)); - memcpy(buffer, data, len); - break; - } - - case RH_GET_CONFIGURATION: - *(__u8 *) buffer = 0x01; - len = 1; - break; - case RH_SET_CONFIGURATION: - break; - default: - R8A66597_DPRINT("unsupported root hub command"); - stat = USB_ST_STALLED; - } - - mdelay(1); - - len = min_t(int, len, leni); - - dev->act_len = len; - dev->status = stat; - - return stat; -} - -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len) -{ - struct r8a66597 *r8a66597 = &gr8a66597; - int ret = 0; - - R8A66597_DPRINT("%s\n", __func__); - R8A66597_DPRINT("pipe = %08x, buffer = %p, len = %d, devnum = %d\n", - pipe, buffer, transfer_len, dev->devnum); - - set_devadd(r8a66597, dev->devnum, dev, 0); - - pipe_buffer_setting(r8a66597, dev, pipe); - - dev->act_len = 0; - while (dev->act_len < transfer_len && ret == 0) { - if (ctrlc()) - return -1; - - if (usb_pipein(pipe)) - ret = receive_bulk_packet(r8a66597, dev, pipe, buffer, - transfer_len); - else - ret = send_bulk_packet(r8a66597, dev, pipe, buffer, - transfer_len); - } - - if (ret == 0) - dev->status = 0; - - return ret; -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, struct devrequest *setup) -{ - struct r8a66597 *r8a66597 = &gr8a66597; - u16 r8a66597_address = setup->request == USB_REQ_SET_ADDRESS ? - 0 : dev->devnum; - - R8A66597_DPRINT("%s\n", __func__); - if (usb_pipedevice(pipe) == r8a66597->rh_devnum) - return r8a66597_submit_rh_msg(dev, pipe, buffer, transfer_len, - setup); - - R8A66597_DPRINT("%s: setup\n", __func__); - set_devadd(r8a66597, r8a66597_address, dev, 0); - - if (send_setup_packet(r8a66597, dev, setup) < 0) { - printf("setup packet send error\n"); - return -1; - } - - dev->act_len = 0; - if (usb_pipein(pipe)) - if (receive_control_packet(r8a66597, dev, buffer, - transfer_len) < 0) - return -1; - - if (send_status_packet(r8a66597, pipe) < 0) - return -1; - - dev->status = 0; - - return 0; -} - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, int interval) -{ - /* no implement */ - R8A66597_DPRINT("%s\n", __func__); - return 0; -} - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - struct r8a66597 *r8a66597 = &gr8a66597; - - R8A66597_DPRINT("%s\n", __func__); - - memset(r8a66597, 0, sizeof(r8a66597)); - r8a66597->reg = CONFIG_R8A66597_BASE_ADDR; - - disable_controller(r8a66597); - mdelay(100); - - enable_controller(r8a66597); - r8a66597_port_power(r8a66597, 0 , 1); - - /* check usb device */ - check_usb_device_connecting(r8a66597); - - mdelay(50); - - return 0; -} - -int usb_lowlevel_stop(int index) -{ - disable_controller(&gr8a66597); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/r8a66597.h b/qemu/roms/u-boot/drivers/usb/host/r8a66597.h deleted file mode 100644 index ca1b67155..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/r8a66597.h +++ /dev/null @@ -1,659 +0,0 @@ -/* - * R8A66597 HCD (Host Controller Driver) for u-boot - * - * Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.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; version 2 of the License. - * - * 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __R8A66597_H__ -#define __R8A66597_H__ - -#define SYSCFG0 0x00 -#define SYSCFG1 0x02 -#define SYSSTS0 0x04 -#define SYSSTS1 0x06 -#define DVSTCTR0 0x08 -#define DVSTCTR1 0x0A -#define TESTMODE 0x0C -#define PINCFG 0x0E -#define DMA0CFG 0x10 -#define DMA1CFG 0x12 -#define CFIFO 0x14 -#define D0FIFO 0x18 -#define D1FIFO 0x1C -#define CFIFOSEL 0x20 -#define CFIFOCTR 0x22 -#define CFIFOSIE 0x24 -#define D0FIFOSEL 0x28 -#define D0FIFOCTR 0x2A -#define D1FIFOSEL 0x2C -#define D1FIFOCTR 0x2E -#define INTENB0 0x30 -#define INTENB1 0x32 -#define INTENB2 0x34 -#define BRDYENB 0x36 -#define NRDYENB 0x38 -#define BEMPENB 0x3A -#define SOFCFG 0x3C -#define INTSTS0 0x40 -#define INTSTS1 0x42 -#define INTSTS2 0x44 -#define BRDYSTS 0x46 -#define NRDYSTS 0x48 -#define BEMPSTS 0x4A -#define FRMNUM 0x4C -#define UFRMNUM 0x4E -#define USBADDR 0x50 -#define USBREQ 0x54 -#define USBVAL 0x56 -#define USBINDX 0x58 -#define USBLENG 0x5A -#define DCPCFG 0x5C -#define DCPMAXP 0x5E -#define DCPCTR 0x60 -#define PIPESEL 0x64 -#define PIPECFG 0x68 -#define PIPEBUF 0x6A -#define PIPEMAXP 0x6C -#define PIPEPERI 0x6E -#define PIPE1CTR 0x70 -#define PIPE2CTR 0x72 -#define PIPE3CTR 0x74 -#define PIPE4CTR 0x76 -#define PIPE5CTR 0x78 -#define PIPE6CTR 0x7A -#define PIPE7CTR 0x7C -#define PIPE8CTR 0x7E -#define PIPE9CTR 0x80 -#define PIPE1TRE 0x90 -#define PIPE1TRN 0x92 -#define PIPE2TRE 0x94 -#define PIPE2TRN 0x96 -#define PIPE3TRE 0x98 -#define PIPE3TRN 0x9A -#define PIPE4TRE 0x9C -#define PIPE4TRN 0x9E -#define PIPE5TRE 0xA0 -#define PIPE5TRN 0xA2 -#define DEVADD0 0xD0 -#define DEVADD1 0xD2 -#define DEVADD2 0xD4 -#define DEVADD3 0xD6 -#define DEVADD4 0xD8 -#define DEVADD5 0xDA -#define DEVADD6 0xDC -#define DEVADD7 0xDE -#define DEVADD8 0xE0 -#define DEVADD9 0xE2 -#define DEVADDA 0xE4 - -/* System Configuration Control Register */ -#define XTAL 0xC000 /* b15-14: Crystal selection */ -#define XTAL48 0x8000 /* 48MHz */ -#define XTAL24 0x4000 /* 24MHz */ -#define XTAL12 0x0000 /* 12MHz */ -#define XCKE 0x2000 /* b13: External clock enable */ -#define PLLC 0x0800 /* b11: PLL control */ -#define SCKE 0x0400 /* b10: USB clock enable */ -#define PCSDIS 0x0200 /* b9: not CS wakeup */ -#define LPSME 0x0100 /* b8: Low power sleep mode */ -#define HSE 0x0080 /* b7: Hi-speed enable */ -#define DCFM 0x0040 /* b6: Controller function select */ -#define DRPD 0x0020 /* b5: D+/- pull down control */ -#define DPRPU 0x0010 /* b4: D+ pull up control */ -#define USBE 0x0001 /* b0: USB module operation enable */ - -/* System Configuration Status Register */ -#define OVCBIT 0x8000 /* b15-14: Over-current bit */ -#define OVCMON 0xC000 /* b15-14: Over-current monitor */ -#define SOFEA 0x0020 /* b5: SOF monitor */ -#define IDMON 0x0004 /* b3: ID-pin monitor */ -#define LNST 0x0003 /* b1-0: D+, D- line status */ -#define SE1 0x0003 /* SE1 */ -#define FS_KSTS 0x0002 /* Full-Speed K State */ -#define FS_JSTS 0x0001 /* Full-Speed J State */ -#define LS_JSTS 0x0002 /* Low-Speed J State */ -#define LS_KSTS 0x0001 /* Low-Speed K State */ -#define SE0 0x0000 /* SE0 */ - -/* Device State Control Register */ -#define EXTLP0 0x0400 /* b10: External port */ -#define VBOUT 0x0200 /* b9: VBUS output */ -#define WKUP 0x0100 /* b8: Remote wakeup */ -#define RWUPE 0x0080 /* b7: Remote wakeup sense */ -#define USBRST 0x0040 /* b6: USB reset enable */ -#define RESUME 0x0020 /* b5: Resume enable */ -#define UACT 0x0010 /* b4: USB bus enable */ -#define RHST 0x0007 /* b1-0: Reset handshake status */ -#define HSPROC 0x0004 /* HS handshake is processing */ -#define HSMODE 0x0003 /* Hi-Speed mode */ -#define FSMODE 0x0002 /* Full-Speed mode */ -#define LSMODE 0x0001 /* Low-Speed mode */ -#define UNDECID 0x0000 /* Undecided */ - -/* Test Mode Register */ -#define UTST 0x000F /* b3-0: Test select */ -#define H_TST_PACKET 0x000C /* HOST TEST Packet */ -#define H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */ -#define H_TST_K 0x000A /* HOST TEST K */ -#define H_TST_J 0x0009 /* HOST TEST J */ -#define H_TST_NORMAL 0x0000 /* HOST Normal Mode */ -#define P_TST_PACKET 0x0004 /* PERI TEST Packet */ -#define P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */ -#define P_TST_K 0x0002 /* PERI TEST K */ -#define P_TST_J 0x0001 /* PERI TEST J */ -#define P_TST_NORMAL 0x0000 /* PERI Normal Mode */ - -/* Data Pin Configuration Register */ -#define LDRV 0x8000 /* b15: Drive Current Adjust */ -#define VIF1 0x0000 /* VIF = 1.8V */ -#define VIF3 0x8000 /* VIF = 3.3V */ -#define INTA 0x0001 /* b1: USB INT-pin active */ - -/* DMAx Pin Configuration Register */ -#define DREQA 0x4000 /* b14: Dreq active select */ -#define BURST 0x2000 /* b13: Burst mode */ -#define DACKA 0x0400 /* b10: Dack active select */ -#define DFORM 0x0380 /* b9-7: DMA mode select */ -#define CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */ -#define CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */ -#define CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */ -#define SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */ -#define DENDA 0x0040 /* b6: Dend active select */ -#define PKTM 0x0020 /* b5: Packet mode */ -#define DENDE 0x0010 /* b4: Dend enable */ -#define OBUS 0x0004 /* b2: OUTbus mode */ - -/* CFIFO/DxFIFO Port Select Register */ -#define RCNT 0x8000 /* b15: Read count mode */ -#define REW 0x4000 /* b14: Buffer rewind */ -#define DCLRM 0x2000 /* b13: DMA buffer clear mode */ -#define DREQE 0x1000 /* b12: DREQ output enable */ -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) -#define MBW 0x0800 -#else -#define MBW 0x0400 /* b10: Maximum bit width for FIFO access */ -#endif -#define MBW_8 0x0000 /* 8bit */ -#define MBW_16 0x0400 /* 16bit */ -#define BIGEND 0x0100 /* b8: Big endian mode */ -#define BYTE_LITTLE 0x0000 /* little dendian */ -#define BYTE_BIG 0x0100 /* big endifan */ -#define ISEL 0x0020 /* b5: DCP FIFO port direction select */ -#define CURPIPE 0x000F /* b2-0: PIPE select */ - -/* CFIFO/DxFIFO Port Control Register */ -#define BVAL 0x8000 /* b15: Buffer valid flag */ -#define BCLR 0x4000 /* b14: Buffer clear */ -#define FRDY 0x2000 /* b13: FIFO ready */ -#define DTLN 0x0FFF /* b11-0: FIFO received data length */ - -/* Interrupt Enable Register 0 */ -#define VBSE 0x8000 /* b15: VBUS interrupt */ -#define RSME 0x4000 /* b14: Resume interrupt */ -#define SOFE 0x2000 /* b13: Frame update interrupt */ -#define DVSE 0x1000 /* b12: Device state transition interrupt */ -#define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */ -#define BEMPE 0x0400 /* b10: Buffer empty interrupt */ -#define NRDYE 0x0200 /* b9: Buffer not ready interrupt */ -#define BRDYE 0x0100 /* b8: Buffer ready interrupt */ - -/* Interrupt Enable Register 1 */ -#define OVRCRE 0x8000 /* b15: Over-current interrupt */ -#define BCHGE 0x4000 /* b14: USB us chenge interrupt */ -#define DTCHE 0x1000 /* b12: Detach sense interrupt */ -#define ATTCHE 0x0800 /* b11: Attach sense interrupt */ -#define EOFERRE 0x0040 /* b6: EOF error interrupt */ -#define SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */ -#define SACKE 0x0010 /* b4: SETUP ACK interrupt */ - -/* BRDY Interrupt Enable/Status Register */ -#define BRDY9 0x0200 /* b9: PIPE9 */ -#define BRDY8 0x0100 /* b8: PIPE8 */ -#define BRDY7 0x0080 /* b7: PIPE7 */ -#define BRDY6 0x0040 /* b6: PIPE6 */ -#define BRDY5 0x0020 /* b5: PIPE5 */ -#define BRDY4 0x0010 /* b4: PIPE4 */ -#define BRDY3 0x0008 /* b3: PIPE3 */ -#define BRDY2 0x0004 /* b2: PIPE2 */ -#define BRDY1 0x0002 /* b1: PIPE1 */ -#define BRDY0 0x0001 /* b1: PIPE0 */ - -/* NRDY Interrupt Enable/Status Register */ -#define NRDY9 0x0200 /* b9: PIPE9 */ -#define NRDY8 0x0100 /* b8: PIPE8 */ -#define NRDY7 0x0080 /* b7: PIPE7 */ -#define NRDY6 0x0040 /* b6: PIPE6 */ -#define NRDY5 0x0020 /* b5: PIPE5 */ -#define NRDY4 0x0010 /* b4: PIPE4 */ -#define NRDY3 0x0008 /* b3: PIPE3 */ -#define NRDY2 0x0004 /* b2: PIPE2 */ -#define NRDY1 0x0002 /* b1: PIPE1 */ -#define NRDY0 0x0001 /* b1: PIPE0 */ - -/* BEMP Interrupt Enable/Status Register */ -#define BEMP9 0x0200 /* b9: PIPE9 */ -#define BEMP8 0x0100 /* b8: PIPE8 */ -#define BEMP7 0x0080 /* b7: PIPE7 */ -#define BEMP6 0x0040 /* b6: PIPE6 */ -#define BEMP5 0x0020 /* b5: PIPE5 */ -#define BEMP4 0x0010 /* b4: PIPE4 */ -#define BEMP3 0x0008 /* b3: PIPE3 */ -#define BEMP2 0x0004 /* b2: PIPE2 */ -#define BEMP1 0x0002 /* b1: PIPE1 */ -#define BEMP0 0x0001 /* b0: PIPE0 */ - -/* SOF Pin Configuration Register */ -#define TRNENSEL 0x0100 /* b8: Select transaction enable period */ -#define BRDYM 0x0040 /* b6: BRDY clear timing */ -#define INTL 0x0020 /* b5: Interrupt sense select */ -#define EDGESTS 0x0010 /* b4: */ -#define SOFMODE 0x000C /* b3-2: SOF pin select */ -#define SOF_125US 0x0008 /* SOF OUT 125us Frame Signal */ -#define SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */ -#define SOF_DISABLE 0x0000 /* SOF OUT Disable */ - -/* Interrupt Status Register 0 */ -#define VBINT 0x8000 /* b15: VBUS interrupt */ -#define RESM 0x4000 /* b14: Resume interrupt */ -#define SOFR 0x2000 /* b13: SOF frame update interrupt */ -#define DVST 0x1000 /* b12: Device state transition interrupt */ -#define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */ -#define BEMP 0x0400 /* b10: Buffer empty interrupt */ -#define NRDY 0x0200 /* b9: Buffer not ready interrupt */ -#define BRDY 0x0100 /* b8: Buffer ready interrupt */ -#define VBSTS 0x0080 /* b7: VBUS input port */ -#define DVSQ 0x0070 /* b6-4: Device state */ -#define DS_SPD_CNFG 0x0070 /* Suspend Configured */ -#define DS_SPD_ADDR 0x0060 /* Suspend Address */ -#define DS_SPD_DFLT 0x0050 /* Suspend Default */ -#define DS_SPD_POWR 0x0040 /* Suspend Powered */ -#define DS_SUSP 0x0040 /* Suspend */ -#define DS_CNFG 0x0030 /* Configured */ -#define DS_ADDS 0x0020 /* Address */ -#define DS_DFLT 0x0010 /* Default */ -#define DS_POWR 0x0000 /* Powered */ -#define DVSQS 0x0030 /* b5-4: Device state */ -#define VALID 0x0008 /* b3: Setup packet detected flag */ -#define CTSQ 0x0007 /* b2-0: Control transfer stage */ -#define CS_SQER 0x0006 /* Sequence error */ -#define CS_WRND 0x0005 /* Control write nodata status stage */ -#define CS_WRSS 0x0004 /* Control write status stage */ -#define CS_WRDS 0x0003 /* Control write data stage */ -#define CS_RDSS 0x0002 /* Control read status stage */ -#define CS_RDDS 0x0001 /* Control read data stage */ -#define CS_IDST 0x0000 /* Idle or setup stage */ - -/* Interrupt Status Register 1 */ -#define OVRCR 0x8000 /* b15: Over-current interrupt */ -#define BCHG 0x4000 /* b14: USB bus chenge interrupt */ -#define DTCH 0x1000 /* b12: Detach sense interrupt */ -#define ATTCH 0x0800 /* b11: Attach sense interrupt */ -#define EOFERR 0x0040 /* b6: EOF-error interrupt */ -#define SIGN 0x0020 /* b5: Setup ignore interrupt */ -#define SACK 0x0010 /* b4: Setup acknowledge interrupt */ - -/* Frame Number Register */ -#define OVRN 0x8000 /* b15: Overrun error */ -#define CRCE 0x4000 /* b14: Received data error */ -#define FRNM 0x07FF /* b10-0: Frame number */ - -/* Micro Frame Number Register */ -#define UFRNM 0x0007 /* b2-0: Micro frame number */ - -/* Default Control Pipe Maxpacket Size Register */ -/* Pipe Maxpacket Size Register */ -#define DEVSEL 0xF000 /* b15-14: Device address select */ -#define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */ - -/* Default Control Pipe Control Register */ -#define BSTS 0x8000 /* b15: Buffer status */ -#define SUREQ 0x4000 /* b14: Send USB request */ -#define CSCLR 0x2000 /* b13: complete-split status clear */ -#define CSSTS 0x1000 /* b12: complete-split status */ -#define SUREQCLR 0x0800 /* b11: stop setup request */ -#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ -#define SQSET 0x0080 /* b7: Sequence toggle bit set */ -#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ -#define PBUSY 0x0020 /* b5: pipe busy */ -#define PINGE 0x0010 /* b4: ping enable */ -#define CCPL 0x0004 /* b2: Enable control transfer complete */ -#define PID 0x0003 /* b1-0: Response PID */ -#define PID_STALL11 0x0003 /* STALL */ -#define PID_STALL 0x0002 /* STALL */ -#define PID_BUF 0x0001 /* BUF */ -#define PID_NAK 0x0000 /* NAK */ - -/* Pipe Window Select Register */ -#define PIPENM 0x0007 /* b2-0: Pipe select */ - -/* Pipe Configuration Register */ -#define R8A66597_TYP 0xC000 /* b15-14: Transfer type */ -#define R8A66597_ISO 0xC000 /* Isochronous */ -#define R8A66597_INT 0x8000 /* Interrupt */ -#define R8A66597_BULK 0x4000 /* Bulk */ -#define R8A66597_BFRE 0x0400 /* b10: Buffer ready interrupt mode select */ -#define R8A66597_DBLB 0x0200 /* b9: Double buffer mode select */ -#define R8A66597_CNTMD 0x0100 /* b8: Continuous transfer mode select */ -#define R8A66597_SHTNAK 0x0080 /* b7: Transfer end NAK */ -#define R8A66597_DIR 0x0010 /* b4: Transfer direction select */ -#define R8A66597_EPNUM 0x000F /* b3-0: Eendpoint number select */ - -/* Pipe Buffer Configuration Register */ -#define BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */ -#define BUFNMB 0x007F /* b6-0: Pipe buffer number */ -#define PIPE0BUF 256 -#define PIPExBUF 64 - -/* Pipe Maxpacket Size Register */ -#define MXPS 0x07FF /* b10-0: Maxpacket size */ - -/* Pipe Cycle Configuration Register */ -#define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */ -#define IITV 0x0007 /* b2-0: Isochronous interval */ - -/* Pipex Control Register */ -#define BSTS 0x8000 /* b15: Buffer status */ -#define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */ -#define CSCLR 0x2000 /* b13: complete-split status clear */ -#define CSSTS 0x1000 /* b12: complete-split status */ -#define ATREPM 0x0400 /* b10: Auto repeat mode */ -#define ACLRM 0x0200 /* b9: Out buffer auto clear mode */ -#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ -#define SQSET 0x0080 /* b7: Sequence toggle bit set */ -#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ -#define PBUSY 0x0020 /* b5: pipe busy */ -#define PID 0x0003 /* b1-0: Response PID */ - -/* PIPExTRE */ -#define TRENB 0x0200 /* b9: Transaction counter enable */ -#define TRCLR 0x0100 /* b8: Transaction counter clear */ - -/* PIPExTRN */ -#define TRNCNT 0xFFFF /* b15-0: Transaction counter */ - -/* DEVADDx */ -#define UPPHUB 0x7800 -#define HUBPORT 0x0700 -#define USBSPD 0x00C0 -#define RTPORT 0x0001 - -#define R8A66597_MAX_NUM_PIPE 10 -#define R8A66597_BUF_BSIZE 8 -#define R8A66597_MAX_DEVICE 10 -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) -#define R8A66597_MAX_ROOT_HUB 1 -#else -#define R8A66597_MAX_ROOT_HUB 2 -#endif -#define R8A66597_MAX_SAMPLING 5 -#define R8A66597_RH_POLL_TIME 10 - -#define BULK_IN_PIPENUM 3 -#define BULK_IN_BUFNUM 8 - -#define BULK_OUT_PIPENUM 4 -#define BULK_OUT_BUFNUM 40 - -#define check_bulk_or_isoc(pipenum) ((pipenum >= 1 && pipenum <= 5)) -#define check_interrupt(pipenum) ((pipenum >= 6 && pipenum <= 9)) -#define make_devsel(addr) (addr << 12) - -struct r8a66597 { - unsigned long reg; - unsigned short pipe_config; /* bit field */ - unsigned short port_status; - unsigned short port_change; - u16 speed; /* HSMODE or FSMODE or LSMODE */ - unsigned char rh_devnum; -}; - -static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset) -{ - return inw(r8a66597->reg + offset); -} - -static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, - unsigned long offset, void *buf, - int len) -{ - int i; -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) - unsigned long fifoaddr = r8a66597->reg + offset; - unsigned long count; - unsigned long *p = buf; - - count = len / 4; - for (i = 0; i < count; i++) - p[i] = inl(r8a66597->reg + offset); - - if (len & 0x00000003) { - unsigned long tmp = inl(fifoaddr); - memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03); - } -#else - unsigned short *p = buf; - - len = (len + 1) / 2; - for (i = 0; i < len; i++) - p[i] = inw(r8a66597->reg + offset); -#endif -} - -static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, - unsigned long offset) -{ - outw(val, r8a66597->reg + offset); -} - -static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, - unsigned long offset, void *buf, - int len) -{ - int i; - unsigned long fifoaddr = r8a66597->reg + offset; -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) - unsigned long count; - unsigned char *pb; - unsigned long *p = buf; - - count = len / 4; - for (i = 0; i < count; i++) - outl(p[i], fifoaddr); - - if (len & 0x00000003) { - pb = (unsigned char *)buf + count * 4; - for (i = 0; i < (len & 0x00000003); i++) { - if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND) - outb(pb[i], fifoaddr + i); - else - outb(pb[i], fifoaddr + 3 - i); - } - } -#else - int odd = len & 0x0001; - unsigned short *p = buf; - - len = len / 2; - for (i = 0; i < len; i++) - outw(p[i], fifoaddr); - - if (odd) { - unsigned char *pb = (unsigned char *)(buf + len); - outb(*pb, fifoaddr); - } -#endif -} - -static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, - u16 val, u16 pat, unsigned long offset) -{ - u16 tmp; - tmp = r8a66597_read(r8a66597, offset); - tmp = tmp & (~pat); - tmp = tmp | val; - r8a66597_write(r8a66597, tmp, offset); -} - -#define r8a66597_bclr(r8a66597, val, offset) \ - r8a66597_mdfy(r8a66597, 0, val, offset) -#define r8a66597_bset(r8a66597, val, offset) \ - r8a66597_mdfy(r8a66597, val, 0, offset) - -static inline unsigned long get_syscfg_reg(int port) -{ - return port == 0 ? SYSCFG0 : SYSCFG1; -} - -static inline unsigned long get_syssts_reg(int port) -{ - return port == 0 ? SYSSTS0 : SYSSTS1; -} - -static inline unsigned long get_dvstctr_reg(int port) -{ - return port == 0 ? DVSTCTR0 : DVSTCTR1; -} - -static inline unsigned long get_dmacfg_reg(int port) -{ - return port == 0 ? DMA0CFG : DMA1CFG; -} - -static inline unsigned long get_intenb_reg(int port) -{ - return port == 0 ? INTENB1 : INTENB2; -} - -static inline unsigned long get_intsts_reg(int port) -{ - return port == 0 ? INTSTS1 : INTSTS2; -} - -static inline u16 get_rh_usb_speed(struct r8a66597 *r8a66597, int port) -{ - unsigned long dvstctr_reg = get_dvstctr_reg(port); - - return r8a66597_read(r8a66597, dvstctr_reg) & RHST; -} - -static inline void r8a66597_port_power(struct r8a66597 *r8a66597, int port, - int power) -{ - unsigned long dvstctr_reg = get_dvstctr_reg(port); - - if (power) - r8a66597_bset(r8a66597, VBOUT, dvstctr_reg); - else - r8a66597_bclr(r8a66597, VBOUT, dvstctr_reg); -} - -#define get_pipectr_addr(pipenum) (PIPE1CTR + (pipenum - 1) * 2) -#define get_pipetre_addr(pipenum) (PIPE1TRE + (pipenum - 1) * 4) -#define get_pipetrn_addr(pipenum) (PIPE1TRN + (pipenum - 1) * 4) -#define get_devadd_addr(address) (DEVADD0 + address * 2) - - -/* USB HUB CONSTANTS (not OHCI-specific; see hub.h, based on usb_ohci.h) */ - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 - -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - -/* OHCI ROOT HUB REGISTER MASKS */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status*/ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -#endif /* __R8A66597_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/host/sl811-hcd.c b/qemu/roms/u-boot/drivers/usb/host/sl811-hcd.c deleted file mode 100644 index b29c67e18..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/sl811-hcd.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * (C) Copyright 2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * This code is based on linux driver for sl811hs chip, source at - * drivers/usb/host/sl811.c: - * - * SL811 Host Controller Interface driver for USB. - * - * Copyright (c) 2003/06, Courage Co., Ltd. - * - * Based on: - * 1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap, - * Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, - * Adam Richter, Gregory P. Smith; - * 2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com> - * 3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <mpc8xx.h> -#include <usb.h> -#include "sl811.h" - -#include "../../../board/kup/common/kup.h" - -#ifdef __PPC__ -# define EIEIO __asm__ volatile ("eieio") -#else -# define EIEIO /* nothing */ -#endif - -#define SL811_ADR (0x50000000) -#define SL811_DAT (0x50000001) - -#ifdef SL811_DEBUG -static int debug = 9; -#endif - -static int root_hub_devnum = 0; -static struct usb_port_status rh_status = { 0 };/* root hub port status */ - -static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe, - void *data, int buf_len, struct devrequest *cmd); - -static void sl811_write (__u8 index, __u8 data) -{ - *(volatile unsigned char *) (SL811_ADR) = index; - EIEIO; - *(volatile unsigned char *) (SL811_DAT) = data; - EIEIO; -} - -static __u8 sl811_read (__u8 index) -{ - __u8 data; - - *(volatile unsigned char *) (SL811_ADR) = index; - EIEIO; - data = *(volatile unsigned char *) (SL811_DAT); - EIEIO; - return (data); -} - -/* - * Read consecutive bytes of data from the SL811H/SL11H buffer - */ -static void inline sl811_read_buf(__u8 offset, __u8 *buf, __u8 size) -{ - *(volatile unsigned char *) (SL811_ADR) = offset; - EIEIO; - while (size--) { - *buf++ = *(volatile unsigned char *) (SL811_DAT); - EIEIO; - } -} - -/* - * Write consecutive bytes of data to the SL811H/SL11H buffer - */ -static void inline sl811_write_buf(__u8 offset, __u8 *buf, __u8 size) -{ - *(volatile unsigned char *) (SL811_ADR) = offset; - EIEIO; - while (size--) { - *(volatile unsigned char *) (SL811_DAT) = *buf++; - EIEIO; - } -} - -int usb_init_kup4x (void) -{ - volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; - volatile memctl8xx_t *memctl = &immap->im_memctl; - int i; - unsigned char tmp; - - memctl = &immap->im_memctl; - memctl->memc_or7 = 0xFFFF8726; - memctl->memc_br7 = 0x50000401; /* start at 0x50000000 */ - /* BP 14 low = USB ON */ - immap->im_cpm.cp_pbdat &= ~(BP_USB_VCC); - /* PB 14 nomal port */ - immap->im_cpm.cp_pbpar &= ~(BP_USB_VCC); - /* output */ - immap->im_cpm.cp_pbdir |= (BP_USB_VCC); - - puts ("USB: "); - - for (i = 0x10; i < 0xff; i++) { - sl811_write(i, i); - tmp = (sl811_read(i)); - if (tmp != i) { - printf ("SL811 compare error index=0x%02x read=0x%02x\n", i, tmp); - return (-1); - } - } - printf ("SL811 ready\n"); - return (0); -} - -/* - * This function resets SL811HS controller and detects the speed of - * the connecting device - * - * Return: 0 = no device attached; 1 = USB device attached - */ -static int sl811_hc_reset(void) -{ - int status ; - - sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI); - sl811_write(SL811_CTRL1, SL811_CTRL1_RESET); - - mdelay(20); - - /* Disable hardware SOF generation, clear all irq status. */ - sl811_write(SL811_CTRL1, 0); - mdelay(2); - sl811_write(SL811_INTRSTS, 0xff); - status = sl811_read(SL811_INTRSTS); - - if (status & SL811_INTR_NOTPRESENT) { - /* Device is not present */ - PDEBUG(0, "Device not present\n"); - rh_status.wPortStatus &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE); - rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION; - sl811_write(SL811_INTR, SL811_INTR_INSRMV); - return 0; - } - - /* Send SOF to address 0, endpoint 0. */ - sl811_write(SL811_LEN_B, 0); - sl811_write(SL811_PIDEP_B, PIDEP(USB_PID_SOF, 0)); - sl811_write(SL811_DEV_B, 0x00); - sl811_write(SL811_SOFLOW, SL811_12M_LOW); - - if (status & SL811_INTR_SPEED_FULL) { - /* full speed device connect directly to root hub */ - PDEBUG (0, "Full speed Device attached\n"); - - sl811_write(SL811_CTRL1, SL811_CTRL1_RESET); - mdelay(20); - sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI); - sl811_write(SL811_CTRL1, SL811_CTRL1_SOF); - - /* start the SOF or EOP */ - sl811_write(SL811_CTRL_B, SL811_USB_CTRL_ARM); - rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION; - rh_status.wPortStatus &= ~USB_PORT_STAT_LOW_SPEED; - mdelay(2); - sl811_write(SL811_INTRSTS, 0xff); - } else { - /* slow speed device connect directly to root-hub */ - PDEBUG(0, "Low speed Device attached\n"); - - sl811_write(SL811_CTRL1, SL811_CTRL1_RESET); - mdelay(20); - sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_CTL2_DSWAP | SL811_12M_HI); - sl811_write(SL811_CTRL1, SL811_CTRL1_SPEED_LOW | SL811_CTRL1_SOF); - - /* start the SOF or EOP */ - sl811_write(SL811_CTRL_B, SL811_USB_CTRL_ARM); - rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION | USB_PORT_STAT_LOW_SPEED; - mdelay(2); - sl811_write(SL811_INTRSTS, 0xff); - } - - rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION; - sl811_write(SL811_INTR, /*SL811_INTR_INSRMV*/SL811_INTR_DONE_A); - - return 1; -} - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - root_hub_devnum = 0; - sl811_hc_reset(); - return 0; -} - -int usb_lowlevel_stop(int index) -{ - sl811_hc_reset(); - return 0; -} - -static int calc_needed_buswidth(int bytes, int need_preamble) -{ - return !need_preamble ? bytes * 8 + 256 : 8 * 8 * bytes + 2048; -} - -static int sl811_send_packet(struct usb_device *dev, unsigned long pipe, __u8 *buffer, int len) -{ - __u8 ctrl = SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE; - __u16 status = 0; - int err = 0, time_start = get_timer(0); - int need_preamble = !(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) && - (dev->speed == USB_SPEED_LOW); - - if (len > 239) - return -1; - - if (usb_pipeout(pipe)) - ctrl |= SL811_USB_CTRL_DIR_OUT; - if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) - ctrl |= SL811_USB_CTRL_TOGGLE_1; - if (need_preamble) - ctrl |= SL811_USB_CTRL_PREAMBLE; - - sl811_write(SL811_INTRSTS, 0xff); - - while (err < 3) { - sl811_write(SL811_ADDR_A, 0x10); - sl811_write(SL811_LEN_A, len); - if (usb_pipeout(pipe) && len) - sl811_write_buf(0x10, buffer, len); - - if (!(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) && - sl811_read(SL811_SOFCNTDIV)*64 < calc_needed_buswidth(len, need_preamble)) - ctrl |= SL811_USB_CTRL_SOF; - else - ctrl &= ~SL811_USB_CTRL_SOF; - - sl811_write(SL811_CTRL_A, ctrl); - while (!(sl811_read(SL811_INTRSTS) & SL811_INTR_DONE_A)) { - if (5*CONFIG_SYS_HZ < get_timer(time_start)) { - printf("USB transmit timed out\n"); - return -USB_ST_CRC_ERR; - } - } - - sl811_write(SL811_INTRSTS, 0xff); - status = sl811_read(SL811_STS_A); - - if (status & SL811_USB_STS_ACK) { - int remainder = sl811_read(SL811_CNT_A); - if (remainder) { - PDEBUG(0, "usb transfer remainder = %d\n", remainder); - len -= remainder; - } - if (usb_pipein(pipe) && len) - sl811_read_buf(0x10, buffer, len); - return len; - } - - if ((status & SL811_USB_STS_NAK) == SL811_USB_STS_NAK) - continue; - - PDEBUG(0, "usb transfer error %#x\n", (int)status); - err++; - } - - err = 0; - - if (status & SL811_USB_STS_ERROR) - err |= USB_ST_BUF_ERR; - if (status & SL811_USB_STS_TIMEOUT) - err |= USB_ST_CRC_ERR; - if (status & SL811_USB_STS_STALL) - err |= USB_ST_STALLED; - - return -err; -} - -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len) -{ - int dir_out = usb_pipeout(pipe); - int ep = usb_pipeendpoint(pipe); - int max = usb_maxpacket(dev, pipe); - int done = 0; - - PDEBUG(7, "dev = %ld pipe = %ld buf = %p size = %d dir_out = %d\n", - usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out); - - dev->status = 0; - - sl811_write(SL811_DEV_A, usb_pipedevice(pipe)); - sl811_write(SL811_PIDEP_A, PIDEP(!dir_out ? USB_PID_IN : USB_PID_OUT, ep)); - while (done < len) { - int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done, - max > len - done ? len - done : max); - if (res < 0) { - dev->status = -res; - return res; - } - - if (!dir_out && res < max) /* short packet */ - break; - - done += res; - usb_dotoggle(dev, ep, dir_out); - } - - dev->act_len = done; - - return 0; -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len,struct devrequest *setup) -{ - int done = 0; - int devnum = usb_pipedevice(pipe); - int ep = usb_pipeendpoint(pipe); - - dev->status = 0; - - if (devnum == root_hub_devnum) - return sl811_rh_submit_urb(dev, pipe, buffer, len, setup); - - PDEBUG(7, "dev = %d pipe = %ld buf = %p size = %d rt = %#x req = %#x bus = %i\n", - devnum, ep, buffer, len, (int)setup->requesttype, - (int)setup->request, sl811_read(SL811_SOFCNTDIV)*64); - - sl811_write(SL811_DEV_A, devnum); - sl811_write(SL811_PIDEP_A, PIDEP(USB_PID_SETUP, ep)); - /* setup phase */ - usb_settoggle(dev, ep, 1, 0); - if (sl811_send_packet(dev, usb_sndctrlpipe(dev, ep), - (__u8*)setup, sizeof(*setup)) == sizeof(*setup)) { - int dir_in = usb_pipein(pipe); - int max = usb_maxpacket(dev, pipe); - - /* data phase */ - sl811_write(SL811_PIDEP_A, - PIDEP(dir_in ? USB_PID_IN : USB_PID_OUT, ep)); - usb_settoggle(dev, ep, usb_pipeout(pipe), 1); - while (done < len) { - int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done, - max > len - done ? len - done : max); - if (res < 0) { - PDEBUG(0, "status data failed!\n"); - dev->status = -res; - return 0; - } - done += res; - usb_dotoggle(dev, ep, usb_pipeout(pipe)); - if (dir_in && res < max) /* short packet */ - break; - } - - /* status phase */ - sl811_write(SL811_PIDEP_A, - PIDEP(!dir_in ? USB_PID_IN : USB_PID_OUT, ep)); - usb_settoggle(dev, ep, !usb_pipeout(pipe), 1); - if (sl811_send_packet(dev, - !dir_in ? usb_rcvctrlpipe(dev, ep) : - usb_sndctrlpipe(dev, ep), - 0, 0) < 0) { - PDEBUG(0, "status phase failed!\n"); - dev->status = -1; - } - } else { - PDEBUG(0, "setup phase failed!\n"); - dev->status = -1; - } - - dev->act_len = done; - - return done; -} - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, int interval) -{ - PDEBUG(0, "dev = %p pipe = %#lx buf = %p size = %d int = %d\n", dev, pipe, - buffer, len, interval); - return -1; -} - -/* - * SL811 Virtual Root Hub - */ - -/* Device descriptor */ -static __u8 sl811_rh_dev_des[] = -{ - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x10, /* __u16 bcdUSB; v1.1 */ - 0x01, - 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ - 0x00, /* __u16 idVendor; */ - 0x00, - 0x00, /* __u16 idProduct; */ - 0x00, - 0x00, /* __u16 bcdDevice; */ - 0x00, - 0x00, /* __u8 iManufacturer; */ - 0x02, /* __u8 iProduct; */ - 0x01, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - -/* Configuration descriptor */ -static __u8 sl811_rh_config_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, /* __u16 wTotalLength; */ - 0x00, - 0x01, /* __u8 bNumInterfaces; */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, - 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ - - /* interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x01, /* __u8 if_bNumEndpoints; */ - 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* __u8 if_bInterfaceSubClass; */ - 0x00, /* __u8 if_bInterfaceProtocol; */ - 0x00, /* __u8 if_iInterface; */ - - /* endpoint */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x08, /* __u16 ep_wMaxPacketSize; */ - 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - -/* root hub class descriptor*/ -static __u8 sl811_rh_hub_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x29, /* __u8 bDescriptorType; Hub-descriptor */ - 0x01, /* __u8 bNbrPorts; */ - 0x00, /* __u16 wHubCharacteristics; */ - 0x00, - 0x50, /* __u8 bPwrOn2pwrGood; 2ms */ - 0x00, /* __u8 bHubContrCurrent; 0 mA */ - 0xfc, /* __u8 DeviceRemovable; *** 7 Ports max *** */ - 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ -}; - -/* - * helper routine for returning string descriptors in UTF-16LE - * input can actually be ISO-8859-1; ASCII is its 7-bit subset - */ -static int ascii2utf (char *s, u8 *utf, int utfmax) -{ - int retval; - - for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) { - *utf++ = *s++; - *utf++ = 0; - } - return retval; -} - -/* - * root_hub_string is used by each host controller's root hub code, - * so that they're identified consistently throughout the system. - */ -static int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len) -{ - char buf [30]; - - /* assert (len > (2 * (sizeof (buf) + 1))); - assert (strlen (type) <= 8);*/ - - /* language ids */ - if (id == 0) { - *data++ = 4; *data++ = 3; /* 4 bytes data */ - *data++ = 0; *data++ = 0; /* some language id */ - return 4; - - /* serial number */ - } else if (id == 1) { - sprintf (buf, "%#x", serial); - - /* product description */ - } else if (id == 2) { - sprintf (buf, "USB %s Root Hub", type); - - /* id 3 == vendor description */ - - /* unsupported IDs --> "stall" */ - } else - return 0; - - ascii2utf (buf, data + 2, len - 2); - data [0] = 2 + strlen(buf) * 2; - data [1] = 3; - return data [0]; -} - -/* helper macro */ -#define OK(x) len = (x); break - -/* - * This function handles all USB request to the the virtual root hub - */ -static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe, - void *data, int buf_len, struct devrequest *cmd) -{ - __u8 data_buf[16]; - __u8 *bufp = data_buf; - int len = 0; - int status = 0; - __u16 bmRType_bReq; - __u16 wValue = le16_to_cpu (cmd->value); - __u16 wLength = le16_to_cpu (cmd->length); -#ifdef SL811_DEBUG - __u16 wIndex = le16_to_cpu (cmd->index); -#endif - - if (usb_pipeint(pipe)) { - PDEBUG(0, "interrupt transfer unimplemented!\n"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - - PDEBUG(5, "submit rh urb, req = %d(%x) val = %#x index = %#x len=%d\n", - bmRType_bReq, bmRType_bReq, wValue, wIndex, wLength); - - /* Request Destination: - without flags: Device, - USB_RECIP_INTERFACE: interface, - USB_RECIP_ENDPOINT: endpoint, - USB_TYPE_CLASS means HUB here, - USB_RECIP_OTHER | USB_TYPE_CLASS almost ever means HUB_PORT here - */ - switch (bmRType_bReq) { - case RH_GET_STATUS: - *(__u16 *)bufp = cpu_to_le16(1); - OK(2); - - case RH_GET_STATUS | USB_RECIP_INTERFACE: - *(__u16 *)bufp = cpu_to_le16(0); - OK(2); - - case RH_GET_STATUS | USB_RECIP_ENDPOINT: - *(__u16 *)bufp = cpu_to_le16(0); - OK(2); - - case RH_GET_STATUS | USB_TYPE_CLASS: - *(__u32 *)bufp = cpu_to_le32(0); - OK(4); - - case RH_GET_STATUS | USB_RECIP_OTHER | USB_TYPE_CLASS: - *(__u32 *)bufp = cpu_to_le32(rh_status.wPortChange<<16 | rh_status.wPortStatus); - OK(4); - - case RH_CLEAR_FEATURE | USB_RECIP_ENDPOINT: - switch (wValue) { - case 1: - OK(0); - } - break; - - case RH_CLEAR_FEATURE | USB_TYPE_CLASS: - switch (wValue) { - case C_HUB_LOCAL_POWER: - OK(0); - - case C_HUB_OVER_CURRENT: - OK(0); - } - break; - - case RH_CLEAR_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS: - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - rh_status.wPortStatus &= ~USB_PORT_STAT_ENABLE; - OK(0); - - case USB_PORT_FEAT_SUSPEND: - rh_status.wPortStatus &= ~USB_PORT_STAT_SUSPEND; - OK(0); - - case USB_PORT_FEAT_POWER: - rh_status.wPortStatus &= ~USB_PORT_STAT_POWER; - OK(0); - - case USB_PORT_FEAT_C_CONNECTION: - rh_status.wPortChange &= ~USB_PORT_STAT_C_CONNECTION; - OK(0); - - case USB_PORT_FEAT_C_ENABLE: - rh_status.wPortChange &= ~USB_PORT_STAT_C_ENABLE; - OK(0); - - case USB_PORT_FEAT_C_SUSPEND: - rh_status.wPortChange &= ~USB_PORT_STAT_C_SUSPEND; - OK(0); - - case USB_PORT_FEAT_C_OVER_CURRENT: - rh_status.wPortChange &= ~USB_PORT_STAT_C_OVERCURRENT; - OK(0); - - case USB_PORT_FEAT_C_RESET: - rh_status.wPortChange &= ~USB_PORT_STAT_C_RESET; - OK(0); - } - break; - - case RH_SET_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS: - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - rh_status.wPortStatus |= USB_PORT_STAT_SUSPEND; - OK(0); - - case USB_PORT_FEAT_RESET: - rh_status.wPortStatus |= USB_PORT_STAT_RESET; - rh_status.wPortChange = 0; - rh_status.wPortChange |= USB_PORT_STAT_C_RESET; - rh_status.wPortStatus &= ~USB_PORT_STAT_RESET; - rh_status.wPortStatus |= USB_PORT_STAT_ENABLE; - OK(0); - - case USB_PORT_FEAT_POWER: - rh_status.wPortStatus |= USB_PORT_STAT_POWER; - OK(0); - - case USB_PORT_FEAT_ENABLE: - rh_status.wPortStatus |= USB_PORT_STAT_ENABLE; - OK(0); - } - break; - - case RH_SET_ADDRESS: - root_hub_devnum = wValue; - OK(0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case USB_DT_DEVICE: - len = sizeof(sl811_rh_dev_des); - bufp = sl811_rh_dev_des; - OK(len); - - case USB_DT_CONFIG: - len = sizeof(sl811_rh_config_des); - bufp = sl811_rh_config_des; - OK(len); - - case USB_DT_STRING: - len = usb_root_hub_string(wValue & 0xff, (int)(long)0, "SL811HS", data, wLength); - if (len > 0) { - bufp = data; - OK(len); - } - - default: - status = -32; - } - break; - - case RH_GET_DESCRIPTOR | USB_TYPE_CLASS: - len = sizeof(sl811_rh_hub_des); - bufp = sl811_rh_hub_des; - OK(len); - - case RH_GET_CONFIGURATION: - bufp[0] = 0x01; - OK(1); - - case RH_SET_CONFIGURATION: - OK(0); - - default: - PDEBUG(1, "unsupported root hub command\n"); - status = -32; - } - - len = min(len, buf_len); - if (data != bufp) - memcpy(data, bufp, len); - - PDEBUG(5, "len = %d, status = %d\n", len, status); - - usb_dev->status = status; - usb_dev->act_len = len; - - return status == 0 ? len : status; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/sl811.h b/qemu/roms/u-boot/drivers/usb/host/sl811.h deleted file mode 100644 index c1f9f013b..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/sl811.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef __UBOOT_SL811_H -#define __UBOOT_SL811_H - -#undef SL811_DEBUG - -#ifdef SL811_DEBUG - #define PDEBUG(level, fmt, args...) \ - if (debug >= (level)) printf("[%s:%d] " fmt, \ - __PRETTY_FUNCTION__, __LINE__ , ## args) -#else - #define PDEBUG(level, fmt, args...) do {} while(0) -#endif - -/* Sl811 host control register */ -#define SL811_CTRL_A 0x00 -#define SL811_ADDR_A 0x01 -#define SL811_LEN_A 0x02 -#define SL811_STS_A 0x03 /* read */ -#define SL811_PIDEP_A 0x03 /* write */ -#define SL811_CNT_A 0x04 /* read */ -#define SL811_DEV_A 0x04 /* write */ -#define SL811_CTRL1 0x05 -#define SL811_INTR 0x06 -#define SL811_CTRL_B 0x08 -#define SL811_ADDR_B 0x09 -#define SL811_LEN_B 0x0A -#define SL811_STS_B 0x0B /* read */ -#define SL811_PIDEP_B 0x0B /* write */ -#define SL811_CNT_B 0x0C /* read */ -#define SL811_DEV_B 0x0C /* write */ -#define SL811_INTRSTS 0x0D /* write clears bitwise */ -#define SL811_HWREV 0x0E /* read */ -#define SL811_SOFLOW 0x0E /* write */ -#define SL811_SOFCNTDIV 0x0F /* read */ -#define SL811_CTRL2 0x0F /* write */ - -/* USB control register bits (addr 0x00 and addr 0x08) */ -#define SL811_USB_CTRL_ARM 0x01 -#define SL811_USB_CTRL_ENABLE 0x02 -#define SL811_USB_CTRL_DIR_OUT 0x04 -#define SL811_USB_CTRL_ISO 0x10 -#define SL811_USB_CTRL_SOF 0x20 -#define SL811_USB_CTRL_TOGGLE_1 0x40 -#define SL811_USB_CTRL_PREAMBLE 0x80 - -/* USB status register bits (addr 0x03 and addr 0x0B) */ -#define SL811_USB_STS_ACK 0x01 -#define SL811_USB_STS_ERROR 0x02 -#define SL811_USB_STS_TIMEOUT 0x04 -#define SL811_USB_STS_TOGGLE_1 0x08 -#define SL811_USB_STS_SETUP 0x10 -#define SL811_USB_STS_OVERFLOW 0x20 -#define SL811_USB_STS_NAK 0x40 -#define SL811_USB_STS_STALL 0x80 - -/* Control register 1 bits (addr 0x05) */ -#define SL811_CTRL1_SOF 0x01 -#define SL811_CTRL1_RESET 0x08 -#define SL811_CTRL1_JKSTATE 0x10 -#define SL811_CTRL1_SPEED_LOW 0x20 -#define SL811_CTRL1_SUSPEND 0x40 - -/* Interrut enable (addr 0x06) and interrupt status register bits (addr 0x0D) */ -#define SL811_INTR_DONE_A 0x01 -#define SL811_INTR_DONE_B 0x02 -#define SL811_INTR_SOF 0x10 -#define SL811_INTR_INSRMV 0x20 -#define SL811_INTR_DETECT 0x40 -#define SL811_INTR_NOTPRESENT 0x40 -#define SL811_INTR_SPEED_FULL 0x80 /* only in status reg */ - -/* HW rev and SOF lo register bits (addr 0x0E) */ -#define SL811_HWR_HWREV 0xF0 - -/* SOF counter and control reg 2 (addr 0x0F) */ -#define SL811_CTL2_SOFHI 0x3F -#define SL811_CTL2_DSWAP 0x40 -#define SL811_CTL2_HOST 0x80 - -/* Set up for 1-ms SOF time. */ -#define SL811_12M_LOW 0xE0 -#define SL811_12M_HI 0x2E - -#define SL811_DATA_START 0x10 -#define SL811_DATA_LIMIT 240 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 - - -#define PIDEP(pid, ep) (((pid) & 0x0f) << 4 | (ep)) - -#endif /* __UBOOT_SL811_H */ diff --git a/qemu/roms/u-boot/drivers/usb/host/utmi-armada100.c b/qemu/roms/u-boot/drivers/usb/host/utmi-armada100.c deleted file mode 100644 index 1e878280f..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/utmi-armada100.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * (C) Copyright 2012 - * eInfochips Ltd. <www.einfochips.com> - * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com> - * - * (C) Copyright 2009 - * Marvell Semiconductor <www.marvell.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include <asm/arch/cpu.h> -#include <asm/arch/armada100.h> -#include <asm/arch/utmi-armada100.h> - -static int utmi_phy_init(void) -{ - struct armd1usb_phy_reg *phy_regs = - (struct armd1usb_phy_reg *)UTMI_PHY_BASE; - int timeout; - - setbits_le32(&phy_regs->utmi_ctrl, INPKT_DELAY_SOF | PLL_PWR_UP); - udelay(1000); - setbits_le32(&phy_regs->utmi_ctrl, PHY_PWR_UP); - - clrbits_le32(&phy_regs->utmi_pll, PLL_FBDIV_MASK | PLL_REFDIV_MASK); - setbits_le32(&phy_regs->utmi_pll, N_DIVIDER << PLL_FBDIV | M_DIVIDER); - - setbits_le32(&phy_regs->utmi_tx, PHSEL_VAL << CK60_PHSEL); - - /* Calibrate pll */ - timeout = 10000; - while (--timeout && ((readl(&phy_regs->utmi_pll) & PLL_READY) == 0)) - ; - if (!timeout) - return -1; - - udelay(200); - setbits_le32(&phy_regs->utmi_pll, VCOCAL_START); - udelay(400); - clrbits_le32(&phy_regs->utmi_pll, VCOCAL_START); - - udelay(200); - setbits_le32(&phy_regs->utmi_tx, RCAL_START); - udelay(400); - clrbits_le32(&phy_regs->utmi_tx, RCAL_START); - - timeout = 10000; - while (--timeout && ((readl(&phy_regs->utmi_pll) & PLL_READY) == 0)) - ; - if (!timeout) - return -1; - - return 0; -} - -/* - * Initialize USB host controller's UTMI Physical interface - */ -int utmi_init(void) -{ - struct armd1mpmu_registers *mpmu_regs = - (struct armd1mpmu_registers *)ARMD1_MPMU_BASE; - - struct armd1apmu_registers *apmu_regs = - (struct armd1apmu_registers *)ARMD1_APMU_BASE; - - /* Turn on 26Mhz ref clock for UTMI PLL */ - setbits_le32(&mpmu_regs->acgr, APB2_26M_EN | AP_26M); - - /* USB Clock reset */ - writel(USB_SPH_AXICLK_EN, &apmu_regs->usbcrc); - writel(USB_SPH_AXICLK_EN | USB_SPH_AXI_RST, &apmu_regs->usbcrc); - - /* Initialize UTMI transceiver */ - return utmi_phy_init(); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci-exynos5.c b/qemu/roms/u-boot/drivers/usb/host/xhci-exynos5.c deleted file mode 100644 index b4946a3f1..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci-exynos5.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * SAMSUNG EXYNOS5 USB HOST XHCI Controller - * - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Vivek Gautam <gautam.vivek@samsung.com> - * Vikas Sajjan <vikas.sajjan@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * This file is a conglomeration for DWC3-init sequence and further - * exynos5 specific PHY-init sequence. - */ - -#include <common.h> -#include <fdtdec.h> -#include <libfdt.h> -#include <malloc.h> -#include <usb.h> -#include <watchdog.h> -#include <asm/arch/cpu.h> -#include <asm/arch/power.h> -#include <asm/arch/xhci-exynos.h> -#include <asm/gpio.h> -#include <asm-generic/errno.h> -#include <linux/compat.h> -#include <linux/usb/dwc3.h> - -#include "xhci.h" - -/* Declare global data pointer */ -DECLARE_GLOBAL_DATA_PTR; - -/** - * Contains pointers to register base addresses - * for the usb controller. - */ -struct exynos_xhci { - struct exynos_usb3_phy *usb3_phy; - struct xhci_hccr *hcd; - struct dwc3 *dwc3_reg; - struct fdt_gpio_state vbus_gpio; -}; - -static struct exynos_xhci exynos; - -#ifdef CONFIG_OF_CONTROL -static int exynos_usb3_parse_dt(const void *blob, struct exynos_xhci *exynos) -{ - fdt_addr_t addr; - unsigned int node; - int depth; - - node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_XHCI); - if (node <= 0) { - debug("XHCI: Can't get device node for xhci\n"); - return -ENODEV; - } - - /* - * Get the base address for XHCI controller from the device node - */ - addr = fdtdec_get_addr(blob, node, "reg"); - if (addr == FDT_ADDR_T_NONE) { - debug("Can't get the XHCI register base address\n"); - return -ENXIO; - } - exynos->hcd = (struct xhci_hccr *)addr; - - /* Vbus gpio */ - fdtdec_decode_gpio(blob, node, "samsung,vbus-gpio", &exynos->vbus_gpio); - - depth = 0; - node = fdtdec_next_compatible_subnode(blob, node, - COMPAT_SAMSUNG_EXYNOS5_USB3_PHY, &depth); - if (node <= 0) { - debug("XHCI: Can't get device node for usb3-phy controller\n"); - return -ENODEV; - } - - /* - * Get the base address for usbphy from the device node - */ - exynos->usb3_phy = (struct exynos_usb3_phy *)fdtdec_get_addr(blob, node, - "reg"); - if (exynos->usb3_phy == NULL) { - debug("Can't get the usbphy register address\n"); - return -ENXIO; - } - - return 0; -} -#endif - -static void exynos5_usb3_phy_init(struct exynos_usb3_phy *phy) -{ - u32 reg; - - /* enabling usb_drd phy */ - set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_EN); - - /* Reset USB 3.0 PHY */ - writel(0x0, &phy->phy_reg0); - - clrbits_le32(&phy->phy_param0, - /* Select PHY CLK source */ - PHYPARAM0_REF_USE_PAD | - /* Set Loss-of-Signal Detector sensitivity */ - PHYPARAM0_REF_LOSLEVEL_MASK); - setbits_le32(&phy->phy_param0, PHYPARAM0_REF_LOSLEVEL); - - writel(0x0, &phy->phy_resume); - - /* - * Setting the Frame length Adj value[6:1] to default 0x20 - * See xHCI 1.0 spec, 5.2.4 - */ - setbits_le32(&phy->link_system, - LINKSYSTEM_XHCI_VERSION_CONTROL | - LINKSYSTEM_FLADJ(0x20)); - - /* Set Tx De-Emphasis level */ - clrbits_le32(&phy->phy_param1, PHYPARAM1_PCS_TXDEEMPH_MASK); - setbits_le32(&phy->phy_param1, PHYPARAM1_PCS_TXDEEMPH); - - setbits_le32(&phy->phy_batchg, PHYBATCHG_UTMI_CLKSEL); - - /* PHYTEST POWERDOWN Control */ - clrbits_le32(&phy->phy_test, - PHYTEST_POWERDOWN_SSP | - PHYTEST_POWERDOWN_HSP); - - /* UTMI Power Control */ - writel(PHYUTMI_OTGDISABLE, &phy->phy_utmi); - - /* Use core clock from main PLL */ - reg = PHYCLKRST_REFCLKSEL_EXT_REFCLK | - /* Default 24Mhz crystal clock */ - PHYCLKRST_FSEL(FSEL_CLKSEL_24M) | - PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF | - PHYCLKRST_SSC_REFCLKSEL(0x88) | - /* Force PortReset of PHY */ - PHYCLKRST_PORTRESET | - /* Digital power supply in normal operating mode */ - PHYCLKRST_RETENABLEN | - /* Enable ref clock for SS function */ - PHYCLKRST_REF_SSP_EN | - /* Enable spread spectrum */ - PHYCLKRST_SSC_EN | - /* Power down HS Bias and PLL blocks in suspend mode */ - PHYCLKRST_COMMONONN; - - writel(reg, &phy->phy_clk_rst); - - /* giving time to Phy clock to settle before resetting */ - udelay(10); - - reg &= ~PHYCLKRST_PORTRESET; - writel(reg, &phy->phy_clk_rst); -} - -static void exynos5_usb3_phy_exit(struct exynos_usb3_phy *phy) -{ - setbits_le32(&phy->phy_utmi, - PHYUTMI_OTGDISABLE | - PHYUTMI_FORCESUSPEND | - PHYUTMI_FORCESLEEP); - - clrbits_le32(&phy->phy_clk_rst, - PHYCLKRST_REF_SSP_EN | - PHYCLKRST_SSC_EN | - PHYCLKRST_COMMONONN); - - /* PHYTEST POWERDOWN Control to remove leakage current */ - setbits_le32(&phy->phy_test, - PHYTEST_POWERDOWN_SSP | - PHYTEST_POWERDOWN_HSP); - - /* disabling usb_drd phy */ - set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_DISABLE); -} - -void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) -{ - clrsetbits_le32(&dwc3_reg->g_ctl, - DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG), - DWC3_GCTL_PRTCAPDIR(mode)); -} - -static void dwc3_core_soft_reset(struct dwc3 *dwc3_reg) -{ - /* Before Resetting PHY, put Core in Reset */ - setbits_le32(&dwc3_reg->g_ctl, - DWC3_GCTL_CORESOFTRESET); - - /* Assert USB3 PHY reset */ - setbits_le32(&dwc3_reg->g_usb3pipectl[0], - DWC3_GUSB3PIPECTL_PHYSOFTRST); - - /* Assert USB2 PHY reset */ - setbits_le32(&dwc3_reg->g_usb2phycfg, - DWC3_GUSB2PHYCFG_PHYSOFTRST); - - mdelay(100); - - /* Clear USB3 PHY reset */ - clrbits_le32(&dwc3_reg->g_usb3pipectl[0], - DWC3_GUSB3PIPECTL_PHYSOFTRST); - - /* Clear USB2 PHY reset */ - clrbits_le32(&dwc3_reg->g_usb2phycfg, - DWC3_GUSB2PHYCFG_PHYSOFTRST); - - /* After PHYs are stable we can take Core out of reset state */ - clrbits_le32(&dwc3_reg->g_ctl, - DWC3_GCTL_CORESOFTRESET); -} - -static int dwc3_core_init(struct dwc3 *dwc3_reg) -{ - u32 reg; - u32 revision; - unsigned int dwc3_hwparams1; - - revision = readl(&dwc3_reg->g_snpsid); - /* This should read as U3 followed by revision number */ - if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) { - puts("this is not a DesignWare USB3 DRD Core\n"); - return -EINVAL; - } - - dwc3_core_soft_reset(dwc3_reg); - - dwc3_hwparams1 = readl(&dwc3_reg->g_hwparams1); - - reg = readl(&dwc3_reg->g_ctl); - reg &= ~DWC3_GCTL_SCALEDOWN_MASK; - reg &= ~DWC3_GCTL_DISSCRAMBLE; - switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1)) { - case DWC3_GHWPARAMS1_EN_PWROPT_CLK: - reg &= ~DWC3_GCTL_DSBLCLKGTNG; - break; - default: - debug("No power optimization available\n"); - } - - /* - * WORKAROUND: DWC3 revisions <1.90a have a bug - * where the device can fail to connect at SuperSpeed - * and falls back to high-speed mode which causes - * the device to enter a Connect/Disconnect loop - */ - if ((revision & DWC3_REVISION_MASK) < 0x190a) - reg |= DWC3_GCTL_U2RSTECN; - - writel(reg, &dwc3_reg->g_ctl); - - return 0; -} - -static int exynos_xhci_core_init(struct exynos_xhci *exynos) -{ - int ret; - - exynos5_usb3_phy_init(exynos->usb3_phy); - - ret = dwc3_core_init(exynos->dwc3_reg); - if (ret) { - debug("failed to initialize core\n"); - return -EINVAL; - } - - /* We are hard-coding DWC3 core to Host Mode */ - dwc3_set_mode(exynos->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); - - return 0; -} - -static void exynos_xhci_core_exit(struct exynos_xhci *exynos) -{ - exynos5_usb3_phy_exit(exynos->usb3_phy); -} - -int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) -{ - struct exynos_xhci *ctx = &exynos; - int ret; - -#ifdef CONFIG_OF_CONTROL - exynos_usb3_parse_dt(gd->fdt_blob, ctx); -#else - ctx->usb3_phy = (struct exynos_usb3_phy *)samsung_get_base_usb3_phy(); - ctx->hcd = (struct xhci_hccr *)samsung_get_base_usb_xhci(); -#endif - - ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); - -#ifdef CONFIG_OF_CONTROL - /* setup the Vbus gpio here */ - if (fdt_gpio_isvalid(&ctx->vbus_gpio) && - !fdtdec_setup_gpio(&ctx->vbus_gpio)) - gpio_direction_output(ctx->vbus_gpio.gpio, 1); -#endif - - ret = exynos_xhci_core_init(ctx); - if (ret) { - puts("XHCI: failed to initialize controller\n"); - return -EINVAL; - } - - *hccr = (ctx->hcd); - *hcor = (struct xhci_hcor *)((uint32_t) *hccr - + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); - - debug("Exynos5-xhci: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -void xhci_hcd_stop(int index) -{ - struct exynos_xhci *ctx = &exynos; - - exynos_xhci_core_exit(ctx); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci-mem.c b/qemu/roms/u-boot/drivers/usb/host/xhci-mem.c deleted file mode 100644 index 89908e8a8..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci-mem.c +++ /dev/null @@ -1,720 +0,0 @@ -/* - * USB HOST XHCI Controller stack - * - * Based on xHCI host controller driver in linux-kernel - * by Sarah Sharp. - * - * Copyright (C) 2008 Intel Corp. - * Author: Sarah Sharp - * - * Copyright (C) 2013 Samsung Electronics Co.Ltd - * Authors: Vivek Gautam <gautam.vivek@samsung.com> - * Vikas Sajjan <vikas.sajjan@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/byteorder.h> -#include <usb.h> -#include <malloc.h> -#include <asm/cache.h> -#include <asm-generic/errno.h> - -#include "xhci.h" - -#define CACHELINE_SIZE CONFIG_SYS_CACHELINE_SIZE -/** - * flushes the address passed till the length - * - * @param addr pointer to memory region to be flushed - * @param len the length of the cache line to be flushed - * @return none - */ -void xhci_flush_cache(uint32_t addr, u32 len) -{ - BUG_ON((void *)addr == NULL || len == 0); - - flush_dcache_range(addr & ~(CACHELINE_SIZE - 1), - ALIGN(addr + len, CACHELINE_SIZE)); -} - -/** - * invalidates the address passed till the length - * - * @param addr pointer to memory region to be invalidates - * @param len the length of the cache line to be invalidated - * @return none - */ -void xhci_inval_cache(uint32_t addr, u32 len) -{ - BUG_ON((void *)addr == NULL || len == 0); - - invalidate_dcache_range(addr & ~(CACHELINE_SIZE - 1), - ALIGN(addr + len, CACHELINE_SIZE)); -} - - -/** - * frees the "segment" pointer passed - * - * @param ptr pointer to "segement" to be freed - * @return none - */ -static void xhci_segment_free(struct xhci_segment *seg) -{ - free(seg->trbs); - seg->trbs = NULL; - - free(seg); -} - -/** - * frees the "ring" pointer passed - * - * @param ptr pointer to "ring" to be freed - * @return none - */ -static void xhci_ring_free(struct xhci_ring *ring) -{ - struct xhci_segment *seg; - struct xhci_segment *first_seg; - - BUG_ON(!ring); - - first_seg = ring->first_seg; - seg = first_seg->next; - while (seg != first_seg) { - struct xhci_segment *next = seg->next; - xhci_segment_free(seg); - seg = next; - } - xhci_segment_free(first_seg); - - free(ring); -} - -/** - * frees the "xhci_container_ctx" pointer passed - * - * @param ptr pointer to "xhci_container_ctx" to be freed - * @return none - */ -static void xhci_free_container_ctx(struct xhci_container_ctx *ctx) -{ - free(ctx->bytes); - free(ctx); -} - -/** - * frees the virtual devices for "xhci_ctrl" pointer passed - * - * @param ptr pointer to "xhci_ctrl" whose virtual devices are to be freed - * @return none - */ -static void xhci_free_virt_devices(struct xhci_ctrl *ctrl) -{ - int i; - int slot_id; - struct xhci_virt_device *virt_dev; - - /* - * refactored here to loop through all virt_dev - * Slot ID 0 is reserved - */ - for (slot_id = 0; slot_id < MAX_HC_SLOTS; slot_id++) { - virt_dev = ctrl->devs[slot_id]; - if (!virt_dev) - continue; - - ctrl->dcbaa->dev_context_ptrs[slot_id] = 0; - - for (i = 0; i < 31; ++i) - if (virt_dev->eps[i].ring) - xhci_ring_free(virt_dev->eps[i].ring); - - if (virt_dev->in_ctx) - xhci_free_container_ctx(virt_dev->in_ctx); - if (virt_dev->out_ctx) - xhci_free_container_ctx(virt_dev->out_ctx); - - free(virt_dev); - /* make sure we are pointing to NULL */ - ctrl->devs[slot_id] = NULL; - } -} - -/** - * frees all the memory allocated - * - * @param ptr pointer to "xhci_ctrl" to be cleaned up - * @return none - */ -void xhci_cleanup(struct xhci_ctrl *ctrl) -{ - xhci_ring_free(ctrl->event_ring); - xhci_ring_free(ctrl->cmd_ring); - xhci_free_virt_devices(ctrl); - free(ctrl->erst.entries); - free(ctrl->dcbaa); - memset(ctrl, '\0', sizeof(struct xhci_ctrl)); -} - -/** - * Malloc the aligned memory - * - * @param size size of memory to be allocated - * @return allocates the memory and returns the aligned pointer - */ -static void *xhci_malloc(unsigned int size) -{ - void *ptr; - size_t cacheline_size = max(XHCI_ALIGNMENT, CACHELINE_SIZE); - - ptr = memalign(cacheline_size, ALIGN(size, cacheline_size)); - BUG_ON(!ptr); - memset(ptr, '\0', size); - - xhci_flush_cache((uint32_t)ptr, size); - - return ptr; -} - -/** - * Make the prev segment point to the next segment. - * Change the last TRB in the prev segment to be a Link TRB which points to the - * address of the next segment. The caller needs to set any Link TRB - * related flags, such as End TRB, Toggle Cycle, and no snoop. - * - * @param prev pointer to the previous segment - * @param next pointer to the next segment - * @param link_trbs flag to indicate whether to link the trbs or NOT - * @return none - */ -static void xhci_link_segments(struct xhci_segment *prev, - struct xhci_segment *next, bool link_trbs) -{ - u32 val; - u64 val_64 = 0; - - if (!prev || !next) - return; - prev->next = next; - if (link_trbs) { - val_64 = (uintptr_t)next->trbs; - prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = val_64; - - /* - * Set the last TRB in the segment to - * have a TRB type ID of Link TRB - */ - val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control); - val &= ~TRB_TYPE_BITMASK; - val |= (TRB_LINK << TRB_TYPE_SHIFT); - - prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val); - } -} - -/** - * Initialises the Ring's enqueue,dequeue,enq_seg pointers - * - * @param ring pointer to the RING to be intialised - * @return none - */ -static void xhci_initialize_ring_info(struct xhci_ring *ring) -{ - /* - * The ring is empty, so the enqueue pointer == dequeue pointer - */ - ring->enqueue = ring->first_seg->trbs; - ring->enq_seg = ring->first_seg; - ring->dequeue = ring->enqueue; - ring->deq_seg = ring->first_seg; - - /* - * The ring is initialized to 0. The producer must write 1 to the - * cycle bit to handover ownership of the TRB, so PCS = 1. - * The consumer must compare CCS to the cycle bit to - * check ownership, so CCS = 1. - */ - ring->cycle_state = 1; -} - -/** - * Allocates a generic ring segment from the ring pool, sets the dma address, - * initializes the segment to zero, and sets the private next pointer to NULL. - * Section 4.11.1.1: - * "All components of all Command and Transfer TRBs shall be initialized to '0'" - * - * @param none - * @return pointer to the newly allocated SEGMENT - */ -static struct xhci_segment *xhci_segment_alloc(void) -{ - struct xhci_segment *seg; - - seg = (struct xhci_segment *)malloc(sizeof(struct xhci_segment)); - BUG_ON(!seg); - - seg->trbs = (union xhci_trb *)xhci_malloc(SEGMENT_SIZE); - - seg->next = NULL; - - return seg; -} - -/** - * Create a new ring with zero or more segments. - * TODO: current code only uses one-time-allocated single-segment rings - * of 1KB anyway, so we might as well get rid of all the segment and - * linking code (and maybe increase the size a bit, e.g. 4KB). - * - * - * Link each segment together into a ring. - * Set the end flag and the cycle toggle bit on the last segment. - * See section 4.9.2 and figures 15 and 16 of XHCI spec rev1.0. - * - * @param num_segs number of segments in the ring - * @param link_trbs flag to indicate whether to link the trbs or NOT - * @return pointer to the newly created RING - */ -struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs) -{ - struct xhci_ring *ring; - struct xhci_segment *prev; - - ring = (struct xhci_ring *)malloc(sizeof(struct xhci_ring)); - BUG_ON(!ring); - - if (num_segs == 0) - return ring; - - ring->first_seg = xhci_segment_alloc(); - BUG_ON(!ring->first_seg); - - num_segs--; - - prev = ring->first_seg; - while (num_segs > 0) { - struct xhci_segment *next; - - next = xhci_segment_alloc(); - BUG_ON(!next); - - xhci_link_segments(prev, next, link_trbs); - - prev = next; - num_segs--; - } - xhci_link_segments(prev, ring->first_seg, link_trbs); - if (link_trbs) { - /* See section 4.9.2.1 and 6.4.4.1 */ - prev->trbs[TRBS_PER_SEGMENT-1].link.control |= - cpu_to_le32(LINK_TOGGLE); - } - xhci_initialize_ring_info(ring); - - return ring; -} - -/** - * Allocates the Container context - * - * @param ctrl Host controller data structure - * @param type type of XHCI Container Context - * @return NULL if failed else pointer to the context on success - */ -static struct xhci_container_ctx - *xhci_alloc_container_ctx(struct xhci_ctrl *ctrl, int type) -{ - struct xhci_container_ctx *ctx; - - ctx = (struct xhci_container_ctx *) - malloc(sizeof(struct xhci_container_ctx)); - BUG_ON(!ctx); - - BUG_ON((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT)); - ctx->type = type; - ctx->size = (MAX_EP_CTX_NUM + 1) * - CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)); - if (type == XHCI_CTX_TYPE_INPUT) - ctx->size += CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)); - - ctx->bytes = (u8 *)xhci_malloc(ctx->size); - - return ctx; -} - -/** - * Allocating virtual device - * - * @param udev pointer to USB deivce structure - * @return 0 on success else -1 on failure - */ -int xhci_alloc_virt_device(struct usb_device *udev) -{ - u64 byte_64 = 0; - unsigned int slot_id = udev->slot_id; - struct xhci_virt_device *virt_dev; - struct xhci_ctrl *ctrl = udev->controller; - - /* Slot ID 0 is reserved */ - if (ctrl->devs[slot_id]) { - printf("Virt dev for slot[%d] already allocated\n", slot_id); - return -EEXIST; - } - - ctrl->devs[slot_id] = (struct xhci_virt_device *) - malloc(sizeof(struct xhci_virt_device)); - - if (!ctrl->devs[slot_id]) { - puts("Failed to allocate virtual device\n"); - return -ENOMEM; - } - - memset(ctrl->devs[slot_id], 0, sizeof(struct xhci_virt_device)); - virt_dev = ctrl->devs[slot_id]; - - /* Allocate the (output) device context that will be used in the HC. */ - virt_dev->out_ctx = xhci_alloc_container_ctx(ctrl, - XHCI_CTX_TYPE_DEVICE); - if (!virt_dev->out_ctx) { - puts("Failed to allocate out context for virt dev\n"); - return -ENOMEM; - } - - /* Allocate the (input) device context for address device command */ - virt_dev->in_ctx = xhci_alloc_container_ctx(ctrl, - XHCI_CTX_TYPE_INPUT); - if (!virt_dev->in_ctx) { - puts("Failed to allocate in context for virt dev\n"); - return -ENOMEM; - } - - /* Allocate endpoint 0 ring */ - virt_dev->eps[0].ring = xhci_ring_alloc(1, true); - - byte_64 = (uintptr_t)(virt_dev->out_ctx->bytes); - - /* Point to output device context in dcbaa. */ - ctrl->dcbaa->dev_context_ptrs[slot_id] = byte_64; - - xhci_flush_cache((uint32_t)&ctrl->dcbaa->dev_context_ptrs[slot_id], - sizeof(__le64)); - return 0; -} - -/** - * Allocates the necessary data structures - * for XHCI host controller - * - * @param ctrl Host controller data structure - * @param hccr pointer to HOST Controller Control Registers - * @param hcor pointer to HOST Controller Operational Registers - * @return 0 if successful else -1 on failure - */ -int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, - struct xhci_hcor *hcor) -{ - uint64_t val_64; - uint64_t trb_64; - uint32_t val; - unsigned long deq; - int i; - struct xhci_segment *seg; - - /* DCBAA initialization */ - ctrl->dcbaa = (struct xhci_device_context_array *) - xhci_malloc(sizeof(struct xhci_device_context_array)); - if (ctrl->dcbaa == NULL) { - puts("unable to allocate DCBA\n"); - return -ENOMEM; - } - - val_64 = (uintptr_t)ctrl->dcbaa; - /* Set the pointer in DCBAA register */ - xhci_writeq(&hcor->or_dcbaap, val_64); - - /* Command ring control pointer register initialization */ - ctrl->cmd_ring = xhci_ring_alloc(1, true); - - /* Set the address in the Command Ring Control register */ - trb_64 = (uintptr_t)ctrl->cmd_ring->first_seg->trbs; - val_64 = xhci_readq(&hcor->or_crcr); - val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | - (trb_64 & (u64) ~CMD_RING_RSVD_BITS) | - ctrl->cmd_ring->cycle_state; - xhci_writeq(&hcor->or_crcr, val_64); - - /* write the address of db register */ - val = xhci_readl(&hccr->cr_dboff); - val &= DBOFF_MASK; - ctrl->dba = (struct xhci_doorbell_array *)((char *)hccr + val); - - /* write the address of runtime register */ - val = xhci_readl(&hccr->cr_rtsoff); - val &= RTSOFF_MASK; - ctrl->run_regs = (struct xhci_run_regs *)((char *)hccr + val); - - /* writting the address of ir_set structure */ - ctrl->ir_set = &ctrl->run_regs->ir_set[0]; - - /* Event ring does not maintain link TRB */ - ctrl->event_ring = xhci_ring_alloc(ERST_NUM_SEGS, false); - ctrl->erst.entries = (struct xhci_erst_entry *) - xhci_malloc(sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS); - - ctrl->erst.num_entries = ERST_NUM_SEGS; - - for (val = 0, seg = ctrl->event_ring->first_seg; - val < ERST_NUM_SEGS; - val++) { - trb_64 = 0; - trb_64 = (uintptr_t)seg->trbs; - struct xhci_erst_entry *entry = &ctrl->erst.entries[val]; - xhci_writeq(&entry->seg_addr, trb_64); - entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); - entry->rsvd = 0; - seg = seg->next; - } - xhci_flush_cache((uint32_t)ctrl->erst.entries, - ERST_NUM_SEGS * sizeof(struct xhci_erst_entry)); - - deq = (unsigned long)ctrl->event_ring->dequeue; - - /* Update HC event ring dequeue pointer */ - xhci_writeq(&ctrl->ir_set->erst_dequeue, - (u64)deq & (u64)~ERST_PTR_MASK); - - /* set ERST count with the number of entries in the segment table */ - val = xhci_readl(&ctrl->ir_set->erst_size); - val &= ERST_SIZE_MASK; - val |= ERST_NUM_SEGS; - xhci_writel(&ctrl->ir_set->erst_size, val); - - /* this is the event ring segment table pointer */ - val_64 = xhci_readq(&ctrl->ir_set->erst_base); - val_64 &= ERST_PTR_MASK; - val_64 |= ((u32)(ctrl->erst.entries) & ~ERST_PTR_MASK); - - xhci_writeq(&ctrl->ir_set->erst_base, val_64); - - /* initializing the virtual devices to NULL */ - for (i = 0; i < MAX_HC_SLOTS; ++i) - ctrl->devs[i] = NULL; - - /* - * Just Zero'ing this register completely, - * or some spurious Device Notification Events - * might screw things here. - */ - xhci_writel(&hcor->or_dnctrl, 0x0); - - return 0; -} - -/** - * Give the input control context for the passed container context - * - * @param ctx pointer to the context - * @return pointer to the Input control context data - */ -struct xhci_input_control_ctx - *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx) -{ - BUG_ON(ctx->type != XHCI_CTX_TYPE_INPUT); - return (struct xhci_input_control_ctx *)ctx->bytes; -} - -/** - * Give the slot context for the passed container context - * - * @param ctrl Host controller data structure - * @param ctx pointer to the context - * @return pointer to the slot control context data - */ -struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *ctx) -{ - if (ctx->type == XHCI_CTX_TYPE_DEVICE) - return (struct xhci_slot_ctx *)ctx->bytes; - - return (struct xhci_slot_ctx *) - (ctx->bytes + CTX_SIZE(readl(&ctrl->hccr->cr_hccparams))); -} - -/** - * Gets the EP context from based on the ep_index - * - * @param ctrl Host controller data structure - * @param ctx context container - * @param ep_index index of the endpoint - * @return pointer to the End point context - */ -struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *ctx, - unsigned int ep_index) -{ - /* increment ep index by offset of start of ep ctx array */ - ep_index++; - if (ctx->type == XHCI_CTX_TYPE_INPUT) - ep_index++; - - return (struct xhci_ep_ctx *) - (ctx->bytes + - (ep_index * CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)))); -} - -/** - * Copy output xhci_ep_ctx to the input xhci_ep_ctx copy. - * Useful when you want to change one particular aspect of the endpoint - * and then issue a configure endpoint command. - * - * @param ctrl Host controller data structure - * @param in_ctx contains the input context - * @param out_ctx contains the input context - * @param ep_index index of the end point - * @return none - */ -void xhci_endpoint_copy(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx, - unsigned int ep_index) -{ - struct xhci_ep_ctx *out_ep_ctx; - struct xhci_ep_ctx *in_ep_ctx; - - out_ep_ctx = xhci_get_ep_ctx(ctrl, out_ctx, ep_index); - in_ep_ctx = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); - - in_ep_ctx->ep_info = out_ep_ctx->ep_info; - in_ep_ctx->ep_info2 = out_ep_ctx->ep_info2; - in_ep_ctx->deq = out_ep_ctx->deq; - in_ep_ctx->tx_info = out_ep_ctx->tx_info; -} - -/** - * Copy output xhci_slot_ctx to the input xhci_slot_ctx. - * Useful when you want to change one particular aspect of the endpoint - * and then issue a configure endpoint command. - * Only the context entries field matters, but - * we'll copy the whole thing anyway. - * - * @param ctrl Host controller data structure - * @param in_ctx contains the inpout context - * @param out_ctx contains the inpout context - * @return none - */ -void xhci_slot_copy(struct xhci_ctrl *ctrl, struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx) -{ - struct xhci_slot_ctx *in_slot_ctx; - struct xhci_slot_ctx *out_slot_ctx; - - in_slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); - out_slot_ctx = xhci_get_slot_ctx(ctrl, out_ctx); - - in_slot_ctx->dev_info = out_slot_ctx->dev_info; - in_slot_ctx->dev_info2 = out_slot_ctx->dev_info2; - in_slot_ctx->tt_info = out_slot_ctx->tt_info; - in_slot_ctx->dev_state = out_slot_ctx->dev_state; -} - -/** - * Setup an xHCI virtual device for a Set Address command - * - * @param udev pointer to the Device Data Structure - * @return returns negative value on failure else 0 on success - */ -void xhci_setup_addressable_virt_dev(struct usb_device *udev) -{ - struct usb_device *hop = udev; - struct xhci_virt_device *virt_dev; - struct xhci_ep_ctx *ep0_ctx; - struct xhci_slot_ctx *slot_ctx; - u32 port_num = 0; - u64 trb_64 = 0; - struct xhci_ctrl *ctrl = udev->controller; - - virt_dev = ctrl->devs[udev->slot_id]; - - BUG_ON(!virt_dev); - - /* Extract the EP0 and Slot Ctrl */ - ep0_ctx = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx, 0); - slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->in_ctx); - - /* Only the control endpoint is valid - one endpoint context */ - slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | 0); - - switch (udev->speed) { - case USB_SPEED_SUPER: - slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); - break; - case USB_SPEED_HIGH: - slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS); - break; - case USB_SPEED_FULL: - slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS); - break; - case USB_SPEED_LOW: - slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_LS); - break; - default: - /* Speed was set earlier, this shouldn't happen. */ - BUG(); - } - - /* Extract the root hub port number */ - if (hop->parent) - while (hop->parent->parent) - hop = hop->parent; - port_num = hop->portnr; - debug("port_num = %d\n", port_num); - - slot_ctx->dev_info2 |= - cpu_to_le32(((port_num & ROOT_HUB_PORT_MASK) << - ROOT_HUB_PORT_SHIFT)); - - /* Step 4 - ring already allocated */ - /* Step 5 */ - ep0_ctx->ep_info2 = cpu_to_le32(CTRL_EP << EP_TYPE_SHIFT); - debug("SPEED = %d\n", udev->speed); - - switch (udev->speed) { - case USB_SPEED_SUPER: - ep0_ctx->ep_info2 |= cpu_to_le32(((512 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); - debug("Setting Packet size = 512bytes\n"); - break; - case USB_SPEED_HIGH: - /* USB core guesses at a 64-byte max packet first for FS devices */ - case USB_SPEED_FULL: - ep0_ctx->ep_info2 |= cpu_to_le32(((64 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); - debug("Setting Packet size = 64bytes\n"); - break; - case USB_SPEED_LOW: - ep0_ctx->ep_info2 |= cpu_to_le32(((8 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); - debug("Setting Packet size = 8bytes\n"); - break; - default: - /* New speed? */ - BUG(); - } - - /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ - ep0_ctx->ep_info2 |= - cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | - ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT)); - - trb_64 = (uintptr_t)virt_dev->eps[0].ring->first_seg->trbs; - ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state); - - /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ - - xhci_flush_cache((uint32_t)ep0_ctx, sizeof(struct xhci_ep_ctx)); - xhci_flush_cache((uint32_t)slot_ctx, sizeof(struct xhci_slot_ctx)); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci-omap.c b/qemu/roms/u-boot/drivers/usb/host/xhci-omap.c deleted file mode 100644 index e667810bb..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci-omap.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * OMAP USB HOST xHCI Controller - * - * (C) Copyright 2013 - * Texas Instruments, <www.ti.com> - * - * Author: Dan Murphy <dmurphy@ti.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> -#include <asm-generic/errno.h> -#include <asm/omap_common.h> -#include <asm/arch/cpu.h> -#include <asm/arch/sys_proto.h> - -#include <linux/compat.h> -#include <linux/usb/dwc3.h> -#include <linux/usb/xhci-omap.h> - -#include "xhci.h" - -/* Declare global data pointer */ -DECLARE_GLOBAL_DATA_PTR; - -static struct omap_xhci omap; - -inline int __board_usb_init(int index, enum usb_init_type init) -{ - return 0; -} -int board_usb_init(int index, enum usb_init_type init) - __attribute__((weak, alias("__board_usb_init"))); - -static void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) -{ - clrsetbits_le32(&dwc3_reg->g_ctl, - DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG), - DWC3_GCTL_PRTCAPDIR(mode)); -} - -static void dwc3_core_soft_reset(struct dwc3 *dwc3_reg) -{ - /* Before Resetting PHY, put Core in Reset */ - setbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); - - omap_reset_usb_phy(dwc3_reg); - - /* After PHYs are stable we can take Core out of reset state */ - clrbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); -} - -static int dwc3_core_init(struct dwc3 *dwc3_reg) -{ - u32 reg; - u32 revision; - unsigned int dwc3_hwparams1; - - revision = readl(&dwc3_reg->g_snpsid); - /* This should read as U3 followed by revision number */ - if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) { - puts("this is not a DesignWare USB3 DRD Core\n"); - return -1; - } - - dwc3_core_soft_reset(dwc3_reg); - - dwc3_hwparams1 = readl(&dwc3_reg->g_hwparams1); - - reg = readl(&dwc3_reg->g_ctl); - reg &= ~DWC3_GCTL_SCALEDOWN_MASK; - reg &= ~DWC3_GCTL_DISSCRAMBLE; - switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1)) { - case DWC3_GHWPARAMS1_EN_PWROPT_CLK: - reg &= ~DWC3_GCTL_DSBLCLKGTNG; - break; - default: - debug("No power optimization available\n"); - } - - /* - * WORKAROUND: DWC3 revisions <1.90a have a bug - * where the device can fail to connect at SuperSpeed - * and falls back to high-speed mode which causes - * the device to enter a Connect/Disconnect loop - */ - if ((revision & DWC3_REVISION_MASK) < 0x190a) - reg |= DWC3_GCTL_U2RSTECN; - - writel(reg, &dwc3_reg->g_ctl); - - return 0; -} - -static int omap_xhci_core_init(struct omap_xhci *omap) -{ - int ret = 0; - - omap_enable_phy(omap); - - ret = dwc3_core_init(omap->dwc3_reg); - if (ret) { - debug("%s:failed to initialize core\n", __func__); - return ret; - } - - /* We are hard-coding DWC3 core to Host Mode */ - dwc3_set_mode(omap->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); - - return ret; -} - -static void omap_xhci_core_exit(struct omap_xhci *omap) -{ - usb_phy_power(0); -} - -int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) -{ - struct omap_xhci *ctx = &omap; - int ret = 0; - - ctx->hcd = (struct xhci_hccr *)OMAP_XHCI_BASE; - ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); - ctx->usb3_phy = (struct omap_usb3_phy *)OMAP_OCP1_SCP_BASE; - ctx->otg_wrapper = (struct omap_dwc_wrapper *)OMAP_OTG_WRAPPER_BASE; - - ret = board_usb_init(index, USB_INIT_HOST); - if (ret != 0) { - puts("Failed to initialize board for USB\n"); - return ret; - } - - ret = omap_xhci_core_init(ctx); - if (ret < 0) { - puts("Failed to initialize xhci\n"); - return ret; - } - - *hccr = (struct xhci_hccr *)(OMAP_XHCI_BASE); - *hcor = (struct xhci_hcor *)((uint32_t) *hccr - + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); - - debug("omap-xhci: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); - - return ret; -} - -void xhci_hcd_stop(int index) -{ - struct omap_xhci *ctx = &omap; - - omap_xhci_core_exit(ctx); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci-ring.c b/qemu/roms/u-boot/drivers/usb/host/xhci-ring.c deleted file mode 100644 index 19c3ec621..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci-ring.c +++ /dev/null @@ -1,939 +0,0 @@ -/* - * USB HOST XHCI Controller stack - * - * Based on xHCI host controller driver in linux-kernel - * by Sarah Sharp. - * - * Copyright (C) 2008 Intel Corp. - * Author: Sarah Sharp - * - * Copyright (C) 2013 Samsung Electronics Co.Ltd - * Authors: Vivek Gautam <gautam.vivek@samsung.com> - * Vikas Sajjan <vikas.sajjan@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/byteorder.h> -#include <usb.h> -#include <asm/unaligned.h> -#include <asm-generic/errno.h> - -#include "xhci.h" - -/** - * Is this TRB a link TRB or was the last TRB the last TRB in this event ring - * segment? I.e. would the updated event TRB pointer step off the end of the - * event seg ? - * - * @param ctrl Host controller data structure - * @param ring pointer to the ring - * @param seg poniter to the segment to which TRB belongs - * @param trb poniter to the ring trb - * @return 1 if this TRB a link TRB else 0 - */ -static int last_trb(struct xhci_ctrl *ctrl, struct xhci_ring *ring, - struct xhci_segment *seg, union xhci_trb *trb) -{ - if (ring == ctrl->event_ring) - return trb == &seg->trbs[TRBS_PER_SEGMENT]; - else - return TRB_TYPE_LINK_LE32(trb->link.control); -} - -/** - * Does this link TRB point to the first segment in a ring, - * or was the previous TRB the last TRB on the last segment in the ERST? - * - * @param ctrl Host controller data structure - * @param ring pointer to the ring - * @param seg poniter to the segment to which TRB belongs - * @param trb poniter to the ring trb - * @return 1 if this TRB is the last TRB on the last segment else 0 - */ -static bool last_trb_on_last_seg(struct xhci_ctrl *ctrl, - struct xhci_ring *ring, - struct xhci_segment *seg, - union xhci_trb *trb) -{ - if (ring == ctrl->event_ring) - return ((trb == &seg->trbs[TRBS_PER_SEGMENT]) && - (seg->next == ring->first_seg)); - else - return le32_to_cpu(trb->link.control) & LINK_TOGGLE; -} - -/** - * See Cycle bit rules. SW is the consumer for the event ring only. - * Don't make a ring full of link TRBs. That would be dumb and this would loop. - * - * If we've just enqueued a TRB that is in the middle of a TD (meaning the - * chain bit is set), then set the chain bit in all the following link TRBs. - * If we've enqueued the last TRB in a TD, make sure the following link TRBs - * have their chain bit cleared (so that each Link TRB is a separate TD). - * - * Section 6.4.4.1 of the 0.95 spec says link TRBs cannot have the chain bit - * set, but other sections talk about dealing with the chain bit set. This was - * fixed in the 0.96 specification errata, but we have to assume that all 0.95 - * xHCI hardware can't handle the chain bit being cleared on a link TRB. - * - * @param ctrl Host controller data structure - * @param ring pointer to the ring - * @param more_trbs_coming flag to indicate whether more trbs - * are expected or NOT. - * Will you enqueue more TRBs before calling - * prepare_ring()? - * @return none - */ -static void inc_enq(struct xhci_ctrl *ctrl, struct xhci_ring *ring, - bool more_trbs_coming) -{ - u32 chain; - union xhci_trb *next; - - chain = le32_to_cpu(ring->enqueue->generic.field[3]) & TRB_CHAIN; - next = ++(ring->enqueue); - - /* - * Update the dequeue pointer further if that was a link TRB or we're at - * the end of an event ring segment (which doesn't have link TRBS) - */ - while (last_trb(ctrl, ring, ring->enq_seg, next)) { - if (ring != ctrl->event_ring) { - /* - * If the caller doesn't plan on enqueueing more - * TDs before ringing the doorbell, then we - * don't want to give the link TRB to the - * hardware just yet. We'll give the link TRB - * back in prepare_ring() just before we enqueue - * the TD at the top of the ring. - */ - if (!chain && !more_trbs_coming) - break; - - /* - * If we're not dealing with 0.95 hardware or - * isoc rings on AMD 0.96 host, - * carry over the chain bit of the previous TRB - * (which may mean the chain bit is cleared). - */ - next->link.control &= cpu_to_le32(~TRB_CHAIN); - next->link.control |= cpu_to_le32(chain); - - next->link.control ^= cpu_to_le32(TRB_CYCLE); - xhci_flush_cache((uint32_t)next, - sizeof(union xhci_trb)); - } - /* Toggle the cycle bit after the last ring segment. */ - if (last_trb_on_last_seg(ctrl, ring, - ring->enq_seg, next)) - ring->cycle_state = (ring->cycle_state ? 0 : 1); - - ring->enq_seg = ring->enq_seg->next; - ring->enqueue = ring->enq_seg->trbs; - next = ring->enqueue; - } -} - -/** - * See Cycle bit rules. SW is the consumer for the event ring only. - * Don't make a ring full of link TRBs. That would be dumb and this would loop. - * - * @param ctrl Host controller data structure - * @param ring Ring whose Dequeue TRB pointer needs to be incremented. - * return none - */ -static void inc_deq(struct xhci_ctrl *ctrl, struct xhci_ring *ring) -{ - do { - /* - * Update the dequeue pointer further if that was a link TRB or - * we're at the end of an event ring segment (which doesn't have - * link TRBS) - */ - if (last_trb(ctrl, ring, ring->deq_seg, ring->dequeue)) { - if (ring == ctrl->event_ring && - last_trb_on_last_seg(ctrl, ring, - ring->deq_seg, ring->dequeue)) { - ring->cycle_state = (ring->cycle_state ? 0 : 1); - } - ring->deq_seg = ring->deq_seg->next; - ring->dequeue = ring->deq_seg->trbs; - } else { - ring->dequeue++; - } - } while (last_trb(ctrl, ring, ring->deq_seg, ring->dequeue)); -} - -/** - * Generic function for queueing a TRB on a ring. - * The caller must have checked to make sure there's room on the ring. - * - * @param more_trbs_coming: Will you enqueue more TRBs before calling - * prepare_ring()? - * @param ctrl Host controller data structure - * @param ring pointer to the ring - * @param more_trbs_coming flag to indicate whether more trbs - * @param trb_fields pointer to trb field array containing TRB contents - * @return pointer to the enqueued trb - */ -static struct xhci_generic_trb *queue_trb(struct xhci_ctrl *ctrl, - struct xhci_ring *ring, - bool more_trbs_coming, - unsigned int *trb_fields) -{ - struct xhci_generic_trb *trb; - int i; - - trb = &ring->enqueue->generic; - - for (i = 0; i < 4; i++) - trb->field[i] = cpu_to_le32(trb_fields[i]); - - xhci_flush_cache((uint32_t)trb, sizeof(struct xhci_generic_trb)); - - inc_enq(ctrl, ring, more_trbs_coming); - - return trb; -} - -/** - * Does various checks on the endpoint ring, and makes it ready - * to queue num_trbs. - * - * @param ctrl Host controller data structure - * @param ep_ring pointer to the EP Transfer Ring - * @param ep_state State of the End Point - * @return error code in case of invalid ep_state, 0 on success - */ -static int prepare_ring(struct xhci_ctrl *ctrl, struct xhci_ring *ep_ring, - u32 ep_state) -{ - union xhci_trb *next = ep_ring->enqueue; - - /* Make sure the endpoint has been added to xHC schedule */ - switch (ep_state) { - case EP_STATE_DISABLED: - /* - * USB core changed config/interfaces without notifying us, - * or hardware is reporting the wrong state. - */ - puts("WARN urb submitted to disabled ep\n"); - return -ENOENT; - case EP_STATE_ERROR: - puts("WARN waiting for error on ep to be cleared\n"); - return -EINVAL; - case EP_STATE_HALTED: - puts("WARN halted endpoint, queueing URB anyway.\n"); - case EP_STATE_STOPPED: - case EP_STATE_RUNNING: - debug("EP STATE RUNNING.\n"); - break; - default: - puts("ERROR unknown endpoint state for ep\n"); - return -EINVAL; - } - - while (last_trb(ctrl, ep_ring, ep_ring->enq_seg, next)) { - /* - * If we're not dealing with 0.95 hardware or isoc rings - * on AMD 0.96 host, clear the chain bit. - */ - next->link.control &= cpu_to_le32(~TRB_CHAIN); - - next->link.control ^= cpu_to_le32(TRB_CYCLE); - - xhci_flush_cache((uint32_t)next, sizeof(union xhci_trb)); - - /* Toggle the cycle bit after the last ring segment. */ - if (last_trb_on_last_seg(ctrl, ep_ring, - ep_ring->enq_seg, next)) - ep_ring->cycle_state = (ep_ring->cycle_state ? 0 : 1); - ep_ring->enq_seg = ep_ring->enq_seg->next; - ep_ring->enqueue = ep_ring->enq_seg->trbs; - next = ep_ring->enqueue; - } - - return 0; -} - -/** - * Generic function for queueing a command TRB on the command ring. - * Check to make sure there's room on the command ring for one command TRB. - * - * @param ctrl Host controller data structure - * @param ptr Pointer address to write in the first two fields (opt.) - * @param slot_id Slot ID to encode in the flags field (opt.) - * @param ep_index Endpoint index to encode in the flags field (opt.) - * @param cmd Command type to enqueue - * @return none - */ -void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id, - u32 ep_index, trb_type cmd) -{ - u32 fields[4]; - u64 val_64 = (uintptr_t)ptr; - - BUG_ON(prepare_ring(ctrl, ctrl->cmd_ring, EP_STATE_RUNNING)); - - fields[0] = lower_32_bits(val_64); - fields[1] = upper_32_bits(val_64); - fields[2] = 0; - fields[3] = TRB_TYPE(cmd) | EP_ID_FOR_TRB(ep_index) | - SLOT_ID_FOR_TRB(slot_id) | ctrl->cmd_ring->cycle_state; - - queue_trb(ctrl, ctrl->cmd_ring, false, fields); - - /* Ring the command ring doorbell */ - xhci_writel(&ctrl->dba->doorbell[0], DB_VALUE_HOST); -} - -/** - * The TD size is the number of bytes remaining in the TD (including this TRB), - * right shifted by 10. - * It must fit in bits 21:17, so it can't be bigger than 31. - * - * @param remainder remaining packets to be sent - * @return remainder if remainder is less than max else max - */ -static u32 xhci_td_remainder(unsigned int remainder) -{ - u32 max = (1 << (21 - 17 + 1)) - 1; - - if ((remainder >> 10) >= max) - return max << 17; - else - return (remainder >> 10) << 17; -} - -/** - * Finds out the remanining packets to be sent - * - * @param running_total total size sent so far - * @param trb_buff_len length of the TRB Buffer - * @param total_packet_count total packet count - * @param maxpacketsize max packet size of current pipe - * @param num_trbs_left number of TRBs left to be processed - * @return 0 if running_total or trb_buff_len is 0, else remainder - */ -static u32 xhci_v1_0_td_remainder(int running_total, - int trb_buff_len, - unsigned int total_packet_count, - int maxpacketsize, - unsigned int num_trbs_left) -{ - int packets_transferred; - - /* One TRB with a zero-length data packet. */ - if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0)) - return 0; - - /* - * All the TRB queueing functions don't count the current TRB in - * running_total. - */ - packets_transferred = (running_total + trb_buff_len) / maxpacketsize; - - if ((total_packet_count - packets_transferred) > 31) - return 31 << 17; - return (total_packet_count - packets_transferred) << 17; -} - -/** - * Ring the doorbell of the End Point - * - * @param udev pointer to the USB device structure - * @param ep_index index of the endpoint - * @param start_cycle cycle flag of the first TRB - * @param start_trb pionter to the first TRB - * @return none - */ -static void giveback_first_trb(struct usb_device *udev, int ep_index, - int start_cycle, - struct xhci_generic_trb *start_trb) -{ - struct xhci_ctrl *ctrl = udev->controller; - - /* - * Pass all the TRBs to the hardware at once and make sure this write - * isn't reordered. - */ - if (start_cycle) - start_trb->field[3] |= cpu_to_le32(start_cycle); - else - start_trb->field[3] &= cpu_to_le32(~TRB_CYCLE); - - xhci_flush_cache((uint32_t)start_trb, sizeof(struct xhci_generic_trb)); - - /* Ringing EP doorbell here */ - xhci_writel(&ctrl->dba->doorbell[udev->slot_id], - DB_VALUE(ep_index, 0)); - - return; -} - -/**** POLLING mechanism for XHCI ****/ - -/** - * Finalizes a handled event TRB by advancing our dequeue pointer and giving - * the TRB back to the hardware for recycling. Must call this exactly once at - * the end of each event handler, and not touch the TRB again afterwards. - * - * @param ctrl Host controller data structure - * @return none - */ -void xhci_acknowledge_event(struct xhci_ctrl *ctrl) -{ - /* Advance our dequeue pointer to the next event */ - inc_deq(ctrl, ctrl->event_ring); - - /* Inform the hardware */ - xhci_writeq(&ctrl->ir_set->erst_dequeue, - (uintptr_t)ctrl->event_ring->dequeue | ERST_EHB); -} - -/** - * Checks if there is a new event to handle on the event ring. - * - * @param ctrl Host controller data structure - * @return 0 if failure else 1 on success - */ -static int event_ready(struct xhci_ctrl *ctrl) -{ - union xhci_trb *event; - - xhci_inval_cache((uint32_t)ctrl->event_ring->dequeue, - sizeof(union xhci_trb)); - - event = ctrl->event_ring->dequeue; - - /* Does the HC or OS own the TRB? */ - if ((le32_to_cpu(event->event_cmd.flags) & TRB_CYCLE) != - ctrl->event_ring->cycle_state) - return 0; - - return 1; -} - -/** - * Waits for a specific type of event and returns it. Discards unexpected - * events. Caller *must* call xhci_acknowledge_event() after it is finished - * processing the event, and must not access the returned pointer afterwards. - * - * @param ctrl Host controller data structure - * @param expected TRB type expected from Event TRB - * @return pointer to event trb - */ -union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) -{ - trb_type type; - unsigned long ts = get_timer(0); - - do { - union xhci_trb *event = ctrl->event_ring->dequeue; - - if (!event_ready(ctrl)) - continue; - - type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags)); - if (type == expected) - return event; - - if (type == TRB_PORT_STATUS) - /* TODO: remove this once enumeration has been reworked */ - /* - * Port status change events always have a - * successful completion code - */ - BUG_ON(GET_COMP_CODE( - le32_to_cpu(event->generic.field[2])) != - COMP_SUCCESS); - else - printf("Unexpected XHCI event TRB, skipping... " - "(%08x %08x %08x %08x)\n", - le32_to_cpu(event->generic.field[0]), - le32_to_cpu(event->generic.field[1]), - le32_to_cpu(event->generic.field[2]), - le32_to_cpu(event->generic.field[3])); - - xhci_acknowledge_event(ctrl); - } while (get_timer(ts) < XHCI_TIMEOUT); - - if (expected == TRB_TRANSFER) - return NULL; - - printf("XHCI timeout on event type %d... cannot recover.\n", expected); - BUG(); -} - -/* - * Stops transfer processing for an endpoint and throws away all unprocessed - * TRBs by setting the xHC's dequeue pointer to our enqueue pointer. The next - * xhci_bulk_tx/xhci_ctrl_tx on this enpoint will add new transfers there and - * ring the doorbell, causing this endpoint to start working again. - * (Careful: This will BUG() when there was no transfer in progress. Shouldn't - * happen in practice for current uses and is too complicated to fix right now.) - */ -static void abort_td(struct usb_device *udev, int ep_index) -{ - struct xhci_ctrl *ctrl = udev->controller; - struct xhci_ring *ring = ctrl->devs[udev->slot_id]->eps[ep_index].ring; - union xhci_trb *event; - u32 field; - - xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_STOP_RING); - - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); - field = le32_to_cpu(event->trans_event.flags); - BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); - BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - BUG_ON(GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len - != COMP_STOP))); - xhci_acknowledge_event(ctrl); - - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) - != udev->slot_id || GET_COMP_CODE(le32_to_cpu( - event->event_cmd.status)) != COMP_SUCCESS); - xhci_acknowledge_event(ctrl); - - xhci_queue_command(ctrl, (void *)((uintptr_t)ring->enqueue | - ring->cycle_state), udev->slot_id, ep_index, TRB_SET_DEQ); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) - != udev->slot_id || GET_COMP_CODE(le32_to_cpu( - event->event_cmd.status)) != COMP_SUCCESS); - xhci_acknowledge_event(ctrl); -} - -static void record_transfer_result(struct usb_device *udev, - union xhci_trb *event, int length) -{ - udev->act_len = min(length, length - - EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len))); - - switch (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len))) { - case COMP_SUCCESS: - BUG_ON(udev->act_len != length); - /* fallthrough */ - case COMP_SHORT_TX: - udev->status = 0; - break; - case COMP_STALL: - udev->status = USB_ST_STALLED; - break; - case COMP_DB_ERR: - case COMP_TRB_ERR: - udev->status = USB_ST_BUF_ERR; - break; - case COMP_BABBLE: - udev->status = USB_ST_BABBLE_DET; - break; - default: - udev->status = 0x80; /* USB_ST_TOO_LAZY_TO_MAKE_A_NEW_MACRO */ - } -} - -/**** Bulk and Control transfer methods ****/ -/** - * Queues up the BULK Request - * - * @param udev pointer to the USB device structure - * @param pipe contains the DIR_IN or OUT , devnum - * @param length length of the buffer - * @param buffer buffer to be read/written based on the request - * @return returns 0 if successful else -1 on failure - */ -int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer) -{ - int num_trbs = 0; - struct xhci_generic_trb *start_trb; - bool first_trb = 0; - int start_cycle; - u32 field = 0; - u32 length_field = 0; - struct xhci_ctrl *ctrl = udev->controller; - int slot_id = udev->slot_id; - int ep_index; - struct xhci_virt_device *virt_dev; - struct xhci_ep_ctx *ep_ctx; - struct xhci_ring *ring; /* EP transfer ring */ - union xhci_trb *event; - - int running_total, trb_buff_len; - unsigned int total_packet_count; - int maxpacketsize; - u64 addr; - int ret; - u32 trb_fields[4]; - u64 val_64 = (uintptr_t)buffer; - - debug("dev=%p, pipe=%lx, buffer=%p, length=%d\n", - udev, pipe, buffer, length); - - ep_index = usb_pipe_ep_index(pipe); - virt_dev = ctrl->devs[slot_id]; - - xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes, - virt_dev->out_ctx->size); - - ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index); - - ring = virt_dev->eps[ep_index].ring; - /* - * How much data is (potentially) left before the 64KB boundary? - * XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec) - * that the buffer should not span 64KB boundary. if so - * we send request in more than 1 TRB by chaining them. - */ - running_total = TRB_MAX_BUFF_SIZE - - (lower_32_bits(val_64) & (TRB_MAX_BUFF_SIZE - 1)); - trb_buff_len = running_total; - running_total &= TRB_MAX_BUFF_SIZE - 1; - - /* - * If there's some data on this 64KB chunk, or we have to send a - * zero-length transfer, we need at least one TRB - */ - if (running_total != 0 || length == 0) - num_trbs++; - - /* How many more 64KB chunks to transfer, how many more TRBs? */ - while (running_total < length) { - num_trbs++; - running_total += TRB_MAX_BUFF_SIZE; - } - - /* - * XXX: Calling routine prepare_ring() called in place of - * prepare_trasfer() as there in 'Linux' since we are not - * maintaining multiple TDs/transfer at the same time. - */ - ret = prepare_ring(ctrl, ring, - le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK); - if (ret < 0) - return ret; - - /* - * Don't give the first TRB to the hardware (by toggling the cycle bit) - * until we've finished creating all the other TRBs. The ring's cycle - * state may change as we enqueue the other TRBs, so save it too. - */ - start_trb = &ring->enqueue->generic; - start_cycle = ring->cycle_state; - - running_total = 0; - maxpacketsize = usb_maxpacket(udev, pipe); - - total_packet_count = DIV_ROUND_UP(length, maxpacketsize); - - /* How much data is in the first TRB? */ - /* - * How much data is (potentially) left before the 64KB boundary? - * XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec) - * that the buffer should not span 64KB boundary. if so - * we send request in more than 1 TRB by chaining them. - */ - addr = val_64; - - if (trb_buff_len > length) - trb_buff_len = length; - - first_trb = true; - - /* flush the buffer before use */ - xhci_flush_cache((uint32_t)buffer, length); - - /* Queue the first TRB, even if it's zero-length */ - do { - u32 remainder = 0; - field = 0; - /* Don't change the cycle bit of the first TRB until later */ - if (first_trb) { - first_trb = false; - if (start_cycle == 0) - field |= TRB_CYCLE; - } else { - field |= ring->cycle_state; - } - - /* - * Chain all the TRBs together; clear the chain bit in the last - * TRB to indicate it's the last TRB in the chain. - */ - if (num_trbs > 1) - field |= TRB_CHAIN; - else - field |= TRB_IOC; - - /* Only set interrupt on short packet for IN endpoints */ - if (usb_pipein(pipe)) - field |= TRB_ISP; - - /* Set the TRB length, TD size, and interrupter fields. */ - if (HC_VERSION(xhci_readl(&ctrl->hccr->cr_capbase)) < 0x100) - remainder = xhci_td_remainder(length - running_total); - else - remainder = xhci_v1_0_td_remainder(running_total, - trb_buff_len, - total_packet_count, - maxpacketsize, - num_trbs - 1); - - length_field = ((trb_buff_len & TRB_LEN_MASK) | - remainder | - ((0 & TRB_INTR_TARGET_MASK) << - TRB_INTR_TARGET_SHIFT)); - - trb_fields[0] = lower_32_bits(addr); - trb_fields[1] = upper_32_bits(addr); - trb_fields[2] = length_field; - trb_fields[3] = field | (TRB_NORMAL << TRB_TYPE_SHIFT); - - queue_trb(ctrl, ring, (num_trbs > 1), trb_fields); - - --num_trbs; - - running_total += trb_buff_len; - - /* Calculate length for next transfer */ - addr += trb_buff_len; - trb_buff_len = min((length - running_total), TRB_MAX_BUFF_SIZE); - } while (running_total < length); - - giveback_first_trb(udev, ep_index, start_cycle, start_trb); - - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); - if (!event) { - debug("XHCI bulk transfer timed out, aborting...\n"); - abort_td(udev, ep_index); - udev->status = USB_ST_NAK_REC; /* closest thing to a timeout */ - udev->act_len = 0; - return -ETIMEDOUT; - } - field = le32_to_cpu(event->trans_event.flags); - - BUG_ON(TRB_TO_SLOT_ID(field) != slot_id); - BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - BUG_ON(*(void **)(uintptr_t)le64_to_cpu(event->trans_event.buffer) - - buffer > (size_t)length); - - record_transfer_result(udev, event, length); - xhci_acknowledge_event(ctrl); - xhci_inval_cache((uint32_t)buffer, length); - - return (udev->status != USB_ST_NOT_PROC) ? 0 : -1; -} - -/** - * Queues up the Control Transfer Request - * - * @param udev pointer to the USB device structure - * @param pipe contains the DIR_IN or OUT , devnum - * @param req request type - * @param length length of the buffer - * @param buffer buffer to be read/written based on the request - * @return returns 0 if successful else error code on failure - */ -int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, - struct devrequest *req, int length, - void *buffer) -{ - int ret; - int start_cycle; - int num_trbs; - u32 field; - u32 length_field; - u64 buf_64 = 0; - struct xhci_generic_trb *start_trb; - struct xhci_ctrl *ctrl = udev->controller; - int slot_id = udev->slot_id; - int ep_index; - u32 trb_fields[4]; - struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; - struct xhci_ring *ep_ring; - union xhci_trb *event; - - debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n", - req->request, req->request, - req->requesttype, req->requesttype, - le16_to_cpu(req->value), le16_to_cpu(req->value), - le16_to_cpu(req->index)); - - ep_index = usb_pipe_ep_index(pipe); - - ep_ring = virt_dev->eps[ep_index].ring; - - /* - * Check to see if the max packet size for the default control - * endpoint changed during FS device enumeration - */ - if (udev->speed == USB_SPEED_FULL) { - ret = xhci_check_maxpacket(udev); - if (ret < 0) - return ret; - } - - xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes, - virt_dev->out_ctx->size); - - struct xhci_ep_ctx *ep_ctx = NULL; - ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index); - - /* 1 TRB for setup, 1 for status */ - num_trbs = 2; - /* - * Don't need to check if we need additional event data and normal TRBs, - * since data in control transfers will never get bigger than 16MB - * XXX: can we get a buffer that crosses 64KB boundaries? - */ - - if (length > 0) - num_trbs++; - /* - * XXX: Calling routine prepare_ring() called in place of - * prepare_trasfer() as there in 'Linux' since we are not - * maintaining multiple TDs/transfer at the same time. - */ - ret = prepare_ring(ctrl, ep_ring, - le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK); - - if (ret < 0) - return ret; - - /* - * Don't give the first TRB to the hardware (by toggling the cycle bit) - * until we've finished creating all the other TRBs. The ring's cycle - * state may change as we enqueue the other TRBs, so save it too. - */ - start_trb = &ep_ring->enqueue->generic; - start_cycle = ep_ring->cycle_state; - - debug("start_trb %p, start_cycle %d\n", start_trb, start_cycle); - - /* Queue setup TRB - see section 6.4.1.2.1 */ - /* FIXME better way to translate setup_packet into two u32 fields? */ - field = 0; - field |= TRB_IDT | (TRB_SETUP << TRB_TYPE_SHIFT); - if (start_cycle == 0) - field |= 0x1; - - /* xHCI 1.0 6.4.1.2.1: Transfer Type field */ - if (HC_VERSION(xhci_readl(&ctrl->hccr->cr_capbase)) == 0x100) { - if (length > 0) { - if (req->requesttype & USB_DIR_IN) - field |= (TRB_DATA_IN << TRB_TX_TYPE_SHIFT); - else - field |= (TRB_DATA_OUT << TRB_TX_TYPE_SHIFT); - } - } - - debug("req->requesttype = %d, req->request = %d," - "le16_to_cpu(req->value) = %d," - "le16_to_cpu(req->index) = %d," - "le16_to_cpu(req->length) = %d\n", - req->requesttype, req->request, le16_to_cpu(req->value), - le16_to_cpu(req->index), le16_to_cpu(req->length)); - - trb_fields[0] = req->requesttype | req->request << 8 | - le16_to_cpu(req->value) << 16; - trb_fields[1] = le16_to_cpu(req->index) | - le16_to_cpu(req->length) << 16; - /* TRB_LEN | (TRB_INTR_TARGET) */ - trb_fields[2] = (8 | ((0 & TRB_INTR_TARGET_MASK) << - TRB_INTR_TARGET_SHIFT)); - /* Immediate data in pointer */ - trb_fields[3] = field; - queue_trb(ctrl, ep_ring, true, trb_fields); - - /* Re-initializing field to zero */ - field = 0; - /* If there's data, queue data TRBs */ - /* Only set interrupt on short packet for IN endpoints */ - if (usb_pipein(pipe)) - field = TRB_ISP | (TRB_DATA << TRB_TYPE_SHIFT); - else - field = (TRB_DATA << TRB_TYPE_SHIFT); - - length_field = (length & TRB_LEN_MASK) | xhci_td_remainder(length) | - ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT); - debug("length_field = %d, length = %d," - "xhci_td_remainder(length) = %d , TRB_INTR_TARGET(0) = %d\n", - length_field, (length & TRB_LEN_MASK), - xhci_td_remainder(length), 0); - - if (length > 0) { - if (req->requesttype & USB_DIR_IN) - field |= TRB_DIR_IN; - buf_64 = (uintptr_t)buffer; - - trb_fields[0] = lower_32_bits(buf_64); - trb_fields[1] = upper_32_bits(buf_64); - trb_fields[2] = length_field; - trb_fields[3] = field | ep_ring->cycle_state; - - xhci_flush_cache((uint32_t)buffer, length); - queue_trb(ctrl, ep_ring, true, trb_fields); - } - - /* - * Queue status TRB - - * see Table 7 and sections 4.11.2.2 and 6.4.1.2.3 - */ - - /* If the device sent data, the status stage is an OUT transfer */ - field = 0; - if (length > 0 && req->requesttype & USB_DIR_IN) - field = 0; - else - field = TRB_DIR_IN; - - trb_fields[0] = 0; - trb_fields[1] = 0; - trb_fields[2] = ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT); - /* Event on completion */ - trb_fields[3] = field | TRB_IOC | - (TRB_STATUS << TRB_TYPE_SHIFT) | - ep_ring->cycle_state; - - queue_trb(ctrl, ep_ring, false, trb_fields); - - giveback_first_trb(udev, ep_index, start_cycle, start_trb); - - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); - if (!event) - goto abort; - field = le32_to_cpu(event->trans_event.flags); - - BUG_ON(TRB_TO_SLOT_ID(field) != slot_id); - BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - - record_transfer_result(udev, event, length); - xhci_acknowledge_event(ctrl); - - /* Invalidate buffer to make it available to usb-core */ - if (length > 0) - xhci_inval_cache((uint32_t)buffer, length); - - if (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len)) - == COMP_SHORT_TX) { - /* Short data stage, clear up additional status stage event */ - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); - if (!event) - goto abort; - BUG_ON(TRB_TO_SLOT_ID(field) != slot_id); - BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - xhci_acknowledge_event(ctrl); - } - - return (udev->status != USB_ST_NOT_PROC) ? 0 : -1; - -abort: - debug("XHCI control transfer timed out, aborting...\n"); - abort_td(udev, ep_index); - udev->status = USB_ST_NAK_REC; - udev->act_len = 0; - return -ETIMEDOUT; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci.c b/qemu/roms/u-boot/drivers/usb/host/xhci.c deleted file mode 100644 index d1c2e5c45..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* - * USB HOST XHCI Controller stack - * - * Based on xHCI host controller driver in linux-kernel - * by Sarah Sharp. - * - * Copyright (C) 2008 Intel Corp. - * Author: Sarah Sharp - * - * Copyright (C) 2013 Samsung Electronics Co.Ltd - * Authors: Vivek Gautam <gautam.vivek@samsung.com> - * Vikas Sajjan <vikas.sajjan@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/** - * This file gives the xhci stack for usb3.0 looking into - * xhci specification Rev1.0 (5/21/10). - * The quirk devices support hasn't been given yet. - */ - -#include <common.h> -#include <asm/byteorder.h> -#include <usb.h> -#include <malloc.h> -#include <watchdog.h> -#include <asm/cache.h> -#include <asm/unaligned.h> -#include <asm-generic/errno.h> -#include "xhci.h" - -#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT -#define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#endif - -static struct descriptor { - struct usb_hub_descriptor hub; - struct usb_device_descriptor device; - struct usb_config_descriptor config; - struct usb_interface_descriptor interface; - struct usb_endpoint_descriptor endpoint; - struct usb_ss_ep_comp_descriptor ep_companion; -} __attribute__ ((packed)) descriptor = { - { - 0xc, /* bDescLength */ - 0x2a, /* bDescriptorType: hub descriptor */ - 2, /* bNrPorts -- runtime modified */ - cpu_to_le16(0x8), /* wHubCharacteristics */ - 10, /* bPwrOn2PwrGood */ - 0, /* bHubCntrCurrent */ - {}, /* Device removable */ - {} /* at most 7 ports! XXX */ - }, - { - 0x12, /* bLength */ - 1, /* bDescriptorType: UDESC_DEVICE */ - cpu_to_le16(0x0300), /* bcdUSB: v3.0 */ - 9, /* bDeviceClass: UDCLASS_HUB */ - 0, /* bDeviceSubClass: UDSUBCLASS_HUB */ - 3, /* bDeviceProtocol: UDPROTO_SSHUBSTT */ - 9, /* bMaxPacketSize: 512 bytes 2^9 */ - 0x0000, /* idVendor */ - 0x0000, /* idProduct */ - cpu_to_le16(0x0100), /* bcdDevice */ - 1, /* iManufacturer */ - 2, /* iProduct */ - 0, /* iSerialNumber */ - 1 /* bNumConfigurations: 1 */ - }, - { - 0x9, - 2, /* bDescriptorType: UDESC_CONFIG */ - cpu_to_le16(0x1f), /* includes SS endpoint descriptor */ - 1, /* bNumInterface */ - 1, /* bConfigurationValue */ - 0, /* iConfiguration */ - 0x40, /* bmAttributes: UC_SELF_POWER */ - 0 /* bMaxPower */ - }, - { - 0x9, /* bLength */ - 4, /* bDescriptorType: UDESC_INTERFACE */ - 0, /* bInterfaceNumber */ - 0, /* bAlternateSetting */ - 1, /* bNumEndpoints */ - 9, /* bInterfaceClass: UICLASS_HUB */ - 0, /* bInterfaceSubClass: UISUBCLASS_HUB */ - 0, /* bInterfaceProtocol: UIPROTO_HSHUBSTT */ - 0 /* iInterface */ - }, - { - 0x7, /* bLength */ - 5, /* bDescriptorType: UDESC_ENDPOINT */ - 0x81, /* bEndpointAddress: IN endpoint 1 */ - 3, /* bmAttributes: UE_INTERRUPT */ - 8, /* wMaxPacketSize */ - 255 /* bInterval */ - }, - { - 0x06, /* ss_bLength */ - 0x30, /* ss_bDescriptorType: SS EP Companion */ - 0x00, /* ss_bMaxBurst: allows 1 TX between ACKs */ - /* ss_bmAttributes: 1 packet per service interval */ - 0x00, - /* ss_wBytesPerInterval: 15 bits for max 15 ports */ - cpu_to_le16(0x02), - }, -}; - -static struct xhci_ctrl xhcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; - -/** - * Waits for as per specified amount of time - * for the "result" to match with "done" - * - * @param ptr pointer to the register to be read - * @param mask mask for the value read - * @param done value to be campared with result - * @param usec time to wait till - * @return 0 if handshake is success else < 0 on failure - */ -static int handshake(uint32_t volatile *ptr, uint32_t mask, - uint32_t done, int usec) -{ - uint32_t result; - - do { - result = xhci_readl(ptr); - if (result == ~(uint32_t)0) - return -ENODEV; - result &= mask; - if (result == done) - return 0; - usec--; - udelay(1); - } while (usec > 0); - - return -ETIMEDOUT; -} - -/** - * Set the run bit and wait for the host to be running. - * - * @param hcor pointer to host controller operation registers - * @return status of the Handshake - */ -static int xhci_start(struct xhci_hcor *hcor) -{ - u32 temp; - int ret; - - puts("Starting the controller\n"); - temp = xhci_readl(&hcor->or_usbcmd); - temp |= (CMD_RUN); - xhci_writel(&hcor->or_usbcmd, temp); - - /* - * Wait for the HCHalted Status bit to be 0 to indicate the host is - * running. - */ - ret = handshake(&hcor->or_usbsts, STS_HALT, 0, XHCI_MAX_HALT_USEC); - if (ret) - debug("Host took too long to start, " - "waited %u microseconds.\n", - XHCI_MAX_HALT_USEC); - return ret; -} - -/** - * Resets the XHCI Controller - * - * @param hcor pointer to host controller operation registers - * @return -EBUSY if XHCI Controller is not halted else status of handshake - */ -int xhci_reset(struct xhci_hcor *hcor) -{ - u32 cmd; - u32 state; - int ret; - - /* Halting the Host first */ - debug("// Halt the HC\n"); - state = xhci_readl(&hcor->or_usbsts) & STS_HALT; - if (!state) { - cmd = xhci_readl(&hcor->or_usbcmd); - cmd &= ~CMD_RUN; - xhci_writel(&hcor->or_usbcmd, cmd); - } - - ret = handshake(&hcor->or_usbsts, - STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); - if (ret) { - printf("Host not halted after %u microseconds.\n", - XHCI_MAX_HALT_USEC); - return -EBUSY; - } - - debug("// Reset the HC\n"); - cmd = xhci_readl(&hcor->or_usbcmd); - cmd |= CMD_RESET; - xhci_writel(&hcor->or_usbcmd, cmd); - - ret = handshake(&hcor->or_usbcmd, CMD_RESET, 0, XHCI_MAX_RESET_USEC); - if (ret) - return ret; - - /* - * xHCI cannot write to any doorbells or operational registers other - * than status until the "Controller Not Ready" flag is cleared. - */ - return handshake(&hcor->or_usbsts, STS_CNR, 0, XHCI_MAX_RESET_USEC); -} - -/** - * Used for passing endpoint bitmasks between the core and HCDs. - * Find the index for an endpoint given its descriptor. - * Use the return value to right shift 1 for the bitmask. - * - * Index = (epnum * 2) + direction - 1, - * where direction = 0 for OUT, 1 for IN. - * For control endpoints, the IN index is used (OUT index is unused), so - * index = (epnum * 2) + direction - 1 = (epnum * 2) + 1 - 1 = (epnum * 2) - * - * @param desc USB enpdoint Descriptor - * @return index of the Endpoint - */ -static unsigned int xhci_get_ep_index(struct usb_endpoint_descriptor *desc) -{ - unsigned int index; - - if (usb_endpoint_xfer_control(desc)) - index = (unsigned int)(usb_endpoint_num(desc) * 2); - else - index = (unsigned int)((usb_endpoint_num(desc) * 2) - - (usb_endpoint_dir_in(desc) ? 0 : 1)); - - return index; -} - -/** - * Issue a configure endpoint command or evaluate context command - * and wait for it to finish. - * - * @param udev pointer to the Device Data Structure - * @param ctx_change flag to indicate the Context has changed or NOT - * @return 0 on success, -1 on failure - */ -static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change) -{ - struct xhci_container_ctx *in_ctx; - struct xhci_virt_device *virt_dev; - struct xhci_ctrl *ctrl = udev->controller; - union xhci_trb *event; - - virt_dev = ctrl->devs[udev->slot_id]; - in_ctx = virt_dev->in_ctx; - - xhci_flush_cache((uint32_t)in_ctx->bytes, in_ctx->size); - xhci_queue_command(ctrl, in_ctx->bytes, udev->slot_id, 0, - ctx_change ? TRB_EVAL_CONTEXT : TRB_CONFIG_EP); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) - != udev->slot_id); - - switch (GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))) { - case COMP_SUCCESS: - debug("Successful %s command\n", - ctx_change ? "Evaluate Context" : "Configure Endpoint"); - break; - default: - printf("ERROR: %s command returned completion code %d.\n", - ctx_change ? "Evaluate Context" : "Configure Endpoint", - GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))); - return -EINVAL; - } - - xhci_acknowledge_event(ctrl); - - return 0; -} - -/** - * Configure the endpoint, programming the device contexts. - * - * @param udev pointer to the USB device structure - * @return returns the status of the xhci_configure_endpoints - */ -static int xhci_set_configuration(struct usb_device *udev) -{ - struct xhci_container_ctx *in_ctx; - struct xhci_container_ctx *out_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_slot_ctx *slot_ctx; - struct xhci_ep_ctx *ep_ctx[MAX_EP_CTX_NUM]; - int cur_ep; - int max_ep_flag = 0; - int ep_index; - unsigned int dir; - unsigned int ep_type; - struct xhci_ctrl *ctrl = udev->controller; - int num_of_ep; - int ep_flag = 0; - u64 trb_64 = 0; - int slot_id = udev->slot_id; - struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; - struct usb_interface *ifdesc; - - out_ctx = virt_dev->out_ctx; - in_ctx = virt_dev->in_ctx; - - num_of_ep = udev->config.if_desc[0].no_of_ep; - ifdesc = &udev->config.if_desc[0]; - - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); - /* Zero the input context control */ - ctrl_ctx->add_flags = 0; - ctrl_ctx->drop_flags = 0; - - /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - ep_flag = xhci_get_ep_index(&ifdesc->ep_desc[cur_ep]); - ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); - if (max_ep_flag < ep_flag) - max_ep_flag = ep_flag; - } - - xhci_inval_cache((uint32_t)out_ctx->bytes, out_ctx->size); - - /* slot context */ - xhci_slot_copy(ctrl, in_ctx, out_ctx); - slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); - slot_ctx->dev_info &= ~(LAST_CTX_MASK); - slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0); - - xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); - - /* filling up ep contexts */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - struct usb_endpoint_descriptor *endpt_desc = NULL; - - endpt_desc = &ifdesc->ep_desc[cur_ep]; - trb_64 = 0; - - ep_index = xhci_get_ep_index(endpt_desc); - ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); - - /* Allocate the ep rings */ - virt_dev->eps[ep_index].ring = xhci_ring_alloc(1, true); - if (!virt_dev->eps[ep_index].ring) - return -ENOMEM; - - /*NOTE: ep_desc[0] actually represents EP1 and so on */ - dir = (((endpt_desc->bEndpointAddress) & (0x80)) >> 7); - ep_type = (((endpt_desc->bmAttributes) & (0x3)) | (dir << 2)); - ep_ctx[ep_index]->ep_info2 = - cpu_to_le32(ep_type << EP_TYPE_SHIFT); - ep_ctx[ep_index]->ep_info2 |= - cpu_to_le32(MAX_PACKET - (get_unaligned(&endpt_desc->wMaxPacketSize))); - - ep_ctx[ep_index]->ep_info2 |= - cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | - ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT)); - - trb_64 = (uintptr_t) - virt_dev->eps[ep_index].ring->enqueue; - ep_ctx[ep_index]->deq = cpu_to_le64(trb_64 | - virt_dev->eps[ep_index].ring->cycle_state); - } - - return xhci_configure_endpoints(udev, false); -} - -/** - * Issue an Address Device command (which will issue a SetAddress request to - * the device). - * - * @param udev pointer to the Device Data Structure - * @return 0 if successful else error code on failure - */ -static int xhci_address_device(struct usb_device *udev) -{ - int ret = 0; - struct xhci_ctrl *ctrl = udev->controller; - struct xhci_slot_ctx *slot_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_virt_device *virt_dev; - int slot_id = udev->slot_id; - union xhci_trb *event; - - virt_dev = ctrl->devs[slot_id]; - - /* - * This is the first Set Address since device plug-in - * so setting up the slot context. - */ - debug("Setting up addressable devices\n"); - xhci_setup_addressable_virt_dev(udev); - - ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx); - ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); - ctrl_ctx->drop_flags = 0; - - xhci_queue_command(ctrl, (void *)ctrl_ctx, slot_id, 0, TRB_ADDR_DEV); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != slot_id); - - switch (GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))) { - case COMP_CTX_STATE: - case COMP_EBADSLT: - printf("Setup ERROR: address device command for slot %d.\n", - slot_id); - ret = -EINVAL; - break; - case COMP_TX_ERR: - puts("Device not responding to set address.\n"); - ret = -EPROTO; - break; - case COMP_DEV_ERR: - puts("ERROR: Incompatible device" - "for address device command.\n"); - ret = -ENODEV; - break; - case COMP_SUCCESS: - debug("Successful Address Device command\n"); - udev->status = 0; - break; - default: - printf("ERROR: unexpected command completion code 0x%x.\n", - GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))); - ret = -EINVAL; - break; - } - - xhci_acknowledge_event(ctrl); - - if (ret < 0) - /* - * TODO: Unsuccessful Address Device command shall leave the - * slot in default state. So, issue Disable Slot command now. - */ - return ret; - - xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes, - virt_dev->out_ctx->size); - slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->out_ctx); - - debug("xHC internal address is: %d\n", - le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK); - - return 0; -} - -/** - * Issue Enable slot command to the controller to allocate - * device slot and assign the slot id. It fails if the xHC - * ran out of device slots, the Enable Slot command timed out, - * or allocating memory failed. - * - * @param udev pointer to the Device Data Structure - * @return Returns 0 on succes else return error code on failure - */ -int usb_alloc_device(struct usb_device *udev) -{ - union xhci_trb *event; - struct xhci_ctrl *ctrl = udev->controller; - int ret; - - /* - * Root hub will be first device to be initailized. - * If this device is root-hub, don't do any xHC related - * stuff. - */ - if (ctrl->rootdev == 0) { - udev->speed = USB_SPEED_SUPER; - return 0; - } - - xhci_queue_command(ctrl, NULL, 0, 0, TRB_ENABLE_SLOT); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(GET_COMP_CODE(le32_to_cpu(event->event_cmd.status)) - != COMP_SUCCESS); - - udev->slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)); - - xhci_acknowledge_event(ctrl); - - ret = xhci_alloc_virt_device(udev); - if (ret < 0) { - /* - * TODO: Unsuccessful Address Device command shall leave - * the slot in default. So, issue Disable Slot command now. - */ - puts("Could not allocate xHCI USB device data structures\n"); - return ret; - } - - return 0; -} - -/* - * Full speed devices may have a max packet size greater than 8 bytes, but the - * USB core doesn't know that until it reads the first 8 bytes of the - * descriptor. If the usb_device's max packet size changes after that point, - * we need to issue an evaluate context command and wait on it. - * - * @param udev pointer to the Device Data Structure - * @return returns the status of the xhci_configure_endpoints - */ -int xhci_check_maxpacket(struct usb_device *udev) -{ - struct xhci_ctrl *ctrl = udev->controller; - unsigned int slot_id = udev->slot_id; - int ep_index = 0; /* control endpoint */ - struct xhci_container_ctx *in_ctx; - struct xhci_container_ctx *out_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_ep_ctx *ep_ctx; - int max_packet_size; - int hw_max_packet_size; - int ret = 0; - struct usb_interface *ifdesc; - - ifdesc = &udev->config.if_desc[0]; - - out_ctx = ctrl->devs[slot_id]->out_ctx; - xhci_inval_cache((uint32_t)out_ctx->bytes, out_ctx->size); - - ep_ctx = xhci_get_ep_ctx(ctrl, out_ctx, ep_index); - hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); - max_packet_size = usb_endpoint_maxp(&ifdesc->ep_desc[0]); - if (hw_max_packet_size != max_packet_size) { - debug("Max Packet Size for ep 0 changed.\n"); - debug("Max packet size in usb_device = %d\n", max_packet_size); - debug("Max packet size in xHCI HW = %d\n", hw_max_packet_size); - debug("Issuing evaluate context command.\n"); - - /* Set up the modified control endpoint 0 */ - xhci_endpoint_copy(ctrl, ctrl->devs[slot_id]->in_ctx, - ctrl->devs[slot_id]->out_ctx, ep_index); - in_ctx = ctrl->devs[slot_id]->in_ctx; - ep_ctx = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); - ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK); - ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size)); - - /* - * Set up the input context flags for the command - * FIXME: This won't work if a non-default control endpoint - * changes max packet sizes. - */ - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); - ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG); - ctrl_ctx->drop_flags = 0; - - ret = xhci_configure_endpoints(udev, true); - } - return ret; -} - -/** - * Clears the Change bits of the Port Status Register - * - * @param wValue request value - * @param wIndex request index - * @param addr address of posrt status register - * @param port_status state of port status register - * @return none - */ -static void xhci_clear_port_change_bit(u16 wValue, - u16 wIndex, volatile uint32_t *addr, u32 port_status) -{ - char *port_change_bit; - u32 status; - - switch (wValue) { - case USB_PORT_FEAT_C_RESET: - status = PORT_RC; - port_change_bit = "reset"; - break; - case USB_PORT_FEAT_C_CONNECTION: - status = PORT_CSC; - port_change_bit = "connect"; - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - status = PORT_OCC; - port_change_bit = "over-current"; - break; - case USB_PORT_FEAT_C_ENABLE: - status = PORT_PEC; - port_change_bit = "enable/disable"; - break; - case USB_PORT_FEAT_C_SUSPEND: - status = PORT_PLC; - port_change_bit = "suspend/resume"; - break; - default: - /* Should never happen */ - return; - } - - /* Change bits are all write 1 to clear */ - xhci_writel(addr, port_status | status); - - port_status = xhci_readl(addr); - debug("clear port %s change, actual port %d status = 0x%x\n", - port_change_bit, wIndex, port_status); -} - -/** - * Save Read Only (RO) bits and save read/write bits where - * writing a 0 clears the bit and writing a 1 sets the bit (RWS). - * For all other types (RW1S, RW1CS, RW, and RZ), writing a '0' has no effect. - * - * @param state state of the Port Status and Control Regsiter - * @return a value that would result in the port being in the - * same state, if the value was written to the port - * status control register. - */ -static u32 xhci_port_state_to_neutral(u32 state) -{ - /* Save read-only status and port state */ - return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS); -} - -/** - * Submits the Requests to the XHCI Host Controller - * - * @param udev pointer to the USB device structure - * @param pipe contains the DIR_IN or OUT , devnum - * @param buffer buffer to be read/written based on the request - * @return returns 0 if successful else -1 on failure - */ -static int xhci_submit_root(struct usb_device *udev, unsigned long pipe, - void *buffer, struct devrequest *req) -{ - uint8_t tmpbuf[4]; - u16 typeReq; - void *srcptr = NULL; - int len, srclen; - uint32_t reg; - volatile uint32_t *status_reg; - struct xhci_ctrl *ctrl = udev->controller; - struct xhci_hcor *hcor = ctrl->hcor; - - if (((req->requesttype & USB_RT_PORT) && - le16_to_cpu(req->index)) > CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS) { - printf("The request port(%d) is not configured\n", - le16_to_cpu(req->index) - 1); - return -EINVAL; - } - - status_reg = (volatile uint32_t *) - (&hcor->portregs[le16_to_cpu(req->index) - 1].or_portsc); - srclen = 0; - - typeReq = req->request | req->requesttype << 8; - - switch (typeReq) { - case DeviceRequest | USB_REQ_GET_DESCRIPTOR: - switch (le16_to_cpu(req->value) >> 8) { - case USB_DT_DEVICE: - debug("USB_DT_DEVICE request\n"); - srcptr = &descriptor.device; - srclen = 0x12; - break; - case USB_DT_CONFIG: - debug("USB_DT_CONFIG config\n"); - srcptr = &descriptor.config; - srclen = 0x19; - break; - case USB_DT_STRING: - debug("USB_DT_STRING config\n"); - switch (le16_to_cpu(req->value) & 0xff) { - case 0: /* Language */ - srcptr = "\4\3\11\4"; - srclen = 4; - break; - case 1: /* Vendor String */ - srcptr = "\16\3u\0-\0b\0o\0o\0t\0"; - srclen = 14; - break; - case 2: /* Product Name */ - srcptr = "\52\3X\0H\0C\0I\0 " - "\0H\0o\0s\0t\0 " - "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0"; - srclen = 42; - break; - default: - printf("unknown value DT_STRING %x\n", - le16_to_cpu(req->value)); - goto unknown; - } - break; - default: - printf("unknown value %x\n", le16_to_cpu(req->value)); - goto unknown; - } - break; - case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8): - switch (le16_to_cpu(req->value) >> 8) { - case USB_DT_HUB: - debug("USB_DT_HUB config\n"); - srcptr = &descriptor.hub; - srclen = 0x8; - break; - default: - printf("unknown value %x\n", le16_to_cpu(req->value)); - goto unknown; - } - break; - case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8): - debug("USB_REQ_SET_ADDRESS\n"); - ctrl->rootdev = le16_to_cpu(req->value); - break; - case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: - /* Do nothing */ - break; - case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8): - tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */ - tmpbuf[1] = 0; - srcptr = tmpbuf; - srclen = 2; - break; - case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): - memset(tmpbuf, 0, 4); - reg = xhci_readl(status_reg); - if (reg & PORT_CONNECT) { - tmpbuf[0] |= USB_PORT_STAT_CONNECTION; - switch (reg & DEV_SPEED_MASK) { - case XDEV_FS: - debug("SPEED = FULLSPEED\n"); - break; - case XDEV_LS: - debug("SPEED = LOWSPEED\n"); - tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; - break; - case XDEV_HS: - debug("SPEED = HIGHSPEED\n"); - tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; - break; - case XDEV_SS: - debug("SPEED = SUPERSPEED\n"); - tmpbuf[1] |= USB_PORT_STAT_SUPER_SPEED >> 8; - break; - } - } - if (reg & PORT_PE) - tmpbuf[0] |= USB_PORT_STAT_ENABLE; - if ((reg & PORT_PLS_MASK) == XDEV_U3) - tmpbuf[0] |= USB_PORT_STAT_SUSPEND; - if (reg & PORT_OC) - tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT; - if (reg & PORT_RESET) - tmpbuf[0] |= USB_PORT_STAT_RESET; - if (reg & PORT_POWER) - /* - * XXX: This Port power bit (for USB 3.0 hub) - * we are faking in USB 2.0 hub port status; - * since there's a change in bit positions in - * two: - * USB 2.0 port status PP is at position[8] - * USB 3.0 port status PP is at position[9] - * So, we are still keeping it at position [8] - */ - tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; - if (reg & PORT_CSC) - tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; - if (reg & PORT_PEC) - tmpbuf[2] |= USB_PORT_STAT_C_ENABLE; - if (reg & PORT_OCC) - tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT; - if (reg & PORT_RC) - tmpbuf[2] |= USB_PORT_STAT_C_RESET; - - srcptr = tmpbuf; - srclen = 4; - break; - case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - reg = xhci_readl(status_reg); - reg = xhci_port_state_to_neutral(reg); - switch (le16_to_cpu(req->value)) { - case USB_PORT_FEAT_ENABLE: - reg |= PORT_PE; - xhci_writel(status_reg, reg); - break; - case USB_PORT_FEAT_POWER: - reg |= PORT_POWER; - xhci_writel(status_reg, reg); - break; - case USB_PORT_FEAT_RESET: - reg |= PORT_RESET; - xhci_writel(status_reg, reg); - break; - default: - printf("unknown feature %x\n", le16_to_cpu(req->value)); - goto unknown; - } - break; - case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - reg = xhci_readl(status_reg); - reg = xhci_port_state_to_neutral(reg); - switch (le16_to_cpu(req->value)) { - case USB_PORT_FEAT_ENABLE: - reg &= ~PORT_PE; - break; - case USB_PORT_FEAT_POWER: - reg &= ~PORT_POWER; - break; - case USB_PORT_FEAT_C_RESET: - case USB_PORT_FEAT_C_CONNECTION: - case USB_PORT_FEAT_C_OVER_CURRENT: - case USB_PORT_FEAT_C_ENABLE: - xhci_clear_port_change_bit((le16_to_cpu(req->value)), - le16_to_cpu(req->index), - status_reg, reg); - break; - default: - printf("unknown feature %x\n", le16_to_cpu(req->value)); - goto unknown; - } - xhci_writel(status_reg, reg); - break; - default: - puts("Unknown request\n"); - goto unknown; - } - - debug("scrlen = %d\n req->length = %d\n", - srclen, le16_to_cpu(req->length)); - - len = min(srclen, le16_to_cpu(req->length)); - - if (srcptr != NULL && len > 0) - memcpy(buffer, srcptr, len); - else - debug("Len is 0\n"); - - udev->act_len = len; - udev->status = 0; - - return 0; - -unknown: - udev->act_len = 0; - udev->status = USB_ST_STALLED; - - return -ENODEV; -} - -/** - * Submits the INT request to XHCI Host cotroller - * - * @param udev pointer to the USB device - * @param pipe contains the DIR_IN or OUT , devnum - * @param buffer buffer to be read/written based on the request - * @param length length of the buffer - * @param interval interval of the interrupt - * @return 0 - */ -int -submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer, - int length, int interval) -{ - /* - * TODO: Not addressing any interrupt type transfer requests - * Add support for it later. - */ - return -EINVAL; -} - -/** - * submit the BULK type of request to the USB Device - * - * @param udev pointer to the USB device - * @param pipe contains the DIR_IN or OUT , devnum - * @param buffer buffer to be read/written based on the request - * @param length length of the buffer - * @return returns 0 if successful else -1 on failure - */ -int -submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer, - int length) -{ - if (usb_pipetype(pipe) != PIPE_BULK) { - printf("non-bulk pipe (type=%lu)", usb_pipetype(pipe)); - return -EINVAL; - } - - return xhci_bulk_tx(udev, pipe, length, buffer); -} - -/** - * submit the control type of request to the Root hub/Device based on the devnum - * - * @param udev pointer to the USB device - * @param pipe contains the DIR_IN or OUT , devnum - * @param buffer buffer to be read/written based on the request - * @param length length of the buffer - * @param setup Request type - * @return returns 0 if successful else -1 on failure - */ -int -submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer, - int length, struct devrequest *setup) -{ - struct xhci_ctrl *ctrl = udev->controller; - int ret = 0; - - if (usb_pipetype(pipe) != PIPE_CONTROL) { - printf("non-control pipe (type=%lu)", usb_pipetype(pipe)); - return -EINVAL; - } - - if (usb_pipedevice(pipe) == ctrl->rootdev) - return xhci_submit_root(udev, pipe, buffer, setup); - - if (setup->request == USB_REQ_SET_ADDRESS) - return xhci_address_device(udev); - - if (setup->request == USB_REQ_SET_CONFIGURATION) { - ret = xhci_set_configuration(udev); - if (ret) { - puts("Failed to configure xHCI endpoint\n"); - return ret; - } - } - - return xhci_ctrl_tx(udev, pipe, setup, length, buffer); -} - -/** - * Intialises the XHCI host controller - * and allocates the necessary data structures - * - * @param index index to the host controller data structure - * @return pointer to the intialised controller - */ -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - uint32_t val; - uint32_t val2; - uint32_t reg; - struct xhci_hccr *hccr; - struct xhci_hcor *hcor; - struct xhci_ctrl *ctrl; - - if (xhci_hcd_init(index, &hccr, (struct xhci_hcor **)&hcor) != 0) - return -ENODEV; - - if (xhci_reset(hcor) != 0) - return -ENODEV; - - ctrl = &xhcic[index]; - - ctrl->hccr = hccr; - ctrl->hcor = hcor; - - /* - * Program the Number of Device Slots Enabled field in the CONFIG - * register with the max value of slots the HC can handle. - */ - val = (xhci_readl(&hccr->cr_hcsparams1) & HCS_SLOTS_MASK); - val2 = xhci_readl(&hcor->or_config); - val |= (val2 & ~HCS_SLOTS_MASK); - xhci_writel(&hcor->or_config, val); - - /* initializing xhci data structures */ - if (xhci_mem_init(ctrl, hccr, hcor) < 0) - return -ENOMEM; - - reg = xhci_readl(&hccr->cr_hcsparams1); - descriptor.hub.bNbrPorts = ((reg & HCS_MAX_PORTS_MASK) >> - HCS_MAX_PORTS_SHIFT); - printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); - - /* Port Indicators */ - reg = xhci_readl(&hccr->cr_hccparams); - if (HCS_INDICATOR(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x80, &descriptor.hub.wHubCharacteristics); - - /* Port Power Control */ - if (HCC_PPC(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x01, &descriptor.hub.wHubCharacteristics); - - if (xhci_start(hcor)) { - xhci_reset(hcor); - return -ENODEV; - } - - /* Zero'ing IRQ control register and IRQ pending register */ - xhci_writel(&ctrl->ir_set->irq_control, 0x0); - xhci_writel(&ctrl->ir_set->irq_pending, 0x0); - - reg = HC_VERSION(xhci_readl(&hccr->cr_capbase)); - printf("USB XHCI %x.%02x\n", reg >> 8, reg & 0xff); - - *controller = &xhcic[index]; - - return 0; -} - -/** - * Stops the XHCI host controller - * and cleans up all the related data structures - * - * @param index index to the host controller data structure - * @return none - */ -int usb_lowlevel_stop(int index) -{ - struct xhci_ctrl *ctrl = (xhcic + index); - u32 temp; - - xhci_reset(ctrl->hcor); - - debug("// Disabling event ring interrupts\n"); - temp = xhci_readl(&ctrl->hcor->or_usbsts); - xhci_writel(&ctrl->hcor->or_usbsts, temp & ~STS_EINT); - temp = xhci_readl(&ctrl->ir_set->irq_pending); - xhci_writel(&ctrl->ir_set->irq_pending, ER_IRQ_DISABLE(temp)); - - xhci_hcd_stop(index); - - xhci_cleanup(ctrl); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci.h b/qemu/roms/u-boot/drivers/usb/host/xhci.h deleted file mode 100644 index ceb1573d8..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci.h +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * USB HOST XHCI Controller - * - * Based on xHCI host controller driver in linux-kernel - * by Sarah Sharp. - * - * Copyright (C) 2008 Intel Corp. - * Author: Sarah Sharp - * - * Copyright (C) 2013 Samsung Electronics Co.Ltd - * Authors: Vivek Gautam <gautam.vivek@samsung.com> - * Vikas Sajjan <vikas.sajjan@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef HOST_XHCI_H_ -#define HOST_XHCI_H_ - -#include <asm/cache.h> -#include <asm/io.h> -#include <linux/list.h> - -#define upper_32_bits(n) (u32)((n) >> 32) -#define lower_32_bits(n) (u32)(n) - -#define MAX_EP_CTX_NUM 31 -#define XHCI_ALIGNMENT 64 -/* Generic timeout for XHCI events */ -#define XHCI_TIMEOUT 5000 -/* Max number of USB devices for any host controller - limit in section 6.1 */ -#define MAX_HC_SLOTS 256 -/* Section 5.3.3 - MaxPorts */ -#define MAX_HC_PORTS 127 - -/* Up to 16 ms to halt an HC */ -#define XHCI_MAX_HALT_USEC (16*1000) - -#define XHCI_MAX_RESET_USEC (250*1000) - -/* - * These bits are Read Only (RO) and should be saved and written to the - * registers: 0, 3, 10:13, 30 - * connect status, over-current status, port speed, and device removable. - * connect status and port speed are also sticky - meaning they're in - * the AUX well and they aren't changed by a hot, warm, or cold reset. - */ -#define XHCI_PORT_RO ((1 << 0) | (1 << 3) | (0xf << 10) | (1 << 30)) -/* - * These bits are RW; writing a 0 clears the bit, writing a 1 sets the bit: - * bits 5:8, 9, 14:15, 25:27 - * link state, port power, port indicator state, "wake on" enable state - */ -#define XHCI_PORT_RWS ((0xf << 5) | (1 << 9) | (0x3 << 14) | (0x7 << 25)) -/* - * These bits are RW; writing a 1 sets the bit, writing a 0 has no effect: - * bit 4 (port reset) - */ -#define XHCI_PORT_RW1S ((1 << 4)) -/* - * These bits are RW; writing a 1 clears the bit, writing a 0 has no effect: - * bits 1, 17, 18, 19, 20, 21, 22, 23 - * port enable/disable, and - * change bits: connect, PED, - * warm port reset changed (reserved zero for USB 2.0 ports), - * over-current, reset, link state, and L1 change - */ -#define XHCI_PORT_RW1CS ((1 << 1) | (0x7f << 17)) -/* - * Bit 16 is RW, and writing a '1' to it causes the link state control to be - * latched in - */ -#define XHCI_PORT_RW ((1 << 16)) -/* - * These bits are Reserved Zero (RsvdZ) and zero should be written to them: - * bits 2, 24, 28:31 - */ -#define XHCI_PORT_RZ ((1 << 2) | (1 << 24) | (0xf << 28)) - -/* - * XHCI Register Space. - */ -struct xhci_hccr { - uint32_t cr_capbase; - uint32_t cr_hcsparams1; - uint32_t cr_hcsparams2; - uint32_t cr_hcsparams3; - uint32_t cr_hccparams; - uint32_t cr_dboff; - uint32_t cr_rtsoff; - -/* hc_capbase bitmasks */ -/* bits 7:0 - how long is the Capabilities register */ -#define HC_LENGTH(p) XHCI_HC_LENGTH(p) -/* bits 31:16 */ -#define HC_VERSION(p) (((p) >> 16) & 0xffff) - -/* HCSPARAMS1 - hcs_params1 - bitmasks */ -/* bits 0:7, Max Device Slots */ -#define HCS_MAX_SLOTS(p) (((p) >> 0) & 0xff) -#define HCS_SLOTS_MASK 0xff -/* bits 8:18, Max Interrupters */ -#define HCS_MAX_INTRS(p) (((p) >> 8) & 0x7ff) -/* bits 24:31, Max Ports - max value is 0x7F = 127 ports */ -#define HCS_MAX_PORTS_SHIFT 24 -#define HCS_MAX_PORTS_MASK (0x7f << HCS_MAX_PORTS_SHIFT) -#define HCS_MAX_PORTS(p) (((p) >> 24) & 0x7f) - -/* HCSPARAMS2 - hcs_params2 - bitmasks */ -/* bits 0:3, frames or uframes that SW needs to queue transactions - * ahead of the HW to meet periodic deadlines */ -#define HCS_IST(p) (((p) >> 0) & 0xf) -/* bits 4:7, max number of Event Ring segments */ -#define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) -/* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ -/* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */ -#define HCS_MAX_SCRATCHPAD(p) (((p) >> 27) & 0x1f) - -/* HCSPARAMS3 - hcs_params3 - bitmasks */ -/* bits 0:7, Max U1 to U0 latency for the roothub ports */ -#define HCS_U1_LATENCY(p) (((p) >> 0) & 0xff) -/* bits 16:31, Max U2 to U0 latency for the roothub ports */ -#define HCS_U2_LATENCY(p) (((p) >> 16) & 0xffff) - -/* HCCPARAMS - hcc_params - bitmasks */ -/* true: HC can use 64-bit address pointers */ -#define HCC_64BIT_ADDR(p) ((p) & (1 << 0)) -/* true: HC can do bandwidth negotiation */ -#define HCC_BANDWIDTH_NEG(p) ((p) & (1 << 1)) -/* true: HC uses 64-byte Device Context structures - * FIXME 64-byte context structures aren't supported yet. - */ -#define HCC_64BYTE_CONTEXT(p) ((p) & (1 << 2)) -/* true: HC has port power switches */ -#define HCC_PPC(p) ((p) & (1 << 3)) -/* true: HC has port indicators */ -#define HCS_INDICATOR(p) ((p) & (1 << 4)) -/* true: HC has Light HC Reset Capability */ -#define HCC_LIGHT_RESET(p) ((p) & (1 << 5)) -/* true: HC supports latency tolerance messaging */ -#define HCC_LTC(p) ((p) & (1 << 6)) -/* true: no secondary Stream ID Support */ -#define HCC_NSS(p) ((p) & (1 << 7)) -/* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15 */ -#define HCC_MAX_PSA(p) (1 << ((((p) >> 12) & 0xf) + 1)) -/* Extended Capabilities pointer from PCI base - section 5.3.6 */ -#define HCC_EXT_CAPS(p) XHCI_HCC_EXT_CAPS(p) - -/* db_off bitmask - bits 0:1 reserved */ -#define DBOFF_MASK (~0x3) - -/* run_regs_off bitmask - bits 0:4 reserved */ -#define RTSOFF_MASK (~0x1f) - -}; - -struct xhci_hcor_port_regs { - volatile uint32_t or_portsc; - volatile uint32_t or_portpmsc; - volatile uint32_t or_portli; - volatile uint32_t reserved_3; -}; - -struct xhci_hcor { - volatile uint32_t or_usbcmd; - volatile uint32_t or_usbsts; - volatile uint32_t or_pagesize; - volatile uint32_t reserved_0[2]; - volatile uint32_t or_dnctrl; - volatile uint64_t or_crcr; - volatile uint32_t reserved_1[4]; - volatile uint64_t or_dcbaap; - volatile uint32_t or_config; - volatile uint32_t reserved_2[241]; - struct xhci_hcor_port_regs portregs[CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS]; - - uint32_t reserved_4[CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS * 254]; -}; - -/* USBCMD - USB command - command bitmasks */ -/* start/stop HC execution - do not write unless HC is halted*/ -#define CMD_RUN XHCI_CMD_RUN -/* Reset HC - resets internal HC state machine and all registers (except - * PCI config regs). HC does NOT drive a USB reset on the downstream ports. - * The xHCI driver must reinitialize the xHC after setting this bit. - */ -#define CMD_RESET (1 << 1) -/* Event Interrupt Enable - a '1' allows interrupts from the host controller */ -#define CMD_EIE XHCI_CMD_EIE -/* Host System Error Interrupt Enable - get out-of-band signal for HC errors */ -#define CMD_HSEIE XHCI_CMD_HSEIE -/* bits 4:6 are reserved (and should be preserved on writes). */ -/* light reset (port status stays unchanged) - reset completed when this is 0 */ -#define CMD_LRESET (1 << 7) -/* host controller save/restore state. */ -#define CMD_CSS (1 << 8) -#define CMD_CRS (1 << 9) -/* Enable Wrap Event - '1' means xHC generates an event when MFINDEX wraps. */ -#define CMD_EWE XHCI_CMD_EWE -/* MFINDEX power management - '1' means xHC can stop MFINDEX counter if all root - * hubs are in U3 (selective suspend), disconnect, disabled, or powered-off. - * '0' means the xHC can power it off if all ports are in the disconnect, - * disabled, or powered-off state. - */ -#define CMD_PM_INDEX (1 << 11) -/* bits 12:31 are reserved (and should be preserved on writes). */ - -/* USBSTS - USB status - status bitmasks */ -/* HC not running - set to 1 when run/stop bit is cleared. */ -#define STS_HALT XHCI_STS_HALT -/* serious error, e.g. PCI parity error. The HC will clear the run/stop bit. */ -#define STS_FATAL (1 << 2) -/* event interrupt - clear this prior to clearing any IP flags in IR set*/ -#define STS_EINT (1 << 3) -/* port change detect */ -#define STS_PORT (1 << 4) -/* bits 5:7 reserved and zeroed */ -/* save state status - '1' means xHC is saving state */ -#define STS_SAVE (1 << 8) -/* restore state status - '1' means xHC is restoring state */ -#define STS_RESTORE (1 << 9) -/* true: save or restore error */ -#define STS_SRE (1 << 10) -/* true: Controller Not Ready to accept doorbell or op reg writes after reset */ -#define STS_CNR XHCI_STS_CNR -/* true: internal Host Controller Error - SW needs to reset and reinitialize */ -#define STS_HCE (1 << 12) -/* bits 13:31 reserved and should be preserved */ - -/* - * DNCTRL - Device Notification Control Register - dev_notification bitmasks - * Generate a device notification event when the HC sees a transaction with a - * notification type that matches a bit set in this bit field. - */ -#define DEV_NOTE_MASK (0xffff) -#define ENABLE_DEV_NOTE(x) (1 << (x)) -/* Most of the device notification types should only be used for debug. - * SW does need to pay attention to function wake notifications. - */ -#define DEV_NOTE_FWAKE ENABLE_DEV_NOTE(1) - -/* CRCR - Command Ring Control Register - cmd_ring bitmasks */ -/* bit 0 is the command ring cycle state */ -/* stop ring operation after completion of the currently executing command */ -#define CMD_RING_PAUSE (1 << 1) -/* stop ring immediately - abort the currently executing command */ -#define CMD_RING_ABORT (1 << 2) -/* true: command ring is running */ -#define CMD_RING_RUNNING (1 << 3) -/* bits 4:5 reserved and should be preserved */ -/* Command Ring pointer - bit mask for the lower 32 bits. */ -#define CMD_RING_RSVD_BITS (0x3f) - -/* CONFIG - Configure Register - config_reg bitmasks */ -/* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */ -#define MAX_DEVS(p) ((p) & 0xff) -/* bits 8:31 - reserved and should be preserved */ - -/* PORTSC - Port Status and Control Register - port_status_base bitmasks */ -/* true: device connected */ -#define PORT_CONNECT (1 << 0) -/* true: port enabled */ -#define PORT_PE (1 << 1) -/* bit 2 reserved and zeroed */ -/* true: port has an over-current condition */ -#define PORT_OC (1 << 3) -/* true: port reset signaling asserted */ -#define PORT_RESET (1 << 4) -/* Port Link State - bits 5:8 - * A read gives the current link PM state of the port, - * a write with Link State Write Strobe set sets the link state. - */ -#define PORT_PLS_MASK (0xf << 5) -#define XDEV_U0 (0x0 << 5) -#define XDEV_U2 (0x2 << 5) -#define XDEV_U3 (0x3 << 5) -#define XDEV_RESUME (0xf << 5) -/* true: port has power (see HCC_PPC) */ -#define PORT_POWER (1 << 9) -/* bits 10:13 indicate device speed: - * 0 - undefined speed - port hasn't be initialized by a reset yet - * 1 - full speed - * 2 - low speed - * 3 - high speed - * 4 - super speed - * 5-15 reserved - */ -#define DEV_SPEED_MASK (0xf << 10) -#define XDEV_FS (0x1 << 10) -#define XDEV_LS (0x2 << 10) -#define XDEV_HS (0x3 << 10) -#define XDEV_SS (0x4 << 10) -#define DEV_UNDEFSPEED(p) (((p) & DEV_SPEED_MASK) == (0x0<<10)) -#define DEV_FULLSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_FS) -#define DEV_LOWSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_LS) -#define DEV_HIGHSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_HS) -#define DEV_SUPERSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_SS) -/* Bits 20:23 in the Slot Context are the speed for the device */ -#define SLOT_SPEED_FS (XDEV_FS << 10) -#define SLOT_SPEED_LS (XDEV_LS << 10) -#define SLOT_SPEED_HS (XDEV_HS << 10) -#define SLOT_SPEED_SS (XDEV_SS << 10) -/* Port Indicator Control */ -#define PORT_LED_OFF (0 << 14) -#define PORT_LED_AMBER (1 << 14) -#define PORT_LED_GREEN (2 << 14) -#define PORT_LED_MASK (3 << 14) -/* Port Link State Write Strobe - set this when changing link state */ -#define PORT_LINK_STROBE (1 << 16) -/* true: connect status change */ -#define PORT_CSC (1 << 17) -/* true: port enable change */ -#define PORT_PEC (1 << 18) -/* true: warm reset for a USB 3.0 device is done. A "hot" reset puts the port - * into an enabled state, and the device into the default state. A "warm" reset - * also resets the link, forcing the device through the link training sequence. - * SW can also look at the Port Reset register to see when warm reset is done. - */ -#define PORT_WRC (1 << 19) -/* true: over-current change */ -#define PORT_OCC (1 << 20) -/* true: reset change - 1 to 0 transition of PORT_RESET */ -#define PORT_RC (1 << 21) -/* port link status change - set on some port link state transitions: - * Transition Reason - * -------------------------------------------------------------------------- - * - U3 to Resume Wakeup signaling from a device - * - Resume to Recovery to U0 USB 3.0 device resume - * - Resume to U0 USB 2.0 device resume - * - U3 to Recovery to U0 Software resume of USB 3.0 device complete - * - U3 to U0 Software resume of USB 2.0 device complete - * - U2 to U0 L1 resume of USB 2.1 device complete - * - U0 to U0 (???) L1 entry rejection by USB 2.1 device - * - U0 to disabled L1 entry error with USB 2.1 device - * - Any state to inactive Error on USB 3.0 port - */ -#define PORT_PLC (1 << 22) -/* port configure error change - port failed to configure its link partner */ -#define PORT_CEC (1 << 23) -/* bit 24 reserved */ -/* wake on connect (enable) */ -#define PORT_WKCONN_E (1 << 25) -/* wake on disconnect (enable) */ -#define PORT_WKDISC_E (1 << 26) -/* wake on over-current (enable) */ -#define PORT_WKOC_E (1 << 27) -/* bits 28:29 reserved */ -/* true: device is removable - for USB 3.0 roothub emulation */ -#define PORT_DEV_REMOVE (1 << 30) -/* Initiate a warm port reset - complete when PORT_WRC is '1' */ -#define PORT_WR (1 << 31) - -/* We mark duplicate entries with -1 */ -#define DUPLICATE_ENTRY ((u8)(-1)) - -/* Port Power Management Status and Control - port_power_base bitmasks */ -/* Inactivity timer value for transitions into U1, in microseconds. - * Timeout can be up to 127us. 0xFF means an infinite timeout. - */ -#define PORT_U1_TIMEOUT(p) ((p) & 0xff) -/* Inactivity timer value for transitions into U2 */ -#define PORT_U2_TIMEOUT(p) (((p) & 0xff) << 8) -/* Bits 24:31 for port testing */ - -/* USB2 Protocol PORTSPMSC */ -#define PORT_L1S_MASK 7 -#define PORT_L1S_SUCCESS 1 -#define PORT_RWE (1 << 3) -#define PORT_HIRD(p) (((p) & 0xf) << 4) -#define PORT_HIRD_MASK (0xf << 4) -#define PORT_L1DS(p) (((p) & 0xff) << 8) -#define PORT_HLE (1 << 16) - -/** -* struct xhci_intr_reg - Interrupt Register Set -* @irq_pending: IMAN - Interrupt Management Register. Used to enable -* interrupts and check for pending interrupts. -* @irq_control: IMOD - Interrupt Moderation Register. -* Used to throttle interrupts. -* @erst_size: Number of segments in the - Event Ring Segment Table (ERST). -* @erst_base: ERST base address. -* @erst_dequeue: Event ring dequeue pointer. -* -* Each interrupter (defined by a MSI-X vector) has an event ring and an Event -* Ring Segment Table (ERST) associated with it. -* The event ring is comprised of multiple segments of the same size. -* The HC places events on the ring and "updates the Cycle bit in the TRBs to -* indicate to software the current position of the Enqueue Pointer." -* The HCD (Linux) processes those events and updates the dequeue pointer. -*/ -struct xhci_intr_reg { - volatile __le32 irq_pending; - volatile __le32 irq_control; - volatile __le32 erst_size; - volatile __le32 rsvd; - volatile __le64 erst_base; - volatile __le64 erst_dequeue; -}; - -/* irq_pending bitmasks */ -#define ER_IRQ_PENDING(p) ((p) & 0x1) -/* bits 2:31 need to be preserved */ -/* THIS IS BUGGY - FIXME - IP IS WRITE 1 TO CLEAR */ -#define ER_IRQ_CLEAR(p) ((p) & 0xfffffffe) -#define ER_IRQ_ENABLE(p) ((ER_IRQ_CLEAR(p)) | 0x2) -#define ER_IRQ_DISABLE(p) ((ER_IRQ_CLEAR(p)) & ~(0x2)) - -/* irq_control bitmasks */ -/* Minimum interval between interrupts (in 250ns intervals). The interval - * between interrupts will be longer if there are no events on the event ring. - * Default is 4000 (1 ms). - */ -#define ER_IRQ_INTERVAL_MASK (0xffff) -/* Counter used to count down the time to the next interrupt - HW use only */ -#define ER_IRQ_COUNTER_MASK (0xffff << 16) - -/* erst_size bitmasks */ -/* Preserve bits 16:31 of erst_size */ -#define ERST_SIZE_MASK (0xffff << 16) - -/* erst_dequeue bitmasks */ -/* Dequeue ERST Segment Index (DESI) - Segment number (or alias) - * where the current dequeue pointer lies. This is an optional HW hint. - */ -#define ERST_DESI_MASK (0x7) -/* Event Handler Busy (EHB) - is the event ring scheduled to be serviced by - * a work queue (or delayed service routine)? - */ -#define ERST_EHB (1 << 3) -#define ERST_PTR_MASK (0xf) - -/** - * struct xhci_run_regs - * @microframe_index: MFINDEX - current microframe number - * - * Section 5.5 Host Controller Runtime Registers: - * "Software should read and write these registers using only Dword (32 bit) - * or larger accesses" - */ -struct xhci_run_regs { - __le32 microframe_index; - __le32 rsvd[7]; - struct xhci_intr_reg ir_set[128]; -}; - -/** - * struct doorbell_array - * - * Bits 0 - 7: Endpoint target - * Bits 8 - 15: RsvdZ - * Bits 16 - 31: Stream ID - * - * Section 5.6 - */ -struct xhci_doorbell_array { - volatile __le32 doorbell[256]; -}; - -#define DB_VALUE(ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16)) -#define DB_VALUE_HOST 0x00000000 - -/** - * struct xhci_protocol_caps - * @revision: major revision, minor revision, capability ID, - * and next capability pointer. - * @name_string: Four ASCII characters to say which spec this xHC - * follows, typically "USB ". - * @port_info: Port offset, count, and protocol-defined information. - */ -struct xhci_protocol_caps { - u32 revision; - u32 name_string; - u32 port_info; -}; - -#define XHCI_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff) -#define XHCI_EXT_PORT_OFF(x) ((x) & 0xff) -#define XHCI_EXT_PORT_COUNT(x) (((x) >> 8) & 0xff) - -/** - * struct xhci_container_ctx - * @type: Type of context. Used to calculated offsets to contained contexts. - * @size: Size of the context data - * @bytes: The raw context data given to HW - * @dma: dma address of the bytes - * - * Represents either a Device or Input context. Holds a pointer to the raw - * memory used for the context (bytes) and dma address of it (dma). - */ -struct xhci_container_ctx { - unsigned type; -#define XHCI_CTX_TYPE_DEVICE 0x1 -#define XHCI_CTX_TYPE_INPUT 0x2 - - int size; - u8 *bytes; -}; - -/** - * struct xhci_slot_ctx - * @dev_info: Route string, device speed, hub info, and last valid endpoint - * @dev_info2: Max exit latency for device number, root hub port number - * @tt_info: tt_info is used to construct split transaction tokens - * @dev_state: slot state and device address - * - * Slot Context - section 6.2.1.1. This assumes the HC uses 32-byte context - * structures. If the HC uses 64-byte contexts, there is an additional 32 bytes - * reserved at the end of the slot context for HC internal use. - */ -struct xhci_slot_ctx { - __le32 dev_info; - __le32 dev_info2; - __le32 tt_info; - __le32 dev_state; - /* offset 0x10 to 0x1f reserved for HC internal use */ - __le32 reserved[4]; -}; - -/* dev_info bitmasks */ -/* Route String - 0:19 */ -#define ROUTE_STRING_MASK (0xfffff) -/* Device speed - values defined by PORTSC Device Speed field - 20:23 */ -#define DEV_SPEED (0xf << 20) -/* bit 24 reserved */ -/* Is this LS/FS device connected through a HS hub? - bit 25 */ -#define DEV_MTT (0x1 << 25) -/* Set if the device is a hub - bit 26 */ -#define DEV_HUB (0x1 << 26) -/* Index of the last valid endpoint context in this device context - 27:31 */ -#define LAST_CTX_MASK (0x1f << 27) -#define LAST_CTX(p) ((p) << 27) -#define LAST_CTX_TO_EP_NUM(p) (((p) >> 27) - 1) -#define SLOT_FLAG (1 << 0) -#define EP0_FLAG (1 << 1) - -/* dev_info2 bitmasks */ -/* Max Exit Latency (ms) - worst case time to wake up all links in dev path */ -#define MAX_EXIT (0xffff) -/* Root hub port number that is needed to access the USB device */ -#define ROOT_HUB_PORT(p) (((p) & 0xff) << 16) -#define ROOT_HUB_PORT_MASK (0xff) -#define ROOT_HUB_PORT_SHIFT (16) -#define DEVINFO_TO_ROOT_HUB_PORT(p) (((p) >> 16) & 0xff) -/* Maximum number of ports under a hub device */ -#define XHCI_MAX_PORTS(p) (((p) & 0xff) << 24) - -/* tt_info bitmasks */ -/* - * TT Hub Slot ID - for low or full speed devices attached to a high-speed hub - * The Slot ID of the hub that isolates the high speed signaling from - * this low or full-speed device. '0' if attached to root hub port. - */ -#define TT_SLOT (0xff) -/* - * The number of the downstream facing port of the high-speed hub - * '0' if the device is not low or full speed. - */ -#define TT_PORT (0xff << 8) -#define TT_THINK_TIME(p) (((p) & 0x3) << 16) - -/* dev_state bitmasks */ -/* USB device address - assigned by the HC */ -#define DEV_ADDR_MASK (0xff) -/* bits 8:26 reserved */ -/* Slot state */ -#define SLOT_STATE (0x1f << 27) -#define GET_SLOT_STATE(p) (((p) & (0x1f << 27)) >> 27) - -#define SLOT_STATE_DISABLED 0 -#define SLOT_STATE_ENABLED SLOT_STATE_DISABLED -#define SLOT_STATE_DEFAULT 1 -#define SLOT_STATE_ADDRESSED 2 -#define SLOT_STATE_CONFIGURED 3 - -/** - * struct xhci_ep_ctx - * @ep_info: endpoint state, streams, mult, and interval information. - * @ep_info2: information on endpoint type, max packet size, max burst size, - * error count, and whether the HC will force an event for all - * transactions. - * @deq: 64-bit ring dequeue pointer address. If the endpoint only - * defines one stream, this points to the endpoint transfer ring. - * Otherwise, it points to a stream context array, which has a - * ring pointer for each flow. - * @tx_info: - * Average TRB lengths for the endpoint ring and - * max payload within an Endpoint Service Interval Time (ESIT). - * - * Endpoint Context - section 6.2.1.2.This assumes the HC uses 32-byte context - * structures.If the HC uses 64-byte contexts, there is an additional 32 bytes - * reserved at the end of the endpoint context for HC internal use. - */ -struct xhci_ep_ctx { - __le32 ep_info; - __le32 ep_info2; - __le64 deq; - __le32 tx_info; - /* offset 0x14 - 0x1f reserved for HC internal use */ - __le32 reserved[3]; -}; - -/* ep_info bitmasks */ -/* - * Endpoint State - bits 0:2 - * 0 - disabled - * 1 - running - * 2 - halted due to halt condition - ok to manipulate endpoint ring - * 3 - stopped - * 4 - TRB error - * 5-7 - reserved - */ -#define EP_STATE_MASK (0xf) -#define EP_STATE_DISABLED 0 -#define EP_STATE_RUNNING 1 -#define EP_STATE_HALTED 2 -#define EP_STATE_STOPPED 3 -#define EP_STATE_ERROR 4 -/* Mult - Max number of burtst within an interval, in EP companion desc. */ -#define EP_MULT(p) (((p) & 0x3) << 8) -#define CTX_TO_EP_MULT(p) (((p) >> 8) & 0x3) -/* bits 10:14 are Max Primary Streams */ -/* bit 15 is Linear Stream Array */ -/* Interval - period between requests to an endpoint - 125u increments. */ -#define EP_INTERVAL(p) (((p) & 0xff) << 16) -#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) -#define CTX_TO_EP_INTERVAL(p) (((p) >> 16) & 0xff) -#define EP_MAXPSTREAMS_MASK (0x1f << 10) -#define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK) -/* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */ -#define EP_HAS_LSA (1 << 15) - -/* ep_info2 bitmasks */ -/* - * Force Event - generate transfer events for all TRBs for this endpoint - * This will tell the HC to ignore the IOC and ISP flags (for debugging only). - */ -#define FORCE_EVENT (0x1) -#define ERROR_COUNT(p) (((p) & 0x3) << 1) -#define ERROR_COUNT_SHIFT (1) -#define ERROR_COUNT_MASK (0x3) -#define CTX_TO_EP_TYPE(p) (((p) >> 3) & 0x7) -#define EP_TYPE(p) ((p) << 3) -#define EP_TYPE_SHIFT (3) -#define ISOC_OUT_EP 1 -#define BULK_OUT_EP 2 -#define INT_OUT_EP 3 -#define CTRL_EP 4 -#define ISOC_IN_EP 5 -#define BULK_IN_EP 6 -#define INT_IN_EP 7 -/* bit 6 reserved */ -/* bit 7 is Host Initiate Disable - for disabling stream selection */ -#define MAX_BURST(p) (((p)&0xff) << 8) -#define MAX_BURST_MASK (0xff) -#define MAX_BURST_SHIFT (8) -#define CTX_TO_MAX_BURST(p) (((p) >> 8) & 0xff) -#define MAX_PACKET(p) (((p)&0xffff) << 16) -#define MAX_PACKET_MASK (0xffff) -#define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff) -#define MAX_PACKET_SHIFT (16) - -/* Get max packet size from ep desc. Bit 10..0 specify the max packet size. - * USB2.0 spec 9.6.6. - */ -#define GET_MAX_PACKET(p) ((p) & 0x7ff) - -/* tx_info bitmasks */ -#define AVG_TRB_LENGTH_FOR_EP(p) ((p) & 0xffff) -#define MAX_ESIT_PAYLOAD_FOR_EP(p) (((p) & 0xffff) << 16) -#define CTX_TO_MAX_ESIT_PAYLOAD(p) (((p) >> 16) & 0xffff) - -/* deq bitmasks */ -#define EP_CTX_CYCLE_MASK (1 << 0) - - -/** - * struct xhci_input_control_context - * Input control context; see section 6.2.5. - * - * @drop_context: set the bit of the endpoint context you want to disable - * @add_context: set the bit of the endpoint context you want to enable - */ -struct xhci_input_control_ctx { - volatile __le32 drop_flags; - volatile __le32 add_flags; - __le32 rsvd2[6]; -}; - - -/** - * struct xhci_device_context_array - * @dev_context_ptr array of 64-bit DMA addresses for device contexts - */ -struct xhci_device_context_array { - /* 64-bit device addresses; we only write 32-bit addresses */ - __le64 dev_context_ptrs[MAX_HC_SLOTS]; -}; -/* TODO: write function to set the 64-bit device DMA address */ -/* - * TODO: change this to be dynamically sized at HC mem init time since the HC - * might not be able to handle the maximum number of devices possible. - */ - - -struct xhci_transfer_event { - /* 64-bit buffer address, or immediate data */ - __le64 buffer; - __le32 transfer_len; - /* This field is interpreted differently based on the type of TRB */ - volatile __le32 flags; -}; - -/* Transfer event TRB length bit mask */ -/* bits 0:23 */ -#define EVENT_TRB_LEN(p) ((p) & 0xffffff) - -/** Transfer Event bit fields **/ -#define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f) - -/* Completion Code - only applicable for some types of TRBs */ -#define COMP_CODE_MASK (0xff << 24) -#define COMP_CODE_SHIFT (24) -#define GET_COMP_CODE(p) (((p) & COMP_CODE_MASK) >> 24) - -typedef enum { - COMP_SUCCESS = 1, - /* Data Buffer Error */ - COMP_DB_ERR, /* 2 */ - /* Babble Detected Error */ - COMP_BABBLE, /* 3 */ - /* USB Transaction Error */ - COMP_TX_ERR, /* 4 */ - /* TRB Error - some TRB field is invalid */ - COMP_TRB_ERR, /* 5 */ - /* Stall Error - USB device is stalled */ - COMP_STALL, /* 6 */ - /* Resource Error - HC doesn't have memory for that device configuration */ - COMP_ENOMEM, /* 7 */ - /* Bandwidth Error - not enough room in schedule for this dev config */ - COMP_BW_ERR, /* 8 */ - /* No Slots Available Error - HC ran out of device slots */ - COMP_ENOSLOTS, /* 9 */ - /* Invalid Stream Type Error */ - COMP_STREAM_ERR, /* 10 */ - /* Slot Not Enabled Error - doorbell rung for disabled device slot */ - COMP_EBADSLT, /* 11 */ - /* Endpoint Not Enabled Error */ - COMP_EBADEP,/* 12 */ - /* Short Packet */ - COMP_SHORT_TX, /* 13 */ - /* Ring Underrun - doorbell rung for an empty isoc OUT ep ring */ - COMP_UNDERRUN, /* 14 */ - /* Ring Overrun - isoc IN ep ring is empty when ep is scheduled to RX */ - COMP_OVERRUN, /* 15 */ - /* Virtual Function Event Ring Full Error */ - COMP_VF_FULL, /* 16 */ - /* Parameter Error - Context parameter is invalid */ - COMP_EINVAL, /* 17 */ - /* Bandwidth Overrun Error - isoc ep exceeded its allocated bandwidth */ - COMP_BW_OVER,/* 18 */ - /* Context State Error - illegal context state transition requested */ - COMP_CTX_STATE,/* 19 */ - /* No Ping Response Error - HC didn't get PING_RESPONSE in time to TX */ - COMP_PING_ERR,/* 20 */ - /* Event Ring is full */ - COMP_ER_FULL,/* 21 */ - /* Incompatible Device Error */ - COMP_DEV_ERR,/* 22 */ - /* Missed Service Error - HC couldn't service an isoc ep within interval */ - COMP_MISSED_INT,/* 23 */ - /* Successfully stopped command ring */ - COMP_CMD_STOP, /* 24 */ - /* Successfully aborted current command and stopped command ring */ - COMP_CMD_ABORT, /* 25 */ - /* Stopped - transfer was terminated by a stop endpoint command */ - COMP_STOP,/* 26 */ - /* Same as COMP_EP_STOPPED, but the transferred length in the event - * is invalid */ - COMP_STOP_INVAL, /* 27*/ - /* Control Abort Error - Debug Capability - control pipe aborted */ - COMP_DBG_ABORT, /* 28 */ - /* Max Exit Latency Too Large Error */ - COMP_MEL_ERR,/* 29 */ - /* TRB type 30 reserved */ - /* Isoc Buffer Overrun - an isoc IN ep sent more data than could fit in TD */ - COMP_BUFF_OVER = 31, - /* Event Lost Error - xHC has an "internal event overrun condition" */ - COMP_ISSUES, /* 32 */ - /* Undefined Error - reported when other error codes don't apply */ - COMP_UNKNOWN, /* 33 */ - /* Invalid Stream ID Error */ - COMP_STRID_ERR, /* 34 */ - /* Secondary Bandwidth Error - may be returned by a Configure Endpoint cmd */ - COMP_2ND_BW_ERR, /* 35 */ - /* Split Transaction Error */ - COMP_SPLIT_ERR /* 36 */ - -} xhci_comp_code; - -struct xhci_link_trb { - /* 64-bit segment pointer*/ - volatile __le64 segment_ptr; - volatile __le32 intr_target; - volatile __le32 control; -}; - -/* control bitfields */ -#define LINK_TOGGLE (0x1 << 1) - -/* Command completion event TRB */ -struct xhci_event_cmd { - /* Pointer to command TRB, or the value passed by the event data trb */ - volatile __le64 cmd_trb; - volatile __le32 status; - volatile __le32 flags; -}; - -/* flags bitmasks */ -/* bits 16:23 are the virtual function ID */ -/* bits 24:31 are the slot ID */ -#define TRB_TO_SLOT_ID(p) (((p) & (0xff << 24)) >> 24) -#define TRB_TO_SLOT_ID_SHIFT (24) -#define TRB_TO_SLOT_ID_MASK (0xff << TRB_TO_SLOT_ID_SHIFT) -#define SLOT_ID_FOR_TRB(p) (((p) & 0xff) << 24) -#define SLOT_ID_FOR_TRB_MASK (0xff) -#define SLOT_ID_FOR_TRB_SHIFT (24) - -/* Stop Endpoint TRB - ep_index to endpoint ID for this TRB */ -#define TRB_TO_EP_INDEX(p) ((((p) & (0x1f << 16)) >> 16) - 1) -#define EP_ID_FOR_TRB(p) ((((p) + 1) & 0x1f) << 16) - -#define SUSPEND_PORT_FOR_TRB(p) (((p) & 1) << 23) -#define TRB_TO_SUSPEND_PORT(p) (((p) & (1 << 23)) >> 23) -#define LAST_EP_INDEX 30 - -/* Set TR Dequeue Pointer command TRB fields */ -#define TRB_TO_STREAM_ID(p) ((((p) & (0xffff << 16)) >> 16)) -#define STREAM_ID_FOR_TRB(p) ((((p)) & 0xffff) << 16) - - -/* Port Status Change Event TRB fields */ -/* Port ID - bits 31:24 */ -#define GET_PORT_ID(p) (((p) & (0xff << 24)) >> 24) -#define PORT_ID_SHIFT (24) -#define PORT_ID_MASK (0xff << PORT_ID_SHIFT) - -/* Normal TRB fields */ -/* transfer_len bitmasks - bits 0:16 */ -#define TRB_LEN(p) ((p) & 0x1ffff) -#define TRB_LEN_MASK (0x1ffff) -/* Interrupter Target - which MSI-X vector to target the completion event at */ -#define TRB_INTR_TARGET_SHIFT (22) -#define TRB_INTR_TARGET_MASK (0x3ff) -#define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22) -#define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff) -#define TRB_TBC(p) (((p) & 0x3) << 7) -#define TRB_TLBPC(p) (((p) & 0xf) << 16) - -/* Cycle bit - indicates TRB ownership by HC or HCD */ -#define TRB_CYCLE (1<<0) -/* - * Force next event data TRB to be evaluated before task switch. - * Used to pass OS data back after a TD completes. - */ -#define TRB_ENT (1<<1) -/* Interrupt on short packet */ -#define TRB_ISP (1<<2) -/* Set PCIe no snoop attribute */ -#define TRB_NO_SNOOP (1<<3) -/* Chain multiple TRBs into a TD */ -#define TRB_CHAIN (1<<4) -/* Interrupt on completion */ -#define TRB_IOC (1<<5) -/* The buffer pointer contains immediate data */ -#define TRB_IDT (1<<6) - -/* Block Event Interrupt */ -#define TRB_BEI (1<<9) - -/* Control transfer TRB specific fields */ -#define TRB_DIR_IN (1<<16) -#define TRB_TX_TYPE(p) ((p) << 16) -#define TRB_TX_TYPE_SHIFT (16) -#define TRB_DATA_OUT 2 -#define TRB_DATA_IN 3 - -/* Isochronous TRB specific fields */ -#define TRB_SIA (1 << 31) - -struct xhci_generic_trb { - volatile __le32 field[4]; -}; - -union xhci_trb { - struct xhci_link_trb link; - struct xhci_transfer_event trans_event; - struct xhci_event_cmd event_cmd; - struct xhci_generic_trb generic; -}; - -/* TRB bit mask */ -#define TRB_TYPE_BITMASK (0xfc00) -#define TRB_TYPE(p) ((p) << 10) -#define TRB_TYPE_SHIFT (10) -#define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10) - -/* TRB type IDs */ -typedef enum { - /* bulk, interrupt, isoc scatter/gather, and control data stage */ - TRB_NORMAL = 1, - /* setup stage for control transfers */ - TRB_SETUP, /* 2 */ - /* data stage for control transfers */ - TRB_DATA, /* 3 */ - /* status stage for control transfers */ - TRB_STATUS, /* 4 */ - /* isoc transfers */ - TRB_ISOC, /* 5 */ - /* TRB for linking ring segments */ - TRB_LINK, /* 6 */ - /* TRB for EVENT DATA */ - TRB_EVENT_DATA, /* 7 */ - /* Transfer Ring No-op (not for the command ring) */ - TRB_TR_NOOP, /* 8 */ - /* Command TRBs */ - /* Enable Slot Command */ - TRB_ENABLE_SLOT, /* 9 */ - /* Disable Slot Command */ - TRB_DISABLE_SLOT, /* 10 */ - /* Address Device Command */ - TRB_ADDR_DEV, /* 11 */ - /* Configure Endpoint Command */ - TRB_CONFIG_EP, /* 12 */ - /* Evaluate Context Command */ - TRB_EVAL_CONTEXT, /* 13 */ - /* Reset Endpoint Command */ - TRB_RESET_EP, /* 14 */ - /* Stop Transfer Ring Command */ - TRB_STOP_RING, /* 15 */ - /* Set Transfer Ring Dequeue Pointer Command */ - TRB_SET_DEQ, /* 16 */ - /* Reset Device Command */ - TRB_RESET_DEV, /* 17 */ - /* Force Event Command (opt) */ - TRB_FORCE_EVENT, /* 18 */ - /* Negotiate Bandwidth Command (opt) */ - TRB_NEG_BANDWIDTH, /* 19 */ - /* Set Latency Tolerance Value Command (opt) */ - TRB_SET_LT, /* 20 */ - /* Get port bandwidth Command */ - TRB_GET_BW, /* 21 */ - /* Force Header Command - generate a transaction or link management packet */ - TRB_FORCE_HEADER, /* 22 */ - /* No-op Command - not for transfer rings */ - TRB_CMD_NOOP, /* 23 */ - /* TRB IDs 24-31 reserved */ - /* Event TRBS */ - /* Transfer Event */ - TRB_TRANSFER = 32, - /* Command Completion Event */ - TRB_COMPLETION, /* 33 */ - /* Port Status Change Event */ - TRB_PORT_STATUS, /* 34 */ - /* Bandwidth Request Event (opt) */ - TRB_BANDWIDTH_EVENT, /* 35 */ - /* Doorbell Event (opt) */ - TRB_DOORBELL, /* 36 */ - /* Host Controller Event */ - TRB_HC_EVENT, /* 37 */ - /* Device Notification Event - device sent function wake notification */ - TRB_DEV_NOTE, /* 38 */ - /* MFINDEX Wrap Event - microframe counter wrapped */ - TRB_MFINDEX_WRAP, /* 39 */ - /* TRB IDs 40-47 reserved, 48-63 is vendor-defined */ - /* Nec vendor-specific command completion event. */ - TRB_NEC_CMD_COMP = 48, /* 48 */ - /* Get NEC firmware revision. */ - TRB_NEC_GET_FW, /* 49 */ -} trb_type; - -#define TRB_TYPE_LINK(x) (((x) & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK)) -/* Above, but for __le32 types -- can avoid work by swapping constants: */ -#define TRB_TYPE_LINK_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \ - cpu_to_le32(TRB_TYPE(TRB_LINK))) -#define TRB_TYPE_NOOP_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \ - cpu_to_le32(TRB_TYPE(TRB_TR_NOOP))) - -/* - * TRBS_PER_SEGMENT must be a multiple of 4, - * since the command ring is 64-byte aligned. - * It must also be greater than 16. - */ -#define TRBS_PER_SEGMENT 64 -/* Allow two commands + a link TRB, along with any reserved command TRBs */ -#define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3) -#define SEGMENT_SIZE (TRBS_PER_SEGMENT*16) -/* SEGMENT_SHIFT should be log2(SEGMENT_SIZE). - * Change this if you change TRBS_PER_SEGMENT! - */ -#define SEGMENT_SHIFT 10 -/* TRB buffer pointers can't cross 64KB boundaries */ -#define TRB_MAX_BUFF_SHIFT 16 -#define TRB_MAX_BUFF_SIZE (1 << TRB_MAX_BUFF_SHIFT) - -struct xhci_segment { - union xhci_trb *trbs; - /* private to HCD */ - struct xhci_segment *next; -}; - -struct xhci_ring { - struct xhci_segment *first_seg; - union xhci_trb *enqueue; - struct xhci_segment *enq_seg; - union xhci_trb *dequeue; - struct xhci_segment *deq_seg; - /* - * Write the cycle state into the TRB cycle field to give ownership of - * the TRB to the host controller (if we are the producer), or to check - * if we own the TRB (if we are the consumer). See section 4.9.1. - */ - volatile u32 cycle_state; - unsigned int num_segs; -}; - -struct xhci_erst_entry { - /* 64-bit event ring segment address */ - __le64 seg_addr; - __le32 seg_size; - /* Set to zero */ - __le32 rsvd; -}; - -struct xhci_erst { - struct xhci_erst_entry *entries; - unsigned int num_entries; - /* Num entries the ERST can contain */ - unsigned int erst_size; -}; - -/* - * Each segment table entry is 4*32bits long. 1K seems like an ok size: - * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, - * meaning 64 ring segments. - * Initial allocated size of the ERST, in number of entries */ -#define ERST_NUM_SEGS 3 -/* Initial number of event segment rings allocated */ -#define ERST_ENTRIES 3 -/* Initial allocated size of the ERST, in number of entries */ -#define ERST_SIZE 64 -/* Poll every 60 seconds */ -#define POLL_TIMEOUT 60 -/* Stop endpoint command timeout (secs) for URB cancellation watchdog timer */ -#define XHCI_STOP_EP_CMD_TIMEOUT 5 -/* XXX: Make these module parameters */ - -struct xhci_virt_ep { - struct xhci_ring *ring; - unsigned int ep_state; -#define SET_DEQ_PENDING (1 << 0) -#define EP_HALTED (1 << 1) /* For stall handling */ -#define EP_HALT_PENDING (1 << 2) /* For URB cancellation */ -/* Transitioning the endpoint to using streams, don't enqueue URBs */ -#define EP_GETTING_STREAMS (1 << 3) -#define EP_HAS_STREAMS (1 << 4) -/* Transitioning the endpoint to not using streams, don't enqueue URBs */ -#define EP_GETTING_NO_STREAMS (1 << 5) -}; - -#define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32) - -struct xhci_virt_device { - struct usb_device *udev; - /* - * Commands to the hardware are passed an "input context" that - * tells the hardware what to change in its data structures. - * The hardware will return changes in an "output context" that - * software must allocate for the hardware. We need to keep - * track of input and output contexts separately because - * these commands might fail and we don't trust the hardware. - */ - struct xhci_container_ctx *out_ctx; - /* Used for addressing devices and configuration changes */ - struct xhci_container_ctx *in_ctx; - /* Rings saved to ensure old alt settings can be re-instated */ -#define XHCI_MAX_RINGS_CACHED 31 - struct xhci_virt_ep eps[31]; -}; - -/* TODO: copied from ehci.h - can be refactored? */ -/* xHCI spec says all registers are little endian */ -static inline unsigned int xhci_readl(uint32_t volatile *regs) -{ - return readl(regs); -} - -static inline void xhci_writel(uint32_t volatile *regs, const unsigned int val) -{ - writel(val, regs); -} - -/* - * Registers should always be accessed with double word or quad word accesses. - * Some xHCI implementations may support 64-bit address pointers. Registers - * with 64-bit address pointers should be written to with dword accesses by - * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second. - * xHCI implementations that do not support 64-bit address pointers will ignore - * the high dword, and write order is irrelevant. - */ -static inline u64 xhci_readq(__le64 volatile *regs) -{ - __u32 *ptr = (__u32 *)regs; - u64 val_lo = readl(ptr); - u64 val_hi = readl(ptr + 1); - return val_lo + (val_hi << 32); -} - -static inline void xhci_writeq(__le64 volatile *regs, const u64 val) -{ - __u32 *ptr = (__u32 *)regs; - u32 val_lo = lower_32_bits(val); - /* FIXME */ - u32 val_hi = 0; - writel(val_lo, ptr); - writel(val_hi, ptr + 1); -} - -int xhci_hcd_init(int index, struct xhci_hccr **ret_hccr, - struct xhci_hcor **ret_hcor); -void xhci_hcd_stop(int index); - - -/************************************************************* - EXTENDED CAPABILITY DEFINITIONS -*************************************************************/ -/* Up to 16 ms to halt an HC */ -#define XHCI_MAX_HALT_USEC (16*1000) -/* HC not running - set to 1 when run/stop bit is cleared. */ -#define XHCI_STS_HALT (1 << 0) - -/* HCCPARAMS offset from PCI base address */ -#define XHCI_HCC_PARAMS_OFFSET 0x10 -/* HCCPARAMS contains the first extended capability pointer */ -#define XHCI_HCC_EXT_CAPS(p) (((p)>>16)&0xffff) - -/* Command and Status registers offset from the Operational Registers address */ -#define XHCI_CMD_OFFSET 0x00 -#define XHCI_STS_OFFSET 0x04 - -#define XHCI_MAX_EXT_CAPS 50 - -/* Capability Register */ -/* bits 7:0 - how long is the Capabilities register */ -#define XHCI_HC_LENGTH(p) (((p) >> 00) & 0x00ff) - -/* Extended capability register fields */ -#define XHCI_EXT_CAPS_ID(p) (((p) >> 0) & 0xff) -#define XHCI_EXT_CAPS_NEXT(p) (((p) >> 8) & 0xff) -#define XHCI_EXT_CAPS_VAL(p) ((p) >> 16) -/* Extended capability IDs - ID 0 reserved */ -#define XHCI_EXT_CAPS_LEGACY 1 -#define XHCI_EXT_CAPS_PROTOCOL 2 -#define XHCI_EXT_CAPS_PM 3 -#define XHCI_EXT_CAPS_VIRT 4 -#define XHCI_EXT_CAPS_ROUTE 5 -/* IDs 6-9 reserved */ -#define XHCI_EXT_CAPS_DEBUG 10 -/* USB Legacy Support Capability - section 7.1.1 */ -#define XHCI_HC_BIOS_OWNED (1 << 16) -#define XHCI_HC_OS_OWNED (1 << 24) - -/* USB Legacy Support Capability - section 7.1.1 */ -/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */ -#define XHCI_LEGACY_SUPPORT_OFFSET (0x00) - -/* USB Legacy Support Control and Status Register - section 7.1.2 */ -/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */ -#define XHCI_LEGACY_CONTROL_OFFSET (0x04) -/* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ -#define XHCI_LEGACY_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17)) - -/* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */ -#define XHCI_L1C (1 << 16) - -/* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ -#define XHCI_HLC (1 << 19) - -/* command register values to disable interrupts and halt the HC */ -/* start/stop HC execution - do not write unless HC is halted*/ -#define XHCI_CMD_RUN (1 << 0) -/* Event Interrupt Enable - get irq when EINT bit is set in USBSTS register */ -#define XHCI_CMD_EIE (1 << 2) -/* Host System Error Interrupt Enable - get irq when HSEIE bit set in USBSTS */ -#define XHCI_CMD_HSEIE (1 << 3) -/* Enable Wrap Event - '1' means xHC generates an event when MFINDEX wraps. */ -#define XHCI_CMD_EWE (1 << 10) - -#define XHCI_IRQS (XHCI_CMD_EIE | XHCI_CMD_HSEIE | XHCI_CMD_EWE) - -/* true: Controller Not Ready to accept doorbell or op reg writes after reset */ -#define XHCI_STS_CNR (1 << 11) - -struct xhci_ctrl { - struct xhci_hccr *hccr; /* R/O registers, not need for volatile */ - struct xhci_hcor *hcor; - struct xhci_doorbell_array *dba; - struct xhci_run_regs *run_regs; - struct xhci_device_context_array *dcbaa \ - __attribute__ ((aligned(ARCH_DMA_MINALIGN))); - struct xhci_ring *event_ring; - struct xhci_ring *cmd_ring; - struct xhci_ring *transfer_ring; - struct xhci_segment *seg; - struct xhci_intr_reg *ir_set; - struct xhci_erst erst; - struct xhci_erst_entry entry[ERST_NUM_SEGS]; - struct xhci_virt_device *devs[MAX_HC_SLOTS]; - int rootdev; -}; - -unsigned long trb_addr(struct xhci_segment *seg, union xhci_trb *trb); -struct xhci_input_control_ctx - *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx); -struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *ctx); -struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *ctx, - unsigned int ep_index); -void xhci_endpoint_copy(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx, - unsigned int ep_index); -void xhci_slot_copy(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx); -void xhci_setup_addressable_virt_dev(struct usb_device *udev); -void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, - u32 slot_id, u32 ep_index, trb_type cmd); -void xhci_acknowledge_event(struct xhci_ctrl *ctrl); -union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected); -int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer); -int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, - struct devrequest *req, int length, void *buffer); -int xhci_check_maxpacket(struct usb_device *udev); -void xhci_flush_cache(uint32_t addr, u32 type_len); -void xhci_inval_cache(uint32_t addr, u32 type_len); -void xhci_cleanup(struct xhci_ctrl *ctrl); -struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs); -int xhci_alloc_virt_device(struct usb_device *udev); -int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, - struct xhci_hcor *hcor); - -#endif /* HOST_XHCI_H_ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/Makefile b/qemu/roms/u-boot/drivers/usb/musb-new/Makefile deleted file mode 100644 index 3facf0fc1..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# for USB OTG silicon based on Mentor Graphics INVENTRA designs -# - -obj-$(CONFIG_MUSB_GADGET) += musb_gadget.o musb_gadget_ep0.o musb_core.o -obj-$(CONFIG_MUSB_GADGET) += musb_uboot.o -obj-$(CONFIG_MUSB_HOST) += musb_host.o musb_core.o musb_uboot.o -obj-$(CONFIG_USB_MUSB_DSPS) += musb_dsps.o -obj-$(CONFIG_USB_MUSB_AM35X) += am35x.o -obj-$(CONFIG_USB_MUSB_OMAP2PLUS) += omap2430.o - -ccflags-y := $(call cc-option,-Wno-unused-variable) \ - $(call cc-option,-Wno-unused-but-set-variable) \ - $(call cc-option,-Wno-unused-label) diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/am35x.c b/qemu/roms/u-boot/drivers/usb/musb-new/am35x.c deleted file mode 100644 index 57c9bd393..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/am35x.c +++ /dev/null @@ -1,709 +0,0 @@ -/* - * Texas Instruments AM35x "glue layer" - * - * Copyright (c) 2010, by Texas Instruments - * - * Based on the DA8xx "glue layer" code. - * Copyright (c) 2008-2009, MontaVista Software, Inc. <source@mvista.com> - * - * This file is part of the Inventra Controller Driver for Linux. - * - * The Inventra Controller Driver for Linux is free software; you - * can redistribute it and/or modify it under the terms of the GNU - * General Public License version 2 as published by the Free Software - * Foundation. - * - * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; if not, - * write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define __UBOOT__ -#ifndef __UBOOT__ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/dma-mapping.h> - -#include <plat/usb.h> -#else -#include <common.h> -#include <asm/omap_musb.h> -#include "linux-compat.h" -#endif - -#include "musb_core.h" - -/* - * AM35x specific definitions - */ -/* USB 2.0 OTG module registers */ -#define USB_REVISION_REG 0x00 -#define USB_CTRL_REG 0x04 -#define USB_STAT_REG 0x08 -#define USB_EMULATION_REG 0x0c -/* 0x10 Reserved */ -#define USB_AUTOREQ_REG 0x14 -#define USB_SRP_FIX_TIME_REG 0x18 -#define USB_TEARDOWN_REG 0x1c -#define EP_INTR_SRC_REG 0x20 -#define EP_INTR_SRC_SET_REG 0x24 -#define EP_INTR_SRC_CLEAR_REG 0x28 -#define EP_INTR_MASK_REG 0x2c -#define EP_INTR_MASK_SET_REG 0x30 -#define EP_INTR_MASK_CLEAR_REG 0x34 -#define EP_INTR_SRC_MASKED_REG 0x38 -#define CORE_INTR_SRC_REG 0x40 -#define CORE_INTR_SRC_SET_REG 0x44 -#define CORE_INTR_SRC_CLEAR_REG 0x48 -#define CORE_INTR_MASK_REG 0x4c -#define CORE_INTR_MASK_SET_REG 0x50 -#define CORE_INTR_MASK_CLEAR_REG 0x54 -#define CORE_INTR_SRC_MASKED_REG 0x58 -/* 0x5c Reserved */ -#define USB_END_OF_INTR_REG 0x60 - -/* Control register bits */ -#define AM35X_SOFT_RESET_MASK 1 - -/* USB interrupt register bits */ -#define AM35X_INTR_USB_SHIFT 16 -#define AM35X_INTR_USB_MASK (0x1ff << AM35X_INTR_USB_SHIFT) -#define AM35X_INTR_DRVVBUS 0x100 -#define AM35X_INTR_RX_SHIFT 16 -#define AM35X_INTR_TX_SHIFT 0 -#define AM35X_TX_EP_MASK 0xffff /* EP0 + 15 Tx EPs */ -#define AM35X_RX_EP_MASK 0xfffe /* 15 Rx EPs */ -#define AM35X_TX_INTR_MASK (AM35X_TX_EP_MASK << AM35X_INTR_TX_SHIFT) -#define AM35X_RX_INTR_MASK (AM35X_RX_EP_MASK << AM35X_INTR_RX_SHIFT) - -#define USB_MENTOR_CORE_OFFSET 0x400 - -struct am35x_glue { - struct device *dev; - struct platform_device *musb; - struct clk *phy_clk; - struct clk *clk; -}; -#define glue_to_musb(g) platform_get_drvdata(g->musb) - -/* - * am35x_musb_enable - enable interrupts - */ -static void am35x_musb_enable(struct musb *musb) -{ - void __iomem *reg_base = musb->ctrl_base; - u32 epmask; - - /* Workaround: setup IRQs through both register sets. */ - epmask = ((musb->epmask & AM35X_TX_EP_MASK) << AM35X_INTR_TX_SHIFT) | - ((musb->epmask & AM35X_RX_EP_MASK) << AM35X_INTR_RX_SHIFT); - - musb_writel(reg_base, EP_INTR_MASK_SET_REG, epmask); - musb_writel(reg_base, CORE_INTR_MASK_SET_REG, AM35X_INTR_USB_MASK); - - /* Force the DRVVBUS IRQ so we can start polling for ID change. */ - if (is_otg_enabled(musb)) - musb_writel(reg_base, CORE_INTR_SRC_SET_REG, - AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT); -} - -/* - * am35x_musb_disable - disable HDRC and flush interrupts - */ -static void am35x_musb_disable(struct musb *musb) -{ - void __iomem *reg_base = musb->ctrl_base; - - musb_writel(reg_base, CORE_INTR_MASK_CLEAR_REG, AM35X_INTR_USB_MASK); - musb_writel(reg_base, EP_INTR_MASK_CLEAR_REG, - AM35X_TX_INTR_MASK | AM35X_RX_INTR_MASK); - musb_writeb(musb->mregs, MUSB_DEVCTL, 0); - musb_writel(reg_base, USB_END_OF_INTR_REG, 0); -} - -#ifndef __UBOOT__ -#define portstate(stmt) stmt - -static void am35x_musb_set_vbus(struct musb *musb, int is_on) -{ - WARN_ON(is_on && is_peripheral_active(musb)); -} - -#define POLL_SECONDS 2 - -static struct timer_list otg_workaround; - -static void otg_timer(unsigned long _musb) -{ - struct musb *musb = (void *)_musb; - void __iomem *mregs = musb->mregs; - u8 devctl; - unsigned long flags; - - /* - * We poll because AM35x's won't expose several OTG-critical - * status change events (from the transceiver) otherwise. - */ - devctl = musb_readb(mregs, MUSB_DEVCTL); - dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, - otg_state_string(musb->xceiv->state)); - - spin_lock_irqsave(&musb->lock, flags); - switch (musb->xceiv->state) { - case OTG_STATE_A_WAIT_BCON: - devctl &= ~MUSB_DEVCTL_SESSION; - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - if (devctl & MUSB_DEVCTL_BDEVICE) { - musb->xceiv->state = OTG_STATE_B_IDLE; - MUSB_DEV_MODE(musb); - } else { - musb->xceiv->state = OTG_STATE_A_IDLE; - MUSB_HST_MODE(musb); - } - break; - case OTG_STATE_A_WAIT_VFALL: - musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; - musb_writel(musb->ctrl_base, CORE_INTR_SRC_SET_REG, - MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT); - break; - case OTG_STATE_B_IDLE: - if (!is_peripheral_enabled(musb)) - break; - - devctl = musb_readb(mregs, MUSB_DEVCTL); - if (devctl & MUSB_DEVCTL_BDEVICE) - mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); - else - musb->xceiv->state = OTG_STATE_A_IDLE; - break; - default: - break; - } - spin_unlock_irqrestore(&musb->lock, flags); -} - -static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout) -{ - static unsigned long last_timer; - - if (!is_otg_enabled(musb)) - return; - - if (timeout == 0) - timeout = jiffies + msecs_to_jiffies(3); - - /* Never idle if active, or when VBUS timeout is not set as host */ - if (musb->is_active || (musb->a_wait_bcon == 0 && - musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { - dev_dbg(musb->controller, "%s active, deleting timer\n", - otg_state_string(musb->xceiv->state)); - del_timer(&otg_workaround); - last_timer = jiffies; - return; - } - - if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) { - dev_dbg(musb->controller, "Longer idle timer already pending, ignoring...\n"); - return; - } - last_timer = timeout; - - dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", - otg_state_string(musb->xceiv->state), - jiffies_to_msecs(timeout - jiffies)); - mod_timer(&otg_workaround, timeout); -} -#endif - -static irqreturn_t am35x_musb_interrupt(int irq, void *hci) -{ - struct musb *musb = hci; - void __iomem *reg_base = musb->ctrl_base; -#ifndef __UBOOT__ - struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; - struct usb_otg *otg = musb->xceiv->otg; -#else - struct omap_musb_board_data *data = - (struct omap_musb_board_data *)musb->controller; -#endif - unsigned long flags; - irqreturn_t ret = IRQ_NONE; - u32 epintr, usbintr; - -#ifdef __UBOOT__ - /* - * It seems that on AM35X interrupt registers can be updated - * before core registers. This confuses the code. - * As a workaround add a small delay here. - */ - udelay(10); -#endif - spin_lock_irqsave(&musb->lock, flags); - - /* Get endpoint interrupts */ - epintr = musb_readl(reg_base, EP_INTR_SRC_MASKED_REG); - - if (epintr) { - musb_writel(reg_base, EP_INTR_SRC_CLEAR_REG, epintr); - - musb->int_rx = - (epintr & AM35X_RX_INTR_MASK) >> AM35X_INTR_RX_SHIFT; - musb->int_tx = - (epintr & AM35X_TX_INTR_MASK) >> AM35X_INTR_TX_SHIFT; - } - - /* Get usb core interrupts */ - usbintr = musb_readl(reg_base, CORE_INTR_SRC_MASKED_REG); - if (!usbintr && !epintr) - goto eoi; - - if (usbintr) { - musb_writel(reg_base, CORE_INTR_SRC_CLEAR_REG, usbintr); - - musb->int_usb = - (usbintr & AM35X_INTR_USB_MASK) >> AM35X_INTR_USB_SHIFT; - } -#ifndef __UBOOT__ - /* - * DRVVBUS IRQs are the only proxy we have (a very poor one!) for - * AM35x's missing ID change IRQ. We need an ID change IRQ to - * switch appropriately between halves of the OTG state machine. - * Managing DEVCTL.SESSION per Mentor docs requires that we know its - * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set. - * Also, DRVVBUS pulses for SRP (but not at 5V) ... - */ - if (usbintr & (AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT)) { - int drvvbus = musb_readl(reg_base, USB_STAT_REG); - void __iomem *mregs = musb->mregs; - u8 devctl = musb_readb(mregs, MUSB_DEVCTL); - int err; - - err = is_host_enabled(musb) && (musb->int_usb & - MUSB_INTR_VBUSERROR); - if (err) { - /* - * The Mentor core doesn't debounce VBUS as needed - * to cope with device connect current spikes. This - * means it's not uncommon for bus-powered devices - * to get VBUS errors during enumeration. - * - * This is a workaround, but newer RTL from Mentor - * seems to allow a better one: "re"-starting sessions - * without waiting for VBUS to stop registering in - * devctl. - */ - musb->int_usb &= ~MUSB_INTR_VBUSERROR; - musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; - mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); - WARNING("VBUS error workaround (delay coming)\n"); - } else if (is_host_enabled(musb) && drvvbus) { - MUSB_HST_MODE(musb); - otg->default_a = 1; - musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; - portstate(musb->port1_status |= USB_PORT_STAT_POWER); - del_timer(&otg_workaround); - } else { - musb->is_active = 0; - MUSB_DEV_MODE(musb); - otg->default_a = 0; - musb->xceiv->state = OTG_STATE_B_IDLE; - portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); - } - - /* NOTE: this must complete power-on within 100 ms. */ - dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", - drvvbus ? "on" : "off", - otg_state_string(musb->xceiv->state), - err ? " ERROR" : "", - devctl); - ret = IRQ_HANDLED; - } -#endif - - if (musb->int_tx || musb->int_rx || musb->int_usb) - ret |= musb_interrupt(musb); - -eoi: - /* EOI needs to be written for the IRQ to be re-asserted. */ - if (ret == IRQ_HANDLED || epintr || usbintr) { - /* clear level interrupt */ - if (data->clear_irq) - data->clear_irq(); - /* write EOI */ - musb_writel(reg_base, USB_END_OF_INTR_REG, 0); - } - -#ifndef __UBOOT__ - /* Poll for ID change */ - if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) - mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); -#endif - - spin_unlock_irqrestore(&musb->lock, flags); - - return ret; -} - -#ifndef __UBOOT__ -static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode) -{ - struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; - int retval = 0; - - if (data->set_mode) - data->set_mode(musb_mode); - else - retval = -EIO; - - return retval; -} -#endif - -static int am35x_musb_init(struct musb *musb) -{ -#ifndef __UBOOT__ - struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; -#else - struct omap_musb_board_data *data = - (struct omap_musb_board_data *)musb->controller; -#endif - void __iomem *reg_base = musb->ctrl_base; - u32 rev; - - musb->mregs += USB_MENTOR_CORE_OFFSET; - - /* Returns zero if e.g. not clocked */ - rev = musb_readl(reg_base, USB_REVISION_REG); - if (!rev) - return -ENODEV; - -#ifndef __UBOOT__ - usb_nop_xceiv_register(); - musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(musb->xceiv)) - return -ENODEV; - - if (is_host_enabled(musb)) - setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); -#endif - - /* Reset the musb */ - if (data->reset) - data->reset(); - - /* Reset the controller */ - musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); - - /* Start the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(1); - - msleep(5); - - musb->isr = am35x_musb_interrupt; - - /* clear level interrupt */ - if (data->clear_irq) - data->clear_irq(); - - return 0; -} - -static int am35x_musb_exit(struct musb *musb) -{ -#ifndef __UBOOT__ - struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; -#else - struct omap_musb_board_data *data = - (struct omap_musb_board_data *)musb->controller; -#endif - -#ifndef __UBOOT__ - if (is_host_enabled(musb)) - del_timer_sync(&otg_workaround); -#endif - - /* Shutdown the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(0); - -#ifndef __UBOOT__ - usb_put_phy(musb->xceiv); - usb_nop_xceiv_unregister(); -#endif - - return 0; -} - -/* AM35x supports only 32bit read operation */ -void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) -{ - void __iomem *fifo = hw_ep->fifo; - u32 val; - int i; - - /* Read for 32bit-aligned destination address */ - if (likely((0x03 & (unsigned long) dst) == 0) && len >= 4) { - readsl(fifo, dst, len >> 2); - dst += len & ~0x03; - len &= 0x03; - } - /* - * Now read the remaining 1 to 3 byte or complete length if - * unaligned address. - */ - if (len > 4) { - for (i = 0; i < (len >> 2); i++) { - *(u32 *) dst = musb_readl(fifo, 0); - dst += 4; - } - len &= 0x03; - } - if (len > 0) { - val = musb_readl(fifo, 0); - memcpy(dst, &val, len); - } -} - -#ifndef __UBOOT__ -static const struct musb_platform_ops am35x_ops = { -#else -const struct musb_platform_ops am35x_ops = { -#endif - .init = am35x_musb_init, - .exit = am35x_musb_exit, - - .enable = am35x_musb_enable, - .disable = am35x_musb_disable, - -#ifndef __UBOOT__ - .set_mode = am35x_musb_set_mode, - .try_idle = am35x_musb_try_idle, - - .set_vbus = am35x_musb_set_vbus, -#endif -}; - -#ifndef __UBOOT__ -static u64 am35x_dmamask = DMA_BIT_MASK(32); - -static int __devinit am35x_probe(struct platform_device *pdev) -{ - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; - struct platform_device *musb; - struct am35x_glue *glue; - - struct clk *phy_clk; - struct clk *clk; - - int ret = -ENOMEM; - - glue = kzalloc(sizeof(*glue), GFP_KERNEL); - if (!glue) { - dev_err(&pdev->dev, "failed to allocate glue context\n"); - goto err0; - } - - musb = platform_device_alloc("musb-hdrc", -1); - if (!musb) { - dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err1; - } - - phy_clk = clk_get(&pdev->dev, "fck"); - if (IS_ERR(phy_clk)) { - dev_err(&pdev->dev, "failed to get PHY clock\n"); - ret = PTR_ERR(phy_clk); - goto err2; - } - - clk = clk_get(&pdev->dev, "ick"); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, "failed to get clock\n"); - ret = PTR_ERR(clk); - goto err3; - } - - ret = clk_enable(phy_clk); - if (ret) { - dev_err(&pdev->dev, "failed to enable PHY clock\n"); - goto err4; - } - - ret = clk_enable(clk); - if (ret) { - dev_err(&pdev->dev, "failed to enable clock\n"); - goto err5; - } - - musb->dev.parent = &pdev->dev; - musb->dev.dma_mask = &am35x_dmamask; - musb->dev.coherent_dma_mask = am35x_dmamask; - - glue->dev = &pdev->dev; - glue->musb = musb; - glue->phy_clk = phy_clk; - glue->clk = clk; - - pdata->platform_ops = &am35x_ops; - - platform_set_drvdata(pdev, glue); - - ret = platform_device_add_resources(musb, pdev->resource, - pdev->num_resources); - if (ret) { - dev_err(&pdev->dev, "failed to add resources\n"); - goto err6; - } - - ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); - if (ret) { - dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err6; - } - - ret = platform_device_add(musb); - if (ret) { - dev_err(&pdev->dev, "failed to register musb device\n"); - goto err6; - } - - return 0; - -err6: - clk_disable(clk); - -err5: - clk_disable(phy_clk); - -err4: - clk_put(clk); - -err3: - clk_put(phy_clk); - -err2: - platform_device_put(musb); - -err1: - kfree(glue); - -err0: - return ret; -} - -static int __devexit am35x_remove(struct platform_device *pdev) -{ - struct am35x_glue *glue = platform_get_drvdata(pdev); - - platform_device_del(glue->musb); - platform_device_put(glue->musb); - clk_disable(glue->clk); - clk_disable(glue->phy_clk); - clk_put(glue->clk); - clk_put(glue->phy_clk); - kfree(glue); - - return 0; -} - -#ifdef CONFIG_PM -static int am35x_suspend(struct device *dev) -{ - struct am35x_glue *glue = dev_get_drvdata(dev); - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; - - /* Shutdown the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(0); - - clk_disable(glue->phy_clk); - clk_disable(glue->clk); - - return 0; -} - -static int am35x_resume(struct device *dev) -{ - struct am35x_glue *glue = dev_get_drvdata(dev); - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; - int ret; - - /* Start the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(1); - - ret = clk_enable(glue->phy_clk); - if (ret) { - dev_err(dev, "failed to enable PHY clock\n"); - return ret; - } - - ret = clk_enable(glue->clk); - if (ret) { - dev_err(dev, "failed to enable clock\n"); - return ret; - } - - return 0; -} - -static struct dev_pm_ops am35x_pm_ops = { - .suspend = am35x_suspend, - .resume = am35x_resume, -}; - -#define DEV_PM_OPS &am35x_pm_ops -#else -#define DEV_PM_OPS NULL -#endif - -static struct platform_driver am35x_driver = { - .probe = am35x_probe, - .remove = __devexit_p(am35x_remove), - .driver = { - .name = "musb-am35x", - .pm = DEV_PM_OPS, - }, -}; - -MODULE_DESCRIPTION("AM35x MUSB Glue Layer"); -MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>"); -MODULE_LICENSE("GPL v2"); - -static int __init am35x_init(void) -{ - return platform_driver_register(&am35x_driver); -} -module_init(am35x_init); - -static void __exit am35x_exit(void) -{ - platform_driver_unregister(&am35x_driver); -} -module_exit(am35x_exit); -#endif diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/linux-compat.h b/qemu/roms/u-boot/drivers/usb/musb-new/linux-compat.h deleted file mode 100644 index d7a5663de..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/linux-compat.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef __LINUX_COMPAT_H__ -#define __LINUX_COMPAT_H__ - -#include <malloc.h> -#include <linux/list.h> -#include <linux/compat.h> - -#define __init -#define __devinit -#define __devinitdata -#define __devinitconst -#define __iomem -#define __deprecated - -struct unused {}; -typedef struct unused unused_t; - -typedef int irqreturn_t; -typedef unused_t spinlock_t; - -struct work_struct {}; - -struct timer_list {}; -struct notifier_block {}; - -typedef unsigned long dmaaddr_t; - -#define spin_lock_init(lock) do {} while (0) -#define spin_lock(lock) do {} while (0) -#define spin_unlock(lock) do {} while (0) -#define spin_lock_irqsave(lock, flags) do {} while (0) -#define spin_unlock_irqrestore(lock, flags) do {} while (0) - -#define setup_timer(timer, func, data) do {} while (0) -#define del_timer_sync(timer) do {} while (0) -#define schedule_work(work) do {} while (0) -#define INIT_WORK(work, fun) do {} while (0) - -#define cpu_relax() do {} while (0) - -#define pr_debug(fmt, args...) debug(fmt, ##args) - -#define WARN(condition, fmt, args...) ({ \ - int ret_warn = !!condition; \ - if (ret_warn) \ - printf(fmt, ##args); \ - ret_warn; }) - -#define pm_runtime_get_sync(dev) do {} while (0) -#define pm_runtime_put(dev) do {} while (0) -#define pm_runtime_put_sync(dev) do {} while (0) -#define pm_runtime_use_autosuspend(dev) do {} while (0) -#define pm_runtime_set_autosuspend_delay(dev, delay) do {} while (0) -#define pm_runtime_enable(dev) do {} while (0) - -#define MODULE_DESCRIPTION(desc) -#define MODULE_AUTHOR(author) -#define MODULE_LICENSE(license) -#define MODULE_ALIAS(alias) -#define module_param(name, type, perm) -#define MODULE_PARM_DESC(name, desc) -#define EXPORT_SYMBOL_GPL(name) - -#define writesl(a, d, s) __raw_writesl((unsigned long)a, d, s) -#define readsl(a, d, s) __raw_readsl((unsigned long)a, d, s) -#define writesw(a, d, s) __raw_writesw((unsigned long)a, d, s) -#define readsw(a, d, s) __raw_readsw((unsigned long)a, d, s) -#define writesb(a, d, s) __raw_writesb((unsigned long)a, d, s) -#define readsb(a, d, s) __raw_readsb((unsigned long)a, d, s) - -#define IRQ_NONE 0 -#define IRQ_HANDLED 0 - -#define dev_set_drvdata(dev, data) do {} while (0) - -#define disable_irq_wake(irq) do {} while (0) -#define enable_irq_wake(irq) -EINVAL -#define free_irq(irq, data) do {} while (0) -#define request_irq(nr, f, flags, nm, data) 0 - -#define device_init_wakeup(dev, a) do {} while (0) - -#define platform_data device_data - -#ifndef wmb -#define wmb() asm volatile ("" : : : "memory") -#endif - -#define msleep(a) udelay(a * 1000) - -/* - * Map U-Boot config options to Linux ones - */ -#ifdef CONFIG_OMAP34XX -#define CONFIG_SOC_OMAP3430 -#endif - -#endif /* __LINUX_COMPAT_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_core.c b/qemu/roms/u-boot/drivers/usb/musb-new/musb_core.c deleted file mode 100644 index 36681b6fc..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_core.c +++ /dev/null @@ -1,2500 +0,0 @@ -/* - * MUSB OTG driver core code - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/* - * Inventra (Multipoint) Dual-Role Controller Driver for Linux. - * - * This consists of a Host Controller Driver (HCD) and a peripheral - * controller driver implementing the "Gadget" API; OTG support is - * in the works. These are normal Linux-USB controller drivers which - * use IRQs and have no dedicated thread. - * - * This version of the driver has only been used with products from - * Texas Instruments. Those products integrate the Inventra logic - * with other DMA, IRQ, and bus modules, as well as other logic that - * needs to be reflected in this driver. - * - * - * NOTE: the original Mentor code here was pretty much a collection - * of mechanisms that don't seem to have been fully integrated/working - * for *any* Linux kernel version. This version aims at Linux 2.6.now, - * Key open issues include: - * - * - Lack of host-side transaction scheduling, for all transfer types. - * The hardware doesn't do it; instead, software must. - * - * This is not an issue for OTG devices that don't support external - * hubs, but for more "normal" USB hosts it's a user issue that the - * "multipoint" support doesn't scale in the expected ways. That - * includes DaVinci EVM in a common non-OTG mode. - * - * * Control and bulk use dedicated endpoints, and there's as - * yet no mechanism to either (a) reclaim the hardware when - * peripherals are NAKing, which gets complicated with bulk - * endpoints, or (b) use more than a single bulk endpoint in - * each direction. - * - * RESULT: one device may be perceived as blocking another one. - * - * * Interrupt and isochronous will dynamically allocate endpoint - * hardware, but (a) there's no record keeping for bandwidth; - * (b) in the common case that few endpoints are available, there - * is no mechanism to reuse endpoints to talk to multiple devices. - * - * RESULT: At one extreme, bandwidth can be overcommitted in - * some hardware configurations, no faults will be reported. - * At the other extreme, the bandwidth capabilities which do - * exist tend to be severely undercommitted. You can't yet hook - * up both a keyboard and a mouse to an external USB hub. - */ - -/* - * This gets many kinds of configuration information: - * - Kconfig for everything user-configurable - * - platform_device for addressing, irq, and platform_data - * - platform_data is mostly for board-specific informarion - * (plus recentrly, SOC or family details) - * - * Most of the conditional compilation will (someday) vanish. - */ - -#define __UBOOT__ -#ifndef __UBOOT__ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/kobject.h> -#include <linux/prefetch.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#else -#include <common.h> -#include <usb.h> -#include <asm/errno.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <linux/usb/musb.h> -#include <asm/io.h> -#include "linux-compat.h" -#include "usb-compat.h" -#endif - -#include "musb_core.h" - -#define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON) - - -#define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" -#define DRIVER_DESC "Inventra Dual-Role USB Controller Driver" - -#define MUSB_VERSION "6.0" - -#define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION - -#define MUSB_DRIVER_NAME "musb-hdrc" -const char musb_driver_name[] = MUSB_DRIVER_NAME; - -MODULE_DESCRIPTION(DRIVER_INFO); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" MUSB_DRIVER_NAME); - - -#ifndef __UBOOT__ -/*-------------------------------------------------------------------------*/ - -static inline struct musb *dev_to_musb(struct device *dev) -{ - return dev_get_drvdata(dev); -} -#endif - -/*-------------------------------------------------------------------------*/ - -#ifndef __UBOOT__ -#ifndef CONFIG_BLACKFIN -static int musb_ulpi_read(struct usb_phy *phy, u32 offset) -{ - void __iomem *addr = phy->io_priv; - int i = 0; - u8 r; - u8 power; - int ret; - - pm_runtime_get_sync(phy->io_dev); - - /* Make sure the transceiver is not in low power mode */ - power = musb_readb(addr, MUSB_POWER); - power &= ~MUSB_POWER_SUSPENDM; - musb_writeb(addr, MUSB_POWER, power); - - /* REVISIT: musbhdrc_ulpi_an.pdf recommends setting the - * ULPICarKitControlDisableUTMI after clearing POWER_SUSPENDM. - */ - - musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset); - musb_writeb(addr, MUSB_ULPI_REG_CONTROL, - MUSB_ULPI_REG_REQ | MUSB_ULPI_RDN_WR); - - while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) - & MUSB_ULPI_REG_CMPLT)) { - i++; - if (i == 10000) { - ret = -ETIMEDOUT; - goto out; - } - - } - r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); - r &= ~MUSB_ULPI_REG_CMPLT; - musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); - - ret = musb_readb(addr, MUSB_ULPI_REG_DATA); - -out: - pm_runtime_put(phy->io_dev); - - return ret; -} - -static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) -{ - void __iomem *addr = phy->io_priv; - int i = 0; - u8 r = 0; - u8 power; - int ret = 0; - - pm_runtime_get_sync(phy->io_dev); - - /* Make sure the transceiver is not in low power mode */ - power = musb_readb(addr, MUSB_POWER); - power &= ~MUSB_POWER_SUSPENDM; - musb_writeb(addr, MUSB_POWER, power); - - musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset); - musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)data); - musb_writeb(addr, MUSB_ULPI_REG_CONTROL, MUSB_ULPI_REG_REQ); - - while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) - & MUSB_ULPI_REG_CMPLT)) { - i++; - if (i == 10000) { - ret = -ETIMEDOUT; - goto out; - } - } - - r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); - r &= ~MUSB_ULPI_REG_CMPLT; - musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); - -out: - pm_runtime_put(phy->io_dev); - - return ret; -} -#else -#define musb_ulpi_read NULL -#define musb_ulpi_write NULL -#endif - -static struct usb_phy_io_ops musb_ulpi_access = { - .read = musb_ulpi_read, - .write = musb_ulpi_write, -}; -#endif - -/*-------------------------------------------------------------------------*/ - -#if !defined(CONFIG_USB_MUSB_TUSB6010) && !defined(CONFIG_USB_MUSB_BLACKFIN) - -/* - * Load an endpoint's FIFO - */ -void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) -{ - struct musb *musb = hw_ep->musb; - void __iomem *fifo = hw_ep->fifo; - - prefetch((u8 *)src); - - dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", - 'T', hw_ep->epnum, fifo, len, src); - - /* we can't assume unaligned reads work */ - if (likely((0x01 & (unsigned long) src) == 0)) { - u16 index = 0; - - /* best case is 32bit-aligned source address */ - if ((0x02 & (unsigned long) src) == 0) { - if (len >= 4) { - writesl(fifo, src + index, len >> 2); - index += len & ~0x03; - } - if (len & 0x02) { - musb_writew(fifo, 0, *(u16 *)&src[index]); - index += 2; - } - } else { - if (len >= 2) { - writesw(fifo, src + index, len >> 1); - index += len & ~0x01; - } - } - if (len & 0x01) - musb_writeb(fifo, 0, src[index]); - } else { - /* byte aligned */ - writesb(fifo, src, len); - } -} - -#if !defined(CONFIG_USB_MUSB_AM35X) -/* - * Unload an endpoint's FIFO - */ -void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) -{ - struct musb *musb = hw_ep->musb; - void __iomem *fifo = hw_ep->fifo; - - dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", - 'R', hw_ep->epnum, fifo, len, dst); - - /* we can't assume unaligned writes work */ - if (likely((0x01 & (unsigned long) dst) == 0)) { - u16 index = 0; - - /* best case is 32bit-aligned destination address */ - if ((0x02 & (unsigned long) dst) == 0) { - if (len >= 4) { - readsl(fifo, dst, len >> 2); - index = len & ~0x03; - } - if (len & 0x02) { - *(u16 *)&dst[index] = musb_readw(fifo, 0); - index += 2; - } - } else { - if (len >= 2) { - readsw(fifo, dst, len >> 1); - index = len & ~0x01; - } - } - if (len & 0x01) - dst[index] = musb_readb(fifo, 0); - } else { - /* byte aligned */ - readsb(fifo, dst, len); - } -} -#endif - -#endif /* normal PIO */ - - -/*-------------------------------------------------------------------------*/ - -/* for high speed test mode; see USB 2.0 spec 7.1.20 */ -static const u8 musb_test_packet[53] = { - /* implicit SYNC then DATA0 to start */ - - /* JKJKJKJK x9 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* JJKKJJKK x8 */ - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - /* JJJJKKKK x8 */ - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - /* JJJJJJJKKKKKKK x8 */ - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - /* JJJJJJJK x8 */ - 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, - /* JKKKKKKK x10, JK */ - 0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e - - /* implicit CRC16 then EOP to end */ -}; - -void musb_load_testpacket(struct musb *musb) -{ - void __iomem *regs = musb->endpoints[0].regs; - - musb_ep_select(musb->mregs, 0); - musb_write_fifo(musb->control_ep, - sizeof(musb_test_packet), musb_test_packet); - musb_writew(regs, MUSB_CSR0, MUSB_CSR0_TXPKTRDY); -} - -#ifndef __UBOOT__ -/*-------------------------------------------------------------------------*/ - -/* - * Handles OTG hnp timeouts, such as b_ase0_brst - */ -void musb_otg_timer_func(unsigned long data) -{ - struct musb *musb = (struct musb *)data; - unsigned long flags; - - spin_lock_irqsave(&musb->lock, flags); - switch (musb->xceiv->state) { - case OTG_STATE_B_WAIT_ACON: - dev_dbg(musb->controller, "HNP: b_wait_acon timeout; back to b_peripheral\n"); - musb_g_disconnect(musb); - musb->xceiv->state = OTG_STATE_B_PERIPHERAL; - musb->is_active = 0; - break; - case OTG_STATE_A_SUSPEND: - case OTG_STATE_A_WAIT_BCON: - dev_dbg(musb->controller, "HNP: %s timeout\n", - otg_state_string(musb->xceiv->state)); - musb_platform_set_vbus(musb, 0); - musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; - break; - default: - dev_dbg(musb->controller, "HNP: Unhandled mode %s\n", - otg_state_string(musb->xceiv->state)); - } - musb->ignore_disconnect = 0; - spin_unlock_irqrestore(&musb->lock, flags); -} - -/* - * Stops the HNP transition. Caller must take care of locking. - */ -void musb_hnp_stop(struct musb *musb) -{ - struct usb_hcd *hcd = musb_to_hcd(musb); - void __iomem *mbase = musb->mregs; - u8 reg; - - dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state)); - - switch (musb->xceiv->state) { - case OTG_STATE_A_PERIPHERAL: - musb_g_disconnect(musb); - dev_dbg(musb->controller, "HNP: back to %s\n", - otg_state_string(musb->xceiv->state)); - break; - case OTG_STATE_B_HOST: - dev_dbg(musb->controller, "HNP: Disabling HR\n"); - hcd->self.is_b_host = 0; - musb->xceiv->state = OTG_STATE_B_PERIPHERAL; - MUSB_DEV_MODE(musb); - reg = musb_readb(mbase, MUSB_POWER); - reg |= MUSB_POWER_SUSPENDM; - musb_writeb(mbase, MUSB_POWER, reg); - /* REVISIT: Start SESSION_REQUEST here? */ - break; - default: - dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n", - otg_state_string(musb->xceiv->state)); - } - - /* - * When returning to A state after HNP, avoid hub_port_rebounce(), - * which cause occasional OPT A "Did not receive reset after connect" - * errors. - */ - musb->port1_status &= ~(USB_PORT_STAT_C_CONNECTION << 16); -} -#endif - -/* - * Interrupt Service Routine to record USB "global" interrupts. - * Since these do not happen often and signify things of - * paramount importance, it seems OK to check them individually; - * the order of the tests is specified in the manual - * - * @param musb instance pointer - * @param int_usb register contents - * @param devctl - * @param power - */ - -static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, - u8 devctl, u8 power) -{ -#ifndef __UBOOT__ - struct usb_otg *otg = musb->xceiv->otg; -#endif - irqreturn_t handled = IRQ_NONE; - - dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl, - int_usb); - -#ifndef __UBOOT__ - /* in host mode, the peripheral may issue remote wakeup. - * in peripheral mode, the host may resume the link. - * spurious RESUME irqs happen too, paired with SUSPEND. - */ - if (int_usb & MUSB_INTR_RESUME) { - handled = IRQ_HANDLED; - dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state)); - - if (devctl & MUSB_DEVCTL_HM) { - void __iomem *mbase = musb->mregs; - - switch (musb->xceiv->state) { - case OTG_STATE_A_SUSPEND: - /* remote wakeup? later, GetPortStatus - * will stop RESUME signaling - */ - - if (power & MUSB_POWER_SUSPENDM) { - /* spurious */ - musb->int_usb &= ~MUSB_INTR_SUSPEND; - dev_dbg(musb->controller, "Spurious SUSPENDM\n"); - break; - } - - power &= ~MUSB_POWER_SUSPENDM; - musb_writeb(mbase, MUSB_POWER, - power | MUSB_POWER_RESUME); - - musb->port1_status |= - (USB_PORT_STAT_C_SUSPEND << 16) - | MUSB_PORT_STAT_RESUME; - musb->rh_timer = jiffies - + msecs_to_jiffies(20); - - musb->xceiv->state = OTG_STATE_A_HOST; - musb->is_active = 1; - usb_hcd_resume_root_hub(musb_to_hcd(musb)); - break; - case OTG_STATE_B_WAIT_ACON: - musb->xceiv->state = OTG_STATE_B_PERIPHERAL; - musb->is_active = 1; - MUSB_DEV_MODE(musb); - break; - default: - WARNING("bogus %s RESUME (%s)\n", - "host", - otg_state_string(musb->xceiv->state)); - } - } else { - switch (musb->xceiv->state) { - case OTG_STATE_A_SUSPEND: - /* possibly DISCONNECT is upcoming */ - musb->xceiv->state = OTG_STATE_A_HOST; - usb_hcd_resume_root_hub(musb_to_hcd(musb)); - break; - case OTG_STATE_B_WAIT_ACON: - case OTG_STATE_B_PERIPHERAL: - /* disconnect while suspended? we may - * not get a disconnect irq... - */ - if ((devctl & MUSB_DEVCTL_VBUS) - != (3 << MUSB_DEVCTL_VBUS_SHIFT) - ) { - musb->int_usb |= MUSB_INTR_DISCONNECT; - musb->int_usb &= ~MUSB_INTR_SUSPEND; - break; - } - musb_g_resume(musb); - break; - case OTG_STATE_B_IDLE: - musb->int_usb &= ~MUSB_INTR_SUSPEND; - break; - default: - WARNING("bogus %s RESUME (%s)\n", - "peripheral", - otg_state_string(musb->xceiv->state)); - } - } - } - - /* see manual for the order of the tests */ - if (int_usb & MUSB_INTR_SESSREQ) { - void __iomem *mbase = musb->mregs; - - if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS - && (devctl & MUSB_DEVCTL_BDEVICE)) { - dev_dbg(musb->controller, "SessReq while on B state\n"); - return IRQ_HANDLED; - } - - dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n", - otg_state_string(musb->xceiv->state)); - - /* IRQ arrives from ID pin sense or (later, if VBUS power - * is removed) SRP. responses are time critical: - * - turn on VBUS (with silicon-specific mechanism) - * - go through A_WAIT_VRISE - * - ... to A_WAIT_BCON. - * a_wait_vrise_tmout triggers VBUS_ERROR transitions - */ - musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); - musb->ep0_stage = MUSB_EP0_START; - musb->xceiv->state = OTG_STATE_A_IDLE; - MUSB_HST_MODE(musb); - musb_platform_set_vbus(musb, 1); - - handled = IRQ_HANDLED; - } - - if (int_usb & MUSB_INTR_VBUSERROR) { - int ignore = 0; - - /* During connection as an A-Device, we may see a short - * current spikes causing voltage drop, because of cable - * and peripheral capacitance combined with vbus draw. - * (So: less common with truly self-powered devices, where - * vbus doesn't act like a power supply.) - * - * Such spikes are short; usually less than ~500 usec, max - * of ~2 msec. That is, they're not sustained overcurrent - * errors, though they're reported using VBUSERROR irqs. - * - * Workarounds: (a) hardware: use self powered devices. - * (b) software: ignore non-repeated VBUS errors. - * - * REVISIT: do delays from lots of DEBUG_KERNEL checks - * make trouble here, keeping VBUS < 4.4V ? - */ - switch (musb->xceiv->state) { - case OTG_STATE_A_HOST: - /* recovery is dicey once we've gotten past the - * initial stages of enumeration, but if VBUS - * stayed ok at the other end of the link, and - * another reset is due (at least for high speed, - * to redo the chirp etc), it might work OK... - */ - case OTG_STATE_A_WAIT_BCON: - case OTG_STATE_A_WAIT_VRISE: - if (musb->vbuserr_retry) { - void __iomem *mbase = musb->mregs; - - musb->vbuserr_retry--; - ignore = 1; - devctl |= MUSB_DEVCTL_SESSION; - musb_writeb(mbase, MUSB_DEVCTL, devctl); - } else { - musb->port1_status |= - USB_PORT_STAT_OVERCURRENT - | (USB_PORT_STAT_C_OVERCURRENT << 16); - } - break; - default: - break; - } - - dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", - otg_state_string(musb->xceiv->state), - devctl, - ({ char *s; - switch (devctl & MUSB_DEVCTL_VBUS) { - case 0 << MUSB_DEVCTL_VBUS_SHIFT: - s = "<SessEnd"; break; - case 1 << MUSB_DEVCTL_VBUS_SHIFT: - s = "<AValid"; break; - case 2 << MUSB_DEVCTL_VBUS_SHIFT: - s = "<VBusValid"; break; - /* case 3 << MUSB_DEVCTL_VBUS_SHIFT: */ - default: - s = "VALID"; break; - }; s; }), - VBUSERR_RETRY_COUNT - musb->vbuserr_retry, - musb->port1_status); - - /* go through A_WAIT_VFALL then start a new session */ - if (!ignore) - musb_platform_set_vbus(musb, 0); - handled = IRQ_HANDLED; - } - - if (int_usb & MUSB_INTR_SUSPEND) { - dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x power %02x\n", - otg_state_string(musb->xceiv->state), devctl, power); - handled = IRQ_HANDLED; - - switch (musb->xceiv->state) { - case OTG_STATE_A_PERIPHERAL: - /* We also come here if the cable is removed, since - * this silicon doesn't report ID-no-longer-grounded. - * - * We depend on T(a_wait_bcon) to shut us down, and - * hope users don't do anything dicey during this - * undesired detour through A_WAIT_BCON. - */ - musb_hnp_stop(musb); - usb_hcd_resume_root_hub(musb_to_hcd(musb)); - musb_root_disconnect(musb); - musb_platform_try_idle(musb, jiffies - + msecs_to_jiffies(musb->a_wait_bcon - ? : OTG_TIME_A_WAIT_BCON)); - - break; - case OTG_STATE_B_IDLE: - if (!musb->is_active) - break; - case OTG_STATE_B_PERIPHERAL: - musb_g_suspend(musb); - musb->is_active = is_otg_enabled(musb) - && otg->gadget->b_hnp_enable; - if (musb->is_active) { - musb->xceiv->state = OTG_STATE_B_WAIT_ACON; - dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n"); - mod_timer(&musb->otg_timer, jiffies - + msecs_to_jiffies( - OTG_TIME_B_ASE0_BRST)); - } - break; - case OTG_STATE_A_WAIT_BCON: - if (musb->a_wait_bcon != 0) - musb_platform_try_idle(musb, jiffies - + msecs_to_jiffies(musb->a_wait_bcon)); - break; - case OTG_STATE_A_HOST: - musb->xceiv->state = OTG_STATE_A_SUSPEND; - musb->is_active = is_otg_enabled(musb) - && otg->host->b_hnp_enable; - break; - case OTG_STATE_B_HOST: - /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ - dev_dbg(musb->controller, "REVISIT: SUSPEND as B_HOST\n"); - break; - default: - /* "should not happen" */ - musb->is_active = 0; - break; - } - } -#endif - - if (int_usb & MUSB_INTR_CONNECT) { - struct usb_hcd *hcd = musb_to_hcd(musb); - - handled = IRQ_HANDLED; - musb->is_active = 1; - - musb->ep0_stage = MUSB_EP0_START; - - /* flush endpoints when transitioning from Device Mode */ - if (is_peripheral_active(musb)) { - /* REVISIT HNP; just force disconnect */ - } - musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask); - musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe); - musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); -#ifndef __UBOOT__ - musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED - |USB_PORT_STAT_HIGH_SPEED - |USB_PORT_STAT_ENABLE - ); - musb->port1_status |= USB_PORT_STAT_CONNECTION - |(USB_PORT_STAT_C_CONNECTION << 16); - - /* high vs full speed is just a guess until after reset */ - if (devctl & MUSB_DEVCTL_LSDEV) - musb->port1_status |= USB_PORT_STAT_LOW_SPEED; - - /* indicate new connection to OTG machine */ - switch (musb->xceiv->state) { - case OTG_STATE_B_PERIPHERAL: - if (int_usb & MUSB_INTR_SUSPEND) { - dev_dbg(musb->controller, "HNP: SUSPEND+CONNECT, now b_host\n"); - int_usb &= ~MUSB_INTR_SUSPEND; - goto b_host; - } else - dev_dbg(musb->controller, "CONNECT as b_peripheral???\n"); - break; - case OTG_STATE_B_WAIT_ACON: - dev_dbg(musb->controller, "HNP: CONNECT, now b_host\n"); -b_host: - musb->xceiv->state = OTG_STATE_B_HOST; - hcd->self.is_b_host = 1; - musb->ignore_disconnect = 0; - del_timer(&musb->otg_timer); - break; - default: - if ((devctl & MUSB_DEVCTL_VBUS) - == (3 << MUSB_DEVCTL_VBUS_SHIFT)) { - musb->xceiv->state = OTG_STATE_A_HOST; - hcd->self.is_b_host = 0; - } - break; - } - - /* poke the root hub */ - MUSB_HST_MODE(musb); - if (hcd->status_urb) - usb_hcd_poll_rh_status(hcd); - else - usb_hcd_resume_root_hub(hcd); - - dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n", - otg_state_string(musb->xceiv->state), devctl); -#endif - } - -#ifndef __UBOOT__ - if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) { - dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n", - otg_state_string(musb->xceiv->state), - MUSB_MODE(musb), devctl); - handled = IRQ_HANDLED; - - switch (musb->xceiv->state) { - case OTG_STATE_A_HOST: - case OTG_STATE_A_SUSPEND: - usb_hcd_resume_root_hub(musb_to_hcd(musb)); - musb_root_disconnect(musb); - if (musb->a_wait_bcon != 0 && is_otg_enabled(musb)) - musb_platform_try_idle(musb, jiffies - + msecs_to_jiffies(musb->a_wait_bcon)); - break; - case OTG_STATE_B_HOST: - /* REVISIT this behaves for "real disconnect" - * cases; make sure the other transitions from - * from B_HOST act right too. The B_HOST code - * in hnp_stop() is currently not used... - */ - musb_root_disconnect(musb); - musb_to_hcd(musb)->self.is_b_host = 0; - musb->xceiv->state = OTG_STATE_B_PERIPHERAL; - MUSB_DEV_MODE(musb); - musb_g_disconnect(musb); - break; - case OTG_STATE_A_PERIPHERAL: - musb_hnp_stop(musb); - musb_root_disconnect(musb); - /* FALLTHROUGH */ - case OTG_STATE_B_WAIT_ACON: - /* FALLTHROUGH */ - case OTG_STATE_B_PERIPHERAL: - case OTG_STATE_B_IDLE: - musb_g_disconnect(musb); - break; - default: - WARNING("unhandled DISCONNECT transition (%s)\n", - otg_state_string(musb->xceiv->state)); - break; - } - } - - /* mentor saves a bit: bus reset and babble share the same irq. - * only host sees babble; only peripheral sees bus reset. - */ - if (int_usb & MUSB_INTR_RESET) { - handled = IRQ_HANDLED; - if (is_host_capable() && (devctl & MUSB_DEVCTL_HM) != 0) { - /* - * Looks like non-HS BABBLE can be ignored, but - * HS BABBLE is an error condition. For HS the solution - * is to avoid babble in the first place and fix what - * caused BABBLE. When HS BABBLE happens we can only - * stop the session. - */ - if (devctl & (MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV)) - dev_dbg(musb->controller, "BABBLE devctl: %02x\n", devctl); - else { - ERR("Stopping host session -- babble\n"); - musb_writeb(musb->mregs, MUSB_DEVCTL, 0); - } - } else if (is_peripheral_capable()) { - dev_dbg(musb->controller, "BUS RESET as %s\n", - otg_state_string(musb->xceiv->state)); - switch (musb->xceiv->state) { - case OTG_STATE_A_SUSPEND: - /* We need to ignore disconnect on suspend - * otherwise tusb 2.0 won't reconnect after a - * power cycle, which breaks otg compliance. - */ - musb->ignore_disconnect = 1; - musb_g_reset(musb); - /* FALLTHROUGH */ - case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ - /* never use invalid T(a_wait_bcon) */ - dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n", - otg_state_string(musb->xceiv->state), - TA_WAIT_BCON(musb)); - mod_timer(&musb->otg_timer, jiffies - + msecs_to_jiffies(TA_WAIT_BCON(musb))); - break; - case OTG_STATE_A_PERIPHERAL: - musb->ignore_disconnect = 0; - del_timer(&musb->otg_timer); - musb_g_reset(musb); - break; - case OTG_STATE_B_WAIT_ACON: - dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n", - otg_state_string(musb->xceiv->state)); - musb->xceiv->state = OTG_STATE_B_PERIPHERAL; - musb_g_reset(musb); - break; - case OTG_STATE_B_IDLE: - musb->xceiv->state = OTG_STATE_B_PERIPHERAL; - /* FALLTHROUGH */ - case OTG_STATE_B_PERIPHERAL: - musb_g_reset(musb); - break; - default: - dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n", - otg_state_string(musb->xceiv->state)); - } - } - } -#endif - -#if 0 -/* REVISIT ... this would be for multiplexing periodic endpoints, or - * supporting transfer phasing to prevent exceeding ISO bandwidth - * limits of a given frame or microframe. - * - * It's not needed for peripheral side, which dedicates endpoints; - * though it _might_ use SOF irqs for other purposes. - * - * And it's not currently needed for host side, which also dedicates - * endpoints, relies on TX/RX interval registers, and isn't claimed - * to support ISO transfers yet. - */ - if (int_usb & MUSB_INTR_SOF) { - void __iomem *mbase = musb->mregs; - struct musb_hw_ep *ep; - u8 epnum; - u16 frame; - - dev_dbg(musb->controller, "START_OF_FRAME\n"); - handled = IRQ_HANDLED; - - /* start any periodic Tx transfers waiting for current frame */ - frame = musb_readw(mbase, MUSB_FRAME); - ep = musb->endpoints; - for (epnum = 1; (epnum < musb->nr_endpoints) - && (musb->epmask >= (1 << epnum)); - epnum++, ep++) { - /* - * FIXME handle framecounter wraps (12 bits) - * eliminate duplicated StartUrb logic - */ - if (ep->dwWaitFrame >= frame) { - ep->dwWaitFrame = 0; - pr_debug("SOF --> periodic TX%s on %d\n", - ep->tx_channel ? " DMA" : "", - epnum); - if (!ep->tx_channel) - musb_h_tx_start(musb, epnum); - else - cppi_hostdma_start(musb, epnum); - } - } /* end of for loop */ - } -#endif - - schedule_work(&musb->irq_work); - - return handled; -} - -/*-------------------------------------------------------------------------*/ - -/* -* Program the HDRC to start (enable interrupts, dma, etc.). -*/ -void musb_start(struct musb *musb) -{ - void __iomem *regs = musb->mregs; - u8 devctl = musb_readb(regs, MUSB_DEVCTL); - - dev_dbg(musb->controller, "<== devctl %02x\n", devctl); - - /* Set INT enable registers, enable interrupts */ - musb_writew(regs, MUSB_INTRTXE, musb->epmask); - musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe); - musb_writeb(regs, MUSB_INTRUSBE, 0xf7); - - musb_writeb(regs, MUSB_TESTMODE, 0); - - /* put into basic highspeed mode and start session */ - musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE -#ifdef CONFIG_USB_GADGET_DUALSPEED - | MUSB_POWER_HSENAB -#endif - /* ENSUSPEND wedges tusb */ - /* | MUSB_POWER_ENSUSPEND */ - ); - - musb->is_active = 0; - devctl = musb_readb(regs, MUSB_DEVCTL); - devctl &= ~MUSB_DEVCTL_SESSION; - - if (is_otg_enabled(musb)) { -#ifndef __UBOOT__ - /* session started after: - * (a) ID-grounded irq, host mode; - * (b) vbus present/connect IRQ, peripheral mode; - * (c) peripheral initiates, using SRP - */ - if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) - musb->is_active = 1; - else - devctl |= MUSB_DEVCTL_SESSION; -#endif - - } else if (is_host_enabled(musb)) { - /* assume ID pin is hard-wired to ground */ - devctl |= MUSB_DEVCTL_SESSION; - - } else /* peripheral is enabled */ { - if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) - musb->is_active = 1; - } - musb_platform_enable(musb); - musb_writeb(regs, MUSB_DEVCTL, devctl); -} - - -static void musb_generic_disable(struct musb *musb) -{ - void __iomem *mbase = musb->mregs; - u16 temp; - - /* disable interrupts */ - musb_writeb(mbase, MUSB_INTRUSBE, 0); - musb_writew(mbase, MUSB_INTRTXE, 0); - musb_writew(mbase, MUSB_INTRRXE, 0); - - /* off */ - musb_writeb(mbase, MUSB_DEVCTL, 0); - - /* flush pending interrupts */ - temp = musb_readb(mbase, MUSB_INTRUSB); - temp = musb_readw(mbase, MUSB_INTRTX); - temp = musb_readw(mbase, MUSB_INTRRX); - -} - -/* - * Make the HDRC stop (disable interrupts, etc.); - * reversible by musb_start - * called on gadget driver unregister - * with controller locked, irqs blocked - * acts as a NOP unless some role activated the hardware - */ -void musb_stop(struct musb *musb) -{ - /* stop IRQs, timers, ... */ - musb_platform_disable(musb); - musb_generic_disable(musb); - dev_dbg(musb->controller, "HDRC disabled\n"); - - /* FIXME - * - mark host and/or peripheral drivers unusable/inactive - * - disable DMA (and enable it in HdrcStart) - * - make sure we can musb_start() after musb_stop(); with - * OTG mode, gadget driver module rmmod/modprobe cycles that - * - ... - */ - musb_platform_try_idle(musb, 0); -} - -#ifndef __UBOOT__ -static void musb_shutdown(struct platform_device *pdev) -{ - struct musb *musb = dev_to_musb(&pdev->dev); - unsigned long flags; - - pm_runtime_get_sync(musb->controller); - - musb_gadget_cleanup(musb); - - spin_lock_irqsave(&musb->lock, flags); - musb_platform_disable(musb); - musb_generic_disable(musb); - spin_unlock_irqrestore(&musb->lock, flags); - - if (!is_otg_enabled(musb) && is_host_enabled(musb)) - usb_remove_hcd(musb_to_hcd(musb)); - musb_writeb(musb->mregs, MUSB_DEVCTL, 0); - musb_platform_exit(musb); - - pm_runtime_put(musb->controller); - /* FIXME power down */ -} -#endif - - -/*-------------------------------------------------------------------------*/ - -/* - * The silicon either has hard-wired endpoint configurations, or else - * "dynamic fifo" sizing. The driver has support for both, though at this - * writing only the dynamic sizing is very well tested. Since we switched - * away from compile-time hardware parameters, we can no longer rely on - * dead code elimination to leave only the relevant one in the object file. - * - * We don't currently use dynamic fifo setup capability to do anything - * more than selecting one of a bunch of predefined configurations. - */ -#if defined(CONFIG_USB_MUSB_TUSB6010) \ - || defined(CONFIG_USB_MUSB_TUSB6010_MODULE) \ - || defined(CONFIG_USB_MUSB_OMAP2PLUS) \ - || defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE) \ - || defined(CONFIG_USB_MUSB_AM35X) \ - || defined(CONFIG_USB_MUSB_AM35X_MODULE) \ - || defined(CONFIG_USB_MUSB_DSPS) \ - || defined(CONFIG_USB_MUSB_DSPS_MODULE) -static ushort __devinitdata fifo_mode = 4; -#elif defined(CONFIG_USB_MUSB_UX500) \ - || defined(CONFIG_USB_MUSB_UX500_MODULE) -static ushort __devinitdata fifo_mode = 5; -#else -static ushort __devinitdata fifo_mode = 2; -#endif - -/* "modprobe ... fifo_mode=1" etc */ -module_param(fifo_mode, ushort, 0); -MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration"); - -/* - * tables defining fifo_mode values. define more if you like. - * for host side, make sure both halves of ep1 are set up. - */ - -/* mode 0 - fits in 2KB */ -static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = { -{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, }, -{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, -{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, -}; - -/* mode 1 - fits in 4KB */ -static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = { -{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, -{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, -{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, }, -{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, -{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, -}; - -/* mode 2 - fits in 4KB */ -static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = { -{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, -{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, -}; - -/* mode 3 - fits in 4KB */ -static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = { -{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, -{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, -{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, -{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, -}; - -/* mode 4 - fits in 16KB */ -static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = { -{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 256, }, -{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 64, }, -{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 256, }, -{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 64, }, -{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 256, }, -{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 64, }, -{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 4096, }, -{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, }, -{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, -}; - -/* mode 5 - fits in 8KB */ -static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = { -{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 32, }, -{ .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 32, }, -{ .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 32, }, -{ .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 32, }, -{ .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 32, }, -{ .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 32, }, -{ .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 32, }, -{ .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 32, }, -{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 32, }, -{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 32, }, -{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 32, }, -{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 32, }, -{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 32, }, -{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 32, }, -{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 512, }, -{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, }, -{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, -}; - -/* - * configure a fifo; for non-shared endpoints, this may be called - * once for a tx fifo and once for an rx fifo. - * - * returns negative errno or offset for next fifo. - */ -static int __devinit -fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep, - const struct musb_fifo_cfg *cfg, u16 offset) -{ - void __iomem *mbase = musb->mregs; - int size = 0; - u16 maxpacket = cfg->maxpacket; - u16 c_off = offset >> 3; - u8 c_size; - - /* expect hw_ep has already been zero-initialized */ - - size = ffs(max(maxpacket, (u16) 8)) - 1; - maxpacket = 1 << size; - - c_size = size - 3; - if (cfg->mode == BUF_DOUBLE) { - if ((offset + (maxpacket << 1)) > - (1 << (musb->config->ram_bits + 2))) - return -EMSGSIZE; - c_size |= MUSB_FIFOSZ_DPB; - } else { - if ((offset + maxpacket) > (1 << (musb->config->ram_bits + 2))) - return -EMSGSIZE; - } - - /* configure the FIFO */ - musb_writeb(mbase, MUSB_INDEX, hw_ep->epnum); - - /* EP0 reserved endpoint for control, bidirectional; - * EP1 reserved for bulk, two unidirection halves. - */ - if (hw_ep->epnum == 1) - musb->bulk_ep = hw_ep; - /* REVISIT error check: be sure ep0 can both rx and tx ... */ - switch (cfg->style) { - case FIFO_TX: - musb_write_txfifosz(mbase, c_size); - musb_write_txfifoadd(mbase, c_off); - hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); - hw_ep->max_packet_sz_tx = maxpacket; - break; - case FIFO_RX: - musb_write_rxfifosz(mbase, c_size); - musb_write_rxfifoadd(mbase, c_off); - hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); - hw_ep->max_packet_sz_rx = maxpacket; - break; - case FIFO_RXTX: - musb_write_txfifosz(mbase, c_size); - musb_write_txfifoadd(mbase, c_off); - hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); - hw_ep->max_packet_sz_rx = maxpacket; - - musb_write_rxfifosz(mbase, c_size); - musb_write_rxfifoadd(mbase, c_off); - hw_ep->tx_double_buffered = hw_ep->rx_double_buffered; - hw_ep->max_packet_sz_tx = maxpacket; - - hw_ep->is_shared_fifo = true; - break; - } - - /* NOTE rx and tx endpoint irqs aren't managed separately, - * which happens to be ok - */ - musb->epmask |= (1 << hw_ep->epnum); - - return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0)); -} - -static struct musb_fifo_cfg __devinitdata ep0_cfg = { - .style = FIFO_RXTX, .maxpacket = 64, -}; - -static int __devinit ep_config_from_table(struct musb *musb) -{ - const struct musb_fifo_cfg *cfg; - unsigned i, n; - int offset; - struct musb_hw_ep *hw_ep = musb->endpoints; - - if (musb->config->fifo_cfg) { - cfg = musb->config->fifo_cfg; - n = musb->config->fifo_cfg_size; - goto done; - } - - switch (fifo_mode) { - default: - fifo_mode = 0; - /* FALLTHROUGH */ - case 0: - cfg = mode_0_cfg; - n = ARRAY_SIZE(mode_0_cfg); - break; - case 1: - cfg = mode_1_cfg; - n = ARRAY_SIZE(mode_1_cfg); - break; - case 2: - cfg = mode_2_cfg; - n = ARRAY_SIZE(mode_2_cfg); - break; - case 3: - cfg = mode_3_cfg; - n = ARRAY_SIZE(mode_3_cfg); - break; - case 4: - cfg = mode_4_cfg; - n = ARRAY_SIZE(mode_4_cfg); - break; - case 5: - cfg = mode_5_cfg; - n = ARRAY_SIZE(mode_5_cfg); - break; - } - - pr_debug("%s: setup fifo_mode %d\n", musb_driver_name, fifo_mode); - -done: - offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0); - /* assert(offset > 0) */ - - /* NOTE: for RTL versions >= 1.400 EPINFO and RAMINFO would - * be better than static musb->config->num_eps and DYN_FIFO_SIZE... - */ - - for (i = 0; i < n; i++) { - u8 epn = cfg->hw_ep_num; - - if (epn >= musb->config->num_eps) { - pr_debug("%s: invalid ep %d\n", - musb_driver_name, epn); - return -EINVAL; - } - offset = fifo_setup(musb, hw_ep + epn, cfg++, offset); - if (offset < 0) { - pr_debug("%s: mem overrun, ep %d\n", - musb_driver_name, epn); - return -EINVAL; - } - epn++; - musb->nr_endpoints = max(epn, musb->nr_endpoints); - } - - pr_debug("%s: %d/%d max ep, %d/%d memory\n", musb_driver_name, n + 1, - musb->config->num_eps * 2 - 1, offset, - (1 << (musb->config->ram_bits + 2))); - - if (!musb->bulk_ep) { - pr_debug("%s: missing bulk\n", musb_driver_name); - return -EINVAL; - } - - return 0; -} - - -/* - * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false - * @param musb the controller - */ -static int __devinit ep_config_from_hw(struct musb *musb) -{ - u8 epnum = 0; - struct musb_hw_ep *hw_ep; - void *mbase = musb->mregs; - int ret = 0; - - dev_dbg(musb->controller, "<== static silicon ep config\n"); - - /* FIXME pick up ep0 maxpacket size */ - - for (epnum = 1; epnum < musb->config->num_eps; epnum++) { - musb_ep_select(mbase, epnum); - hw_ep = musb->endpoints + epnum; - - ret = musb_read_fifosize(musb, hw_ep, epnum); - if (ret < 0) - break; - - /* FIXME set up hw_ep->{rx,tx}_double_buffered */ - - /* pick an RX/TX endpoint for bulk */ - if (hw_ep->max_packet_sz_tx < 512 - || hw_ep->max_packet_sz_rx < 512) - continue; - - /* REVISIT: this algorithm is lazy, we should at least - * try to pick a double buffered endpoint. - */ - if (musb->bulk_ep) - continue; - musb->bulk_ep = hw_ep; - } - - if (!musb->bulk_ep) { - pr_debug("%s: missing bulk\n", musb_driver_name); - return -EINVAL; - } - - return 0; -} - -enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, }; - -/* Initialize MUSB (M)HDRC part of the USB hardware subsystem; - * configure endpoints, or take their config from silicon - */ -static int __devinit musb_core_init(u16 musb_type, struct musb *musb) -{ - u8 reg; - char *type; - char aInfo[90], aRevision[32], aDate[12]; - void __iomem *mbase = musb->mregs; - int status = 0; - int i; - - /* log core options (read using indexed model) */ - reg = musb_read_configdata(mbase); - - strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8"); - if (reg & MUSB_CONFIGDATA_DYNFIFO) { - strcat(aInfo, ", dyn FIFOs"); - musb->dyn_fifo = true; - } -#ifndef CONFIG_MUSB_DISABLE_BULK_COMBINE_SPLIT - if (reg & MUSB_CONFIGDATA_MPRXE) { - strcat(aInfo, ", bulk combine"); - musb->bulk_combine = true; - } - if (reg & MUSB_CONFIGDATA_MPTXE) { - strcat(aInfo, ", bulk split"); - musb->bulk_split = true; - } -#else - musb->bulk_combine = false; - musb->bulk_split = false; -#endif - if (reg & MUSB_CONFIGDATA_HBRXE) { - strcat(aInfo, ", HB-ISO Rx"); - musb->hb_iso_rx = true; - } - if (reg & MUSB_CONFIGDATA_HBTXE) { - strcat(aInfo, ", HB-ISO Tx"); - musb->hb_iso_tx = true; - } - if (reg & MUSB_CONFIGDATA_SOFTCONE) - strcat(aInfo, ", SoftConn"); - - pr_debug("%s:ConfigData=0x%02x (%s)\n", musb_driver_name, reg, aInfo); - - aDate[0] = 0; - if (MUSB_CONTROLLER_MHDRC == musb_type) { - musb->is_multipoint = 1; - type = "M"; - } else { - musb->is_multipoint = 0; - type = ""; -#ifndef CONFIG_USB_OTG_BLACKLIST_HUB - printk(KERN_ERR - "%s: kernel must blacklist external hubs\n", - musb_driver_name); -#endif - } - - /* log release info */ - musb->hwvers = musb_read_hwvers(mbase); - snprintf(aRevision, 32, "%d.%d%s", MUSB_HWVERS_MAJOR(musb->hwvers), - MUSB_HWVERS_MINOR(musb->hwvers), - (musb->hwvers & MUSB_HWVERS_RC) ? "RC" : ""); - pr_debug("%s: %sHDRC RTL version %s %s\n", musb_driver_name, type, - aRevision, aDate); - - /* configure ep0 */ - musb_configure_ep0(musb); - - /* discover endpoint configuration */ - musb->nr_endpoints = 1; - musb->epmask = 1; - - if (musb->dyn_fifo) - status = ep_config_from_table(musb); - else - status = ep_config_from_hw(musb); - - if (status < 0) - return status; - - /* finish init, and print endpoint config */ - for (i = 0; i < musb->nr_endpoints; i++) { - struct musb_hw_ep *hw_ep = musb->endpoints + i; - - hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase; -#if defined(CONFIG_USB_MUSB_TUSB6010) || defined (CONFIG_USB_MUSB_TUSB6010_MODULE) - hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i); - hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i); - hw_ep->fifo_sync_va = - musb->sync_va + 0x400 + MUSB_FIFO_OFFSET(i); - - if (i == 0) - hw_ep->conf = mbase - 0x400 + TUSB_EP0_CONF; - else - hw_ep->conf = mbase + 0x400 + (((i - 1) & 0xf) << 2); -#endif - - hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase; - hw_ep->target_regs = musb_read_target_reg_base(i, mbase); - hw_ep->rx_reinit = 1; - hw_ep->tx_reinit = 1; - - if (hw_ep->max_packet_sz_tx) { - dev_dbg(musb->controller, - "%s: hw_ep %d%s, %smax %d\n", - musb_driver_name, i, - hw_ep->is_shared_fifo ? "shared" : "tx", - hw_ep->tx_double_buffered - ? "doublebuffer, " : "", - hw_ep->max_packet_sz_tx); - } - if (hw_ep->max_packet_sz_rx && !hw_ep->is_shared_fifo) { - dev_dbg(musb->controller, - "%s: hw_ep %d%s, %smax %d\n", - musb_driver_name, i, - "rx", - hw_ep->rx_double_buffered - ? "doublebuffer, " : "", - hw_ep->max_packet_sz_rx); - } - if (!(hw_ep->max_packet_sz_tx || hw_ep->max_packet_sz_rx)) - dev_dbg(musb->controller, "hw_ep %d not configured\n", i); - } - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \ - defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) - -static irqreturn_t generic_interrupt(int irq, void *__hci) -{ - unsigned long flags; - irqreturn_t retval = IRQ_NONE; - struct musb *musb = __hci; - - spin_lock_irqsave(&musb->lock, flags); - - musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); - musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); - musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); - - if (musb->int_usb || musb->int_tx || musb->int_rx) - retval = musb_interrupt(musb); - - spin_unlock_irqrestore(&musb->lock, flags); - - return retval; -} - -#else -#define generic_interrupt NULL -#endif - -/* - * handle all the irqs defined by the HDRC core. for now we expect: other - * irq sources (phy, dma, etc) will be handled first, musb->int_* values - * will be assigned, and the irq will already have been acked. - * - * called in irq context with spinlock held, irqs blocked - */ -irqreturn_t musb_interrupt(struct musb *musb) -{ - irqreturn_t retval = IRQ_NONE; - u8 devctl, power; - int ep_num; - u32 reg; - - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - power = musb_readb(musb->mregs, MUSB_POWER); - - dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n", - (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral", - musb->int_usb, musb->int_tx, musb->int_rx); - - /* the core can interrupt us for multiple reasons; docs have - * a generic interrupt flowchart to follow - */ - if (musb->int_usb) - retval |= musb_stage0_irq(musb, musb->int_usb, - devctl, power); - - /* "stage 1" is handling endpoint irqs */ - - /* handle endpoint 0 first */ - if (musb->int_tx & 1) { - if (devctl & MUSB_DEVCTL_HM) { - if (is_host_capable()) - retval |= musb_h_ep0_irq(musb); - } else { - if (is_peripheral_capable()) - retval |= musb_g_ep0_irq(musb); - } - } - - /* RX on endpoints 1-15 */ - reg = musb->int_rx >> 1; - ep_num = 1; - while (reg) { - if (reg & 1) { - /* musb_ep_select(musb->mregs, ep_num); */ - /* REVISIT just retval = ep->rx_irq(...) */ - retval = IRQ_HANDLED; - if (devctl & MUSB_DEVCTL_HM) { - if (is_host_capable()) - musb_host_rx(musb, ep_num); - } else { - if (is_peripheral_capable()) - musb_g_rx(musb, ep_num); - } - } - - reg >>= 1; - ep_num++; - } - - /* TX on endpoints 1-15 */ - reg = musb->int_tx >> 1; - ep_num = 1; - while (reg) { - if (reg & 1) { - /* musb_ep_select(musb->mregs, ep_num); */ - /* REVISIT just retval |= ep->tx_irq(...) */ - retval = IRQ_HANDLED; - if (devctl & MUSB_DEVCTL_HM) { - if (is_host_capable()) - musb_host_tx(musb, ep_num); - } else { - if (is_peripheral_capable()) - musb_g_tx(musb, ep_num); - } - } - reg >>= 1; - ep_num++; - } - - return retval; -} -EXPORT_SYMBOL_GPL(musb_interrupt); - -#ifndef CONFIG_MUSB_PIO_ONLY -static bool __devinitdata use_dma = 1; - -/* "modprobe ... use_dma=0" etc */ -module_param(use_dma, bool, 0); -MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); - -void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit) -{ - u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - - /* called with controller lock already held */ - - if (!epnum) { -#ifndef CONFIG_USB_TUSB_OMAP_DMA - if (!is_cppi_enabled()) { - /* endpoint 0 */ - if (devctl & MUSB_DEVCTL_HM) - musb_h_ep0_irq(musb); - else - musb_g_ep0_irq(musb); - } -#endif - } else { - /* endpoints 1..15 */ - if (transmit) { - if (devctl & MUSB_DEVCTL_HM) { - if (is_host_capable()) - musb_host_tx(musb, epnum); - } else { - if (is_peripheral_capable()) - musb_g_tx(musb, epnum); - } - } else { - /* receive */ - if (devctl & MUSB_DEVCTL_HM) { - if (is_host_capable()) - musb_host_rx(musb, epnum); - } else { - if (is_peripheral_capable()) - musb_g_rx(musb, epnum); - } - } - } -} -EXPORT_SYMBOL_GPL(musb_dma_completion); - -#else -#define use_dma 0 -#endif - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_SYSFS - -static ssize_t -musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct musb *musb = dev_to_musb(dev); - unsigned long flags; - int ret = -EINVAL; - - spin_lock_irqsave(&musb->lock, flags); - ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state)); - spin_unlock_irqrestore(&musb->lock, flags); - - return ret; -} - -static ssize_t -musb_mode_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t n) -{ - struct musb *musb = dev_to_musb(dev); - unsigned long flags; - int status; - - spin_lock_irqsave(&musb->lock, flags); - if (sysfs_streq(buf, "host")) - status = musb_platform_set_mode(musb, MUSB_HOST); - else if (sysfs_streq(buf, "peripheral")) - status = musb_platform_set_mode(musb, MUSB_PERIPHERAL); - else if (sysfs_streq(buf, "otg")) - status = musb_platform_set_mode(musb, MUSB_OTG); - else - status = -EINVAL; - spin_unlock_irqrestore(&musb->lock, flags); - - return (status == 0) ? n : status; -} -static DEVICE_ATTR(mode, 0644, musb_mode_show, musb_mode_store); - -static ssize_t -musb_vbus_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t n) -{ - struct musb *musb = dev_to_musb(dev); - unsigned long flags; - unsigned long val; - - if (sscanf(buf, "%lu", &val) < 1) { - dev_err(dev, "Invalid VBUS timeout ms value\n"); - return -EINVAL; - } - - spin_lock_irqsave(&musb->lock, flags); - /* force T(a_wait_bcon) to be zero/unlimited *OR* valid */ - musb->a_wait_bcon = val ? max_t(int, val, OTG_TIME_A_WAIT_BCON) : 0 ; - if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON) - musb->is_active = 0; - musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val)); - spin_unlock_irqrestore(&musb->lock, flags); - - return n; -} - -static ssize_t -musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct musb *musb = dev_to_musb(dev); - unsigned long flags; - unsigned long val; - int vbus; - - spin_lock_irqsave(&musb->lock, flags); - val = musb->a_wait_bcon; - /* FIXME get_vbus_status() is normally #defined as false... - * and is effectively TUSB-specific. - */ - vbus = musb_platform_get_vbus_status(musb); - spin_unlock_irqrestore(&musb->lock, flags); - - return sprintf(buf, "Vbus %s, timeout %lu msec\n", - vbus ? "on" : "off", val); -} -static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store); - -/* Gadget drivers can't know that a host is connected so they might want - * to start SRP, but users can. This allows userspace to trigger SRP. - */ -static ssize_t -musb_srp_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t n) -{ - struct musb *musb = dev_to_musb(dev); - unsigned short srp; - - if (sscanf(buf, "%hu", &srp) != 1 - || (srp != 1)) { - dev_err(dev, "SRP: Value must be 1\n"); - return -EINVAL; - } - - if (srp == 1) - musb_g_wakeup(musb); - - return n; -} -static DEVICE_ATTR(srp, 0644, NULL, musb_srp_store); - -static struct attribute *musb_attributes[] = { - &dev_attr_mode.attr, - &dev_attr_vbus.attr, - &dev_attr_srp.attr, - NULL -}; - -static const struct attribute_group musb_attr_group = { - .attrs = musb_attributes, -}; - -#endif /* sysfs */ - -#ifndef __UBOOT__ -/* Only used to provide driver mode change events */ -static void musb_irq_work(struct work_struct *data) -{ - struct musb *musb = container_of(data, struct musb, irq_work); - static int old_state; - - if (musb->xceiv->state != old_state) { - old_state = musb->xceiv->state; - sysfs_notify(&musb->controller->kobj, NULL, "mode"); - } -} -#endif - -/* -------------------------------------------------------------------------- - * Init support - */ - -static struct musb *__devinit -allocate_instance(struct device *dev, - struct musb_hdrc_config *config, void __iomem *mbase) -{ - struct musb *musb; - struct musb_hw_ep *ep; - int epnum; -#ifndef __UBOOT__ - struct usb_hcd *hcd; - - hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev)); - if (!hcd) - return NULL; - /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */ - - musb = hcd_to_musb(hcd); -#else - musb = calloc(1, sizeof(*musb)); - if (!musb) - return NULL; -#endif - INIT_LIST_HEAD(&musb->control); - INIT_LIST_HEAD(&musb->in_bulk); - INIT_LIST_HEAD(&musb->out_bulk); - -#ifndef __UBOOT__ - hcd->uses_new_polling = 1; - hcd->has_tt = 1; -#endif - - musb->vbuserr_retry = VBUSERR_RETRY_COUNT; - musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON; - dev_set_drvdata(dev, musb); - musb->mregs = mbase; - musb->ctrl_base = mbase; - musb->nIrq = -ENODEV; - musb->config = config; - BUG_ON(musb->config->num_eps > MUSB_C_NUM_EPS); - for (epnum = 0, ep = musb->endpoints; - epnum < musb->config->num_eps; - epnum++, ep++) { - ep->musb = musb; - ep->epnum = epnum; - } - - musb->controller = dev; - - return musb; -} - -static void musb_free(struct musb *musb) -{ - /* this has multiple entry modes. it handles fault cleanup after - * probe(), where things may be partially set up, as well as rmmod - * cleanup after everything's been de-activated. - */ - -#ifdef CONFIG_SYSFS - sysfs_remove_group(&musb->controller->kobj, &musb_attr_group); -#endif - - if (musb->nIrq >= 0) { - if (musb->irq_wake) - disable_irq_wake(musb->nIrq); - free_irq(musb->nIrq, musb); - } - if (is_dma_capable() && musb->dma_controller) { - struct dma_controller *c = musb->dma_controller; - - (void) c->stop(c); - dma_controller_destroy(c); - } - - kfree(musb); -} - -/* - * Perform generic per-controller initialization. - * - * @pDevice: the controller (already clocked, etc) - * @nIrq: irq - * @mregs: virtual address of controller registers, - * not yet corrected for platform-specific offsets - */ -#ifndef __UBOOT__ -static int __devinit -musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) -#else -struct musb * -musb_init_controller(struct musb_hdrc_platform_data *plat, struct device *dev, - void *ctrl) -#endif -{ - int status; - struct musb *musb; -#ifndef __UBOOT__ - struct musb_hdrc_platform_data *plat = dev->platform_data; -#else - int nIrq = 0; -#endif - - /* The driver might handle more features than the board; OK. - * Fail when the board needs a feature that's not enabled. - */ - if (!plat) { - dev_dbg(dev, "no platform_data?\n"); - status = -ENODEV; - goto fail0; - } - - /* allocate */ - musb = allocate_instance(dev, plat->config, ctrl); - if (!musb) { - status = -ENOMEM; - goto fail0; - } - - pm_runtime_use_autosuspend(musb->controller); - pm_runtime_set_autosuspend_delay(musb->controller, 200); - pm_runtime_enable(musb->controller); - - spin_lock_init(&musb->lock); - musb->board_mode = plat->mode; - musb->board_set_power = plat->set_power; - musb->min_power = plat->min_power; - musb->ops = plat->platform_ops; - - /* The musb_platform_init() call: - * - adjusts musb->mregs and musb->isr if needed, - * - may initialize an integrated tranceiver - * - initializes musb->xceiv, usually by otg_get_phy() - * - stops powering VBUS - * - * There are various transceiver configurations. Blackfin, - * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses - * external/discrete ones in various flavors (twl4030 family, - * isp1504, non-OTG, etc) mostly hooking up through ULPI. - */ - musb->isr = generic_interrupt; - status = musb_platform_init(musb); - if (status < 0) - goto fail1; - - if (!musb->isr) { - status = -ENODEV; - goto fail2; - } - -#ifndef __UBOOT__ - if (!musb->xceiv->io_ops) { - musb->xceiv->io_dev = musb->controller; - musb->xceiv->io_priv = musb->mregs; - musb->xceiv->io_ops = &musb_ulpi_access; - } -#endif - - pm_runtime_get_sync(musb->controller); - -#ifndef CONFIG_MUSB_PIO_ONLY - if (use_dma && dev->dma_mask) { - struct dma_controller *c; - - c = dma_controller_create(musb, musb->mregs); - musb->dma_controller = c; - if (c) - (void) c->start(c); - } -#endif -#ifndef __UBOOT__ - /* ideally this would be abstracted in platform setup */ - if (!is_dma_capable() || !musb->dma_controller) - dev->dma_mask = NULL; -#endif - - /* be sure interrupts are disabled before connecting ISR */ - musb_platform_disable(musb); - musb_generic_disable(musb); - - /* setup musb parts of the core (especially endpoints) */ - status = musb_core_init(plat->config->multipoint - ? MUSB_CONTROLLER_MHDRC - : MUSB_CONTROLLER_HDRC, musb); - if (status < 0) - goto fail3; - - setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb); - - /* Init IRQ workqueue before request_irq */ - INIT_WORK(&musb->irq_work, musb_irq_work); - - /* attach to the IRQ */ - if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) { - dev_err(dev, "request_irq %d failed!\n", nIrq); - status = -ENODEV; - goto fail3; - } - musb->nIrq = nIrq; -/* FIXME this handles wakeup irqs wrong */ - if (enable_irq_wake(nIrq) == 0) { - musb->irq_wake = 1; - device_init_wakeup(dev, 1); - } else { - musb->irq_wake = 0; - } - -#ifndef __UBOOT__ - /* host side needs more setup */ - if (is_host_enabled(musb)) { - struct usb_hcd *hcd = musb_to_hcd(musb); - - otg_set_host(musb->xceiv->otg, &hcd->self); - - if (is_otg_enabled(musb)) - hcd->self.otg_port = 1; - musb->xceiv->otg->host = &hcd->self; - hcd->power_budget = 2 * (plat->power ? : 250); - - /* program PHY to use external vBus if required */ - if (plat->extvbus) { - u8 busctl = musb_read_ulpi_buscontrol(musb->mregs); - busctl |= MUSB_ULPI_USE_EXTVBUS; - musb_write_ulpi_buscontrol(musb->mregs, busctl); - } - } -#endif - - /* For the host-only role, we can activate right away. - * (We expect the ID pin to be forcibly grounded!!) - * Otherwise, wait till the gadget driver hooks up. - */ - if (!is_otg_enabled(musb) && is_host_enabled(musb)) { - struct usb_hcd *hcd = musb_to_hcd(musb); - - MUSB_HST_MODE(musb); -#ifndef __UBOOT__ - musb->xceiv->otg->default_a = 1; - musb->xceiv->state = OTG_STATE_A_IDLE; - - status = usb_add_hcd(musb_to_hcd(musb), 0, 0); - - hcd->self.uses_pio_for_control = 1; - dev_dbg(musb->controller, "%s mode, status %d, devctl %02x %c\n", - "HOST", status, - musb_readb(musb->mregs, MUSB_DEVCTL), - (musb_readb(musb->mregs, MUSB_DEVCTL) - & MUSB_DEVCTL_BDEVICE - ? 'B' : 'A')); -#endif - - } else /* peripheral is enabled */ { - MUSB_DEV_MODE(musb); -#ifndef __UBOOT__ - musb->xceiv->otg->default_a = 0; - musb->xceiv->state = OTG_STATE_B_IDLE; -#endif - - if (is_peripheral_capable()) - status = musb_gadget_setup(musb); - -#ifndef __UBOOT__ - dev_dbg(musb->controller, "%s mode, status %d, dev%02x\n", - is_otg_enabled(musb) ? "OTG" : "PERIPHERAL", - status, - musb_readb(musb->mregs, MUSB_DEVCTL)); -#endif - - } - if (status < 0) - goto fail3; - - status = musb_init_debugfs(musb); - if (status < 0) - goto fail4; - -#ifdef CONFIG_SYSFS - status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); - if (status) - goto fail5; -#endif - - pm_runtime_put(musb->controller); - - pr_debug("USB %s mode controller at %p using %s, IRQ %d\n", - ({char *s; - switch (musb->board_mode) { - case MUSB_HOST: s = "Host"; break; - case MUSB_PERIPHERAL: s = "Peripheral"; break; - default: s = "OTG"; break; - }; s; }), - ctrl, - (is_dma_capable() && musb->dma_controller) - ? "DMA" : "PIO", - musb->nIrq); - -#ifndef __UBOOT__ - return 0; -#else - return status == 0 ? musb : NULL; -#endif - -fail5: - musb_exit_debugfs(musb); - -fail4: -#ifndef __UBOOT__ - if (!is_otg_enabled(musb) && is_host_enabled(musb)) - usb_remove_hcd(musb_to_hcd(musb)); - else -#endif - musb_gadget_cleanup(musb); - -fail3: - pm_runtime_put_sync(musb->controller); - -fail2: - if (musb->irq_wake) - device_init_wakeup(dev, 0); - musb_platform_exit(musb); - -fail1: - dev_err(musb->controller, - "musb_init_controller failed with status %d\n", status); - - musb_free(musb); - -fail0: - -#ifndef __UBOOT__ - return status; -#else - return status == 0 ? musb : NULL; -#endif - -} - -/*-------------------------------------------------------------------------*/ - -/* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just - * bridge to a platform device; this driver then suffices. - */ - -#ifndef CONFIG_MUSB_PIO_ONLY -static u64 *orig_dma_mask; -#endif - -#ifndef __UBOOT__ -static int __devinit musb_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - int irq = platform_get_irq_byname(pdev, "mc"); - int status; - struct resource *iomem; - void __iomem *base; - - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iomem || irq <= 0) - return -ENODEV; - - base = ioremap(iomem->start, resource_size(iomem)); - if (!base) { - dev_err(dev, "ioremap failed\n"); - return -ENOMEM; - } - -#ifndef CONFIG_MUSB_PIO_ONLY - /* clobbered by use_dma=n */ - orig_dma_mask = dev->dma_mask; -#endif - status = musb_init_controller(dev, irq, base); - if (status < 0) - iounmap(base); - - return status; -} - -static int __devexit musb_remove(struct platform_device *pdev) -{ - struct musb *musb = dev_to_musb(&pdev->dev); - void __iomem *ctrl_base = musb->ctrl_base; - - /* this gets called on rmmod. - * - Host mode: host may still be active - * - Peripheral mode: peripheral is deactivated (or never-activated) - * - OTG mode: both roles are deactivated (or never-activated) - */ - musb_exit_debugfs(musb); - musb_shutdown(pdev); - - musb_free(musb); - iounmap(ctrl_base); - device_init_wakeup(&pdev->dev, 0); -#ifndef CONFIG_MUSB_PIO_ONLY - pdev->dev.dma_mask = orig_dma_mask; -#endif - return 0; -} - -#ifdef CONFIG_PM - -static void musb_save_context(struct musb *musb) -{ - int i; - void __iomem *musb_base = musb->mregs; - void __iomem *epio; - - if (is_host_enabled(musb)) { - musb->context.frame = musb_readw(musb_base, MUSB_FRAME); - musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE); - musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs); - } - musb->context.power = musb_readb(musb_base, MUSB_POWER); - musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); - musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE); - musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); - musb->context.index = musb_readb(musb_base, MUSB_INDEX); - musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL); - - for (i = 0; i < musb->config->num_eps; ++i) { - struct musb_hw_ep *hw_ep; - - hw_ep = &musb->endpoints[i]; - if (!hw_ep) - continue; - - epio = hw_ep->regs; - if (!epio) - continue; - - musb_writeb(musb_base, MUSB_INDEX, i); - musb->context.index_regs[i].txmaxp = - musb_readw(epio, MUSB_TXMAXP); - musb->context.index_regs[i].txcsr = - musb_readw(epio, MUSB_TXCSR); - musb->context.index_regs[i].rxmaxp = - musb_readw(epio, MUSB_RXMAXP); - musb->context.index_regs[i].rxcsr = - musb_readw(epio, MUSB_RXCSR); - - if (musb->dyn_fifo) { - musb->context.index_regs[i].txfifoadd = - musb_read_txfifoadd(musb_base); - musb->context.index_regs[i].rxfifoadd = - musb_read_rxfifoadd(musb_base); - musb->context.index_regs[i].txfifosz = - musb_read_txfifosz(musb_base); - musb->context.index_regs[i].rxfifosz = - musb_read_rxfifosz(musb_base); - } - if (is_host_enabled(musb)) { - musb->context.index_regs[i].txtype = - musb_readb(epio, MUSB_TXTYPE); - musb->context.index_regs[i].txinterval = - musb_readb(epio, MUSB_TXINTERVAL); - musb->context.index_regs[i].rxtype = - musb_readb(epio, MUSB_RXTYPE); - musb->context.index_regs[i].rxinterval = - musb_readb(epio, MUSB_RXINTERVAL); - - musb->context.index_regs[i].txfunaddr = - musb_read_txfunaddr(musb_base, i); - musb->context.index_regs[i].txhubaddr = - musb_read_txhubaddr(musb_base, i); - musb->context.index_regs[i].txhubport = - musb_read_txhubport(musb_base, i); - - musb->context.index_regs[i].rxfunaddr = - musb_read_rxfunaddr(musb_base, i); - musb->context.index_regs[i].rxhubaddr = - musb_read_rxhubaddr(musb_base, i); - musb->context.index_regs[i].rxhubport = - musb_read_rxhubport(musb_base, i); - } - } -} - -static void musb_restore_context(struct musb *musb) -{ - int i; - void __iomem *musb_base = musb->mregs; - void __iomem *ep_target_regs; - void __iomem *epio; - - if (is_host_enabled(musb)) { - musb_writew(musb_base, MUSB_FRAME, musb->context.frame); - musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); - musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); - } - musb_writeb(musb_base, MUSB_POWER, musb->context.power); - musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe); - musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe); - musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe); - musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl); - - for (i = 0; i < musb->config->num_eps; ++i) { - struct musb_hw_ep *hw_ep; - - hw_ep = &musb->endpoints[i]; - if (!hw_ep) - continue; - - epio = hw_ep->regs; - if (!epio) - continue; - - musb_writeb(musb_base, MUSB_INDEX, i); - musb_writew(epio, MUSB_TXMAXP, - musb->context.index_regs[i].txmaxp); - musb_writew(epio, MUSB_TXCSR, - musb->context.index_regs[i].txcsr); - musb_writew(epio, MUSB_RXMAXP, - musb->context.index_regs[i].rxmaxp); - musb_writew(epio, MUSB_RXCSR, - musb->context.index_regs[i].rxcsr); - - if (musb->dyn_fifo) { - musb_write_txfifosz(musb_base, - musb->context.index_regs[i].txfifosz); - musb_write_rxfifosz(musb_base, - musb->context.index_regs[i].rxfifosz); - musb_write_txfifoadd(musb_base, - musb->context.index_regs[i].txfifoadd); - musb_write_rxfifoadd(musb_base, - musb->context.index_regs[i].rxfifoadd); - } - - if (is_host_enabled(musb)) { - musb_writeb(epio, MUSB_TXTYPE, - musb->context.index_regs[i].txtype); - musb_writeb(epio, MUSB_TXINTERVAL, - musb->context.index_regs[i].txinterval); - musb_writeb(epio, MUSB_RXTYPE, - musb->context.index_regs[i].rxtype); - musb_writeb(epio, MUSB_RXINTERVAL, - - musb->context.index_regs[i].rxinterval); - musb_write_txfunaddr(musb_base, i, - musb->context.index_regs[i].txfunaddr); - musb_write_txhubaddr(musb_base, i, - musb->context.index_regs[i].txhubaddr); - musb_write_txhubport(musb_base, i, - musb->context.index_regs[i].txhubport); - - ep_target_regs = - musb_read_target_reg_base(i, musb_base); - - musb_write_rxfunaddr(ep_target_regs, - musb->context.index_regs[i].rxfunaddr); - musb_write_rxhubaddr(ep_target_regs, - musb->context.index_regs[i].rxhubaddr); - musb_write_rxhubport(ep_target_regs, - musb->context.index_regs[i].rxhubport); - } - } - musb_writeb(musb_base, MUSB_INDEX, musb->context.index); -} - -static int musb_suspend(struct device *dev) -{ - struct musb *musb = dev_to_musb(dev); - unsigned long flags; - - spin_lock_irqsave(&musb->lock, flags); - - if (is_peripheral_active(musb)) { - /* FIXME force disconnect unless we know USB will wake - * the system up quickly enough to respond ... - */ - } else if (is_host_active(musb)) { - /* we know all the children are suspended; sometimes - * they will even be wakeup-enabled. - */ - } - - spin_unlock_irqrestore(&musb->lock, flags); - return 0; -} - -static int musb_resume_noirq(struct device *dev) -{ - /* for static cmos like DaVinci, register values were preserved - * unless for some reason the whole soc powered down or the USB - * module got reset through the PSC (vs just being disabled). - */ - return 0; -} - -static int musb_runtime_suspend(struct device *dev) -{ - struct musb *musb = dev_to_musb(dev); - - musb_save_context(musb); - - return 0; -} - -static int musb_runtime_resume(struct device *dev) -{ - struct musb *musb = dev_to_musb(dev); - static int first = 1; - - /* - * When pm_runtime_get_sync called for the first time in driver - * init, some of the structure is still not initialized which is - * used in restore function. But clock needs to be - * enabled before any register access, so - * pm_runtime_get_sync has to be called. - * Also context restore without save does not make - * any sense - */ - if (!first) - musb_restore_context(musb); - first = 0; - - return 0; -} - -static const struct dev_pm_ops musb_dev_pm_ops = { - .suspend = musb_suspend, - .resume_noirq = musb_resume_noirq, - .runtime_suspend = musb_runtime_suspend, - .runtime_resume = musb_runtime_resume, -}; - -#define MUSB_DEV_PM_OPS (&musb_dev_pm_ops) -#else -#define MUSB_DEV_PM_OPS NULL -#endif - -static struct platform_driver musb_driver = { - .driver = { - .name = (char *)musb_driver_name, - .bus = &platform_bus_type, - .owner = THIS_MODULE, - .pm = MUSB_DEV_PM_OPS, - }, - .probe = musb_probe, - .remove = __devexit_p(musb_remove), - .shutdown = musb_shutdown, -}; - -/*-------------------------------------------------------------------------*/ - -static int __init musb_init(void) -{ - if (usb_disabled()) - return 0; - - pr_info("%s: version " MUSB_VERSION ", " - "?dma?" - ", " - "otg (peripheral+host)", - musb_driver_name); - return platform_driver_register(&musb_driver); -} -module_init(musb_init); - -static void __exit musb_cleanup(void) -{ - platform_driver_unregister(&musb_driver); -} -module_exit(musb_cleanup); -#endif diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_core.h b/qemu/roms/u-boot/drivers/usb/musb-new/musb_core.h deleted file mode 100644 index 269574209..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_core.h +++ /dev/null @@ -1,623 +0,0 @@ -/* - * MUSB OTG driver defines - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __MUSB_CORE_H__ -#define __MUSB_CORE_H__ - -#ifndef __UBOOT__ -#include <linux/slab.h> -#include <linux/list.h> -#include <linux/interrupt.h> -#include <linux/errno.h> -#include <linux/timer.h> -#include <linux/device.h> -#include <linux/usb.h> -#include <linux/usb/otg.h> -#else -#include <asm/errno.h> -#endif -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <linux/usb/musb.h> - -struct musb; -struct musb_hw_ep; -struct musb_ep; - -/* Helper defines for struct musb->hwvers */ -#define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f) -#define MUSB_HWVERS_MINOR(x) (x & 0x3ff) -#define MUSB_HWVERS_RC 0x8000 -#define MUSB_HWVERS_1300 0x52C -#define MUSB_HWVERS_1400 0x590 -#define MUSB_HWVERS_1800 0x720 -#define MUSB_HWVERS_1900 0x784 -#define MUSB_HWVERS_2000 0x800 - -#include "musb_debug.h" -#include "musb_dma.h" - -#include "musb_io.h" -#include "musb_regs.h" - -#include "musb_gadget.h" -#ifndef __UBOOT__ -#include <linux/usb/hcd.h> -#endif -#include "musb_host.h" - -#define is_peripheral_enabled(musb) ((musb)->board_mode != MUSB_HOST) -#define is_host_enabled(musb) ((musb)->board_mode != MUSB_PERIPHERAL) -#define is_otg_enabled(musb) ((musb)->board_mode == MUSB_OTG) - -/* NOTE: otg and peripheral-only state machines start at B_IDLE. - * OTG or host-only go to A_IDLE when ID is sensed. - */ -#define is_peripheral_active(m) (!(m)->is_host) -#define is_host_active(m) ((m)->is_host) - -#ifdef CONFIG_PROC_FS -#include <linux/fs.h> -#define MUSB_CONFIG_PROC_FS -#endif - -/****************************** PERIPHERAL ROLE *****************************/ - -#ifndef __UBOOT__ -#define is_peripheral_capable() (1) -#else -#ifdef CONFIG_MUSB_GADGET -#define is_peripheral_capable() (1) -#else -#define is_peripheral_capable() (0) -#endif -#endif - -extern irqreturn_t musb_g_ep0_irq(struct musb *); -extern void musb_g_tx(struct musb *, u8); -extern void musb_g_rx(struct musb *, u8); -extern void musb_g_reset(struct musb *); -extern void musb_g_suspend(struct musb *); -extern void musb_g_resume(struct musb *); -extern void musb_g_wakeup(struct musb *); -extern void musb_g_disconnect(struct musb *); - -/****************************** HOST ROLE ***********************************/ - -#ifndef __UBOOT__ -#define is_host_capable() (1) -#else -#ifdef CONFIG_MUSB_HOST -#define is_host_capable() (1) -#else -#define is_host_capable() (0) -#endif -#endif - -extern irqreturn_t musb_h_ep0_irq(struct musb *); -extern void musb_host_tx(struct musb *, u8); -extern void musb_host_rx(struct musb *, u8); - -/****************************** CONSTANTS ********************************/ - -#ifndef MUSB_C_NUM_EPS -#define MUSB_C_NUM_EPS ((u8)16) -#endif - -#ifndef MUSB_MAX_END0_PACKET -#define MUSB_MAX_END0_PACKET ((u16)MUSB_EP0_FIFOSIZE) -#endif - -/* host side ep0 states */ -enum musb_h_ep0_state { - MUSB_EP0_IDLE, - MUSB_EP0_START, /* expect ack of setup */ - MUSB_EP0_IN, /* expect IN DATA */ - MUSB_EP0_OUT, /* expect ack of OUT DATA */ - MUSB_EP0_STATUS, /* expect ack of STATUS */ -} __attribute__ ((packed)); - -/* peripheral side ep0 states */ -enum musb_g_ep0_state { - MUSB_EP0_STAGE_IDLE, /* idle, waiting for SETUP */ - MUSB_EP0_STAGE_SETUP, /* received SETUP */ - MUSB_EP0_STAGE_TX, /* IN data */ - MUSB_EP0_STAGE_RX, /* OUT data */ - MUSB_EP0_STAGE_STATUSIN, /* (after OUT data) */ - MUSB_EP0_STAGE_STATUSOUT, /* (after IN data) */ - MUSB_EP0_STAGE_ACKWAIT, /* after zlp, before statusin */ -} __attribute__ ((packed)); - -/* - * OTG protocol constants. See USB OTG 1.3 spec, - * sections 5.5 "Device Timings" and 6.6.5 "Timers". - */ -#define OTG_TIME_A_WAIT_VRISE 100 /* msec (max) */ -#define OTG_TIME_A_WAIT_BCON 1100 /* min 1 second */ -#define OTG_TIME_A_AIDL_BDIS 200 /* min 200 msec */ -#define OTG_TIME_B_ASE0_BRST 100 /* min 3.125 ms */ - - -/*************************** REGISTER ACCESS ********************************/ - -/* Endpoint registers (other than dynfifo setup) can be accessed either - * directly with the "flat" model, or after setting up an index register. - */ - -#if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_SOC_OMAP2430) \ - || defined(CONFIG_SOC_OMAP3430) || defined(CONFIG_BLACKFIN) \ - || defined(CONFIG_ARCH_OMAP4) -/* REVISIT indexed access seemed to - * misbehave (on DaVinci) for at least peripheral IN ... - */ -#define MUSB_FLAT_REG -#endif - -/* TUSB mapping: "flat" plus ep0 special cases */ -#if defined(CONFIG_USB_MUSB_TUSB6010) || \ - defined(CONFIG_USB_MUSB_TUSB6010_MODULE) -#define musb_ep_select(_mbase, _epnum) \ - musb_writeb((_mbase), MUSB_INDEX, (_epnum)) -#define MUSB_EP_OFFSET MUSB_TUSB_OFFSET - -/* "flat" mapping: each endpoint has its own i/o address */ -#elif defined(MUSB_FLAT_REG) -#define musb_ep_select(_mbase, _epnum) (((void)(_mbase)), ((void)(_epnum))) -#define MUSB_EP_OFFSET MUSB_FLAT_OFFSET - -/* "indexed" mapping: INDEX register controls register bank select */ -#else -#define musb_ep_select(_mbase, _epnum) \ - musb_writeb((_mbase), MUSB_INDEX, (_epnum)) -#define MUSB_EP_OFFSET MUSB_INDEXED_OFFSET -#endif - -/****************************** FUNCTIONS ********************************/ - -#define MUSB_HST_MODE(_musb)\ - { (_musb)->is_host = true; } -#define MUSB_DEV_MODE(_musb) \ - { (_musb)->is_host = false; } - -#define test_devctl_hst_mode(_x) \ - (musb_readb((_x)->mregs, MUSB_DEVCTL)&MUSB_DEVCTL_HM) - -#define MUSB_MODE(musb) ((musb)->is_host ? "Host" : "Peripheral") - -/******************************** TYPES *************************************/ - -/** - * struct musb_platform_ops - Operations passed to musb_core by HW glue layer - * @init: turns on clocks, sets up platform-specific registers, etc - * @exit: undoes @init - * @set_mode: forcefully changes operating mode - * @try_ilde: tries to idle the IP - * @vbus_status: returns vbus status if possible - * @set_vbus: forces vbus status - * @adjust_channel_params: pre check for standard dma channel_program func - */ -struct musb_platform_ops { - int (*init)(struct musb *musb); - int (*exit)(struct musb *musb); - - void (*enable)(struct musb *musb); - void (*disable)(struct musb *musb); - - int (*set_mode)(struct musb *musb, u8 mode); - void (*try_idle)(struct musb *musb, unsigned long timeout); - - int (*vbus_status)(struct musb *musb); - void (*set_vbus)(struct musb *musb, int on); - - int (*adjust_channel_params)(struct dma_channel *channel, - u16 packet_sz, u8 *mode, - dma_addr_t *dma_addr, u32 *len); -}; - -/* - * struct musb_hw_ep - endpoint hardware (bidirectional) - * - * Ordered slightly for better cacheline locality. - */ -struct musb_hw_ep { - struct musb *musb; - void __iomem *fifo; - void __iomem *regs; - -#if defined(CONFIG_USB_MUSB_TUSB6010) || \ - defined(CONFIG_USB_MUSB_TUSB6010_MODULE) - void __iomem *conf; -#endif - - /* index in musb->endpoints[] */ - u8 epnum; - - /* hardware configuration, possibly dynamic */ - bool is_shared_fifo; - bool tx_double_buffered; - bool rx_double_buffered; - u16 max_packet_sz_tx; - u16 max_packet_sz_rx; - - struct dma_channel *tx_channel; - struct dma_channel *rx_channel; - -#if defined(CONFIG_USB_MUSB_TUSB6010) || \ - defined(CONFIG_USB_MUSB_TUSB6010_MODULE) - /* TUSB has "asynchronous" and "synchronous" dma modes */ - dma_addr_t fifo_async; - dma_addr_t fifo_sync; - void __iomem *fifo_sync_va; -#endif - - void __iomem *target_regs; - - /* currently scheduled peripheral endpoint */ - struct musb_qh *in_qh; - struct musb_qh *out_qh; - - u8 rx_reinit; - u8 tx_reinit; - - /* peripheral side */ - struct musb_ep ep_in; /* TX */ - struct musb_ep ep_out; /* RX */ -}; - -static inline struct musb_request *next_in_request(struct musb_hw_ep *hw_ep) -{ - return next_request(&hw_ep->ep_in); -} - -static inline struct musb_request *next_out_request(struct musb_hw_ep *hw_ep) -{ - return next_request(&hw_ep->ep_out); -} - -struct musb_csr_regs { - /* FIFO registers */ - u16 txmaxp, txcsr, rxmaxp, rxcsr; - u16 rxfifoadd, txfifoadd; - u8 txtype, txinterval, rxtype, rxinterval; - u8 rxfifosz, txfifosz; - u8 txfunaddr, txhubaddr, txhubport; - u8 rxfunaddr, rxhubaddr, rxhubport; -}; - -struct musb_context_registers { - - u8 power; - u16 intrtxe, intrrxe; - u8 intrusbe; - u16 frame; - u8 index, testmode; - - u8 devctl, busctl, misc; - u32 otg_interfsel; - - struct musb_csr_regs index_regs[MUSB_C_NUM_EPS]; -}; - -/* - * struct musb - Driver instance data. - */ -struct musb { - /* device lock */ - spinlock_t lock; - - const struct musb_platform_ops *ops; - struct musb_context_registers context; - - irqreturn_t (*isr)(int, void *); - struct work_struct irq_work; - u16 hwvers; - -/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ -#define MUSB_PORT_STAT_RESUME (1 << 31) - - u32 port1_status; - - unsigned long rh_timer; - - enum musb_h_ep0_state ep0_stage; - - /* bulk traffic normally dedicates endpoint hardware, and each - * direction has its own ring of host side endpoints. - * we try to progress the transfer at the head of each endpoint's - * queue until it completes or NAKs too much; then we try the next - * endpoint. - */ - struct musb_hw_ep *bulk_ep; - - struct list_head control; /* of musb_qh */ - struct list_head in_bulk; /* of musb_qh */ - struct list_head out_bulk; /* of musb_qh */ - - struct timer_list otg_timer; - struct notifier_block nb; - - struct dma_controller *dma_controller; - - struct device *controller; - void __iomem *ctrl_base; - void __iomem *mregs; - -#if defined(CONFIG_USB_MUSB_TUSB6010) || \ - defined(CONFIG_USB_MUSB_TUSB6010_MODULE) - dma_addr_t async; - dma_addr_t sync; - void __iomem *sync_va; -#endif - - /* passed down from chip/board specific irq handlers */ - u8 int_usb; - u16 int_rx; - u16 int_tx; - - struct usb_phy *xceiv; - - int nIrq; - unsigned irq_wake:1; - - struct musb_hw_ep endpoints[MUSB_C_NUM_EPS]; -#define control_ep endpoints - -#define VBUSERR_RETRY_COUNT 3 - u16 vbuserr_retry; - u16 epmask; - u8 nr_endpoints; - - u8 board_mode; /* enum musb_mode */ - int (*board_set_power)(int state); - - u8 min_power; /* vbus for periph, in mA/2 */ - - bool is_host; - - int a_wait_bcon; /* VBUS timeout in msecs */ - unsigned long idle_timeout; /* Next timeout in jiffies */ - - /* active means connected and not suspended */ - unsigned is_active:1; - - unsigned is_multipoint:1; - unsigned ignore_disconnect:1; /* during bus resets */ - - unsigned hb_iso_rx:1; /* high bandwidth iso rx? */ - unsigned hb_iso_tx:1; /* high bandwidth iso tx? */ - unsigned dyn_fifo:1; /* dynamic FIFO supported? */ - - unsigned bulk_split:1; -#define can_bulk_split(musb,type) \ - (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_split) - - unsigned bulk_combine:1; -#define can_bulk_combine(musb,type) \ - (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine) - - /* is_suspended means USB B_PERIPHERAL suspend */ - unsigned is_suspended:1; - - /* may_wakeup means remote wakeup is enabled */ - unsigned may_wakeup:1; - - /* is_self_powered is reported in device status and the - * config descriptor. is_bus_powered means B_PERIPHERAL - * draws some VBUS current; both can be true. - */ - unsigned is_self_powered:1; - unsigned is_bus_powered:1; - - unsigned set_address:1; - unsigned test_mode:1; - unsigned softconnect:1; - - u8 address; - u8 test_mode_nr; - u16 ackpend; /* ep0 */ - enum musb_g_ep0_state ep0_state; - struct usb_gadget g; /* the gadget */ - struct usb_gadget_driver *gadget_driver; /* its driver */ - - /* - * FIXME: Remove this flag. - * - * This is only added to allow Blackfin to work - * with current driver. For some unknown reason - * Blackfin doesn't work with double buffering - * and that's enabled by default. - * - * We added this flag to forcefully disable double - * buffering until we get it working. - */ - unsigned double_buffer_not_ok:1; - - struct musb_hdrc_config *config; - -#ifdef MUSB_CONFIG_PROC_FS - struct proc_dir_entry *proc_entry; -#endif -}; - -static inline struct musb *gadget_to_musb(struct usb_gadget *g) -{ - return container_of(g, struct musb, g); -} - -#ifdef CONFIG_BLACKFIN -static inline int musb_read_fifosize(struct musb *musb, - struct musb_hw_ep *hw_ep, u8 epnum) -{ - musb->nr_endpoints++; - musb->epmask |= (1 << epnum); - - if (epnum < 5) { - hw_ep->max_packet_sz_tx = 128; - hw_ep->max_packet_sz_rx = 128; - } else { - hw_ep->max_packet_sz_tx = 1024; - hw_ep->max_packet_sz_rx = 1024; - } - hw_ep->is_shared_fifo = false; - - return 0; -} - -static inline void musb_configure_ep0(struct musb *musb) -{ - musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE; - musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; - musb->endpoints[0].is_shared_fifo = true; -} - -#else - -static inline int musb_read_fifosize(struct musb *musb, - struct musb_hw_ep *hw_ep, u8 epnum) -{ - void *mbase = musb->mregs; - u8 reg = 0; - - /* read from core using indexed model */ - reg = musb_readb(mbase, MUSB_EP_OFFSET(epnum, MUSB_FIFOSIZE)); - /* 0's returned when no more endpoints */ - if (!reg) - return -ENODEV; - - musb->nr_endpoints++; - musb->epmask |= (1 << epnum); - - hw_ep->max_packet_sz_tx = 1 << (reg & 0x0f); - - /* shared TX/RX FIFO? */ - if ((reg & 0xf0) == 0xf0) { - hw_ep->max_packet_sz_rx = hw_ep->max_packet_sz_tx; - hw_ep->is_shared_fifo = true; - return 0; - } else { - hw_ep->max_packet_sz_rx = 1 << ((reg & 0xf0) >> 4); - hw_ep->is_shared_fifo = false; - } - - return 0; -} - -static inline void musb_configure_ep0(struct musb *musb) -{ - musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE; - musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; - musb->endpoints[0].is_shared_fifo = true; -} -#endif /* CONFIG_BLACKFIN */ - - -/***************************** Glue it together *****************************/ - -extern const char musb_driver_name[]; - -extern void musb_start(struct musb *musb); -extern void musb_stop(struct musb *musb); - -extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src); -extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst); - -extern void musb_load_testpacket(struct musb *); - -extern irqreturn_t musb_interrupt(struct musb *); - -extern void musb_hnp_stop(struct musb *musb); - -static inline void musb_platform_set_vbus(struct musb *musb, int is_on) -{ - if (musb->ops->set_vbus) - musb->ops->set_vbus(musb, is_on); -} - -static inline void musb_platform_enable(struct musb *musb) -{ - if (musb->ops->enable) - musb->ops->enable(musb); -} - -static inline void musb_platform_disable(struct musb *musb) -{ - if (musb->ops->disable) - musb->ops->disable(musb); -} - -static inline int musb_platform_set_mode(struct musb *musb, u8 mode) -{ - if (!musb->ops->set_mode) - return 0; - - return musb->ops->set_mode(musb, mode); -} - -static inline void musb_platform_try_idle(struct musb *musb, - unsigned long timeout) -{ - if (musb->ops->try_idle) - musb->ops->try_idle(musb, timeout); -} - -static inline int musb_platform_get_vbus_status(struct musb *musb) -{ - if (!musb->ops->vbus_status) - return 0; - - return musb->ops->vbus_status(musb); -} - -static inline int musb_platform_init(struct musb *musb) -{ - if (!musb->ops->init) - return -EINVAL; - - return musb->ops->init(musb); -} - -static inline int musb_platform_exit(struct musb *musb) -{ - if (!musb->ops->exit) - return -EINVAL; - - return musb->ops->exit(musb); -} - -#ifdef __UBOOT__ -struct musb * -musb_init_controller(struct musb_hdrc_platform_data *plat, struct device *dev, - void *ctrl); -#endif -#endif /* __MUSB_CORE_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_debug.h b/qemu/roms/u-boot/drivers/usb/musb-new/musb_debug.h deleted file mode 100644 index 27ba8f799..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_debug.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * MUSB OTG driver debug defines - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __MUSB_LINUX_DEBUG_H__ -#define __MUSB_LINUX_DEBUG_H__ - -#define yprintk(facility, format, args...) \ - do { printk(facility "%s %d: " format , \ - __func__, __LINE__ , ## args); } while (0) -#define WARNING(fmt, args...) yprintk(KERN_WARNING, fmt, ## args) -#define INFO(fmt, args...) yprintk(KERN_INFO, fmt, ## args) -#define ERR(fmt, args...) yprintk(KERN_ERR, fmt, ## args) - -#ifdef CONFIG_DEBUG_FS -int musb_init_debugfs(struct musb *musb); -void musb_exit_debugfs(struct musb *musb); -#else -static inline int musb_init_debugfs(struct musb *musb) -{ - return 0; -} -static inline void musb_exit_debugfs(struct musb *musb) -{ -} -#endif - -#endif /* __MUSB_LINUX_DEBUG_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_dma.h b/qemu/roms/u-boot/drivers/usb/musb-new/musb_dma.h deleted file mode 100644 index 3a97c4e2d..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_dma.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * MUSB OTG driver DMA controller abstraction - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __MUSB_DMA_H__ -#define __MUSB_DMA_H__ - -struct musb_hw_ep; - -/* - * DMA Controller Abstraction - * - * DMA Controllers are abstracted to allow use of a variety of different - * implementations of DMA, as allowed by the Inventra USB cores. On the - * host side, usbcore sets up the DMA mappings and flushes caches; on the - * peripheral side, the gadget controller driver does. Responsibilities - * of a DMA controller driver include: - * - * - Handling the details of moving multiple USB packets - * in cooperation with the Inventra USB core, including especially - * the correct RX side treatment of short packets and buffer-full - * states (both of which terminate transfers). - * - * - Knowing the correlation between dma channels and the - * Inventra core's local endpoint resources and data direction. - * - * - Maintaining a list of allocated/available channels. - * - * - Updating channel status on interrupts, - * whether shared with the Inventra core or separate. - */ - -#define DMA_ADDR_INVALID (~(dma_addr_t)0) - -#ifndef CONFIG_MUSB_PIO_ONLY -#define is_dma_capable() (1) -#else -#define is_dma_capable() (0) -#endif - -#ifdef CONFIG_USB_TI_CPPI_DMA -#define is_cppi_enabled() 1 -#else -#define is_cppi_enabled() 0 -#endif - -#ifdef CONFIG_USB_TUSB_OMAP_DMA -#define tusb_dma_omap() 1 -#else -#define tusb_dma_omap() 0 -#endif - -/* Anomaly 05000456 - USB Receive Interrupt Is Not Generated in DMA Mode 1 - * Only allow DMA mode 1 to be used when the USB will actually generate the - * interrupts we expect. - */ -#ifdef CONFIG_BLACKFIN -# undef USE_MODE1 -# if !ANOMALY_05000456 -# define USE_MODE1 -# endif -#endif - -/* - * DMA channel status ... updated by the dma controller driver whenever that - * status changes, and protected by the overall controller spinlock. - */ -enum dma_channel_status { - /* unallocated */ - MUSB_DMA_STATUS_UNKNOWN, - /* allocated ... but not busy, no errors */ - MUSB_DMA_STATUS_FREE, - /* busy ... transactions are active */ - MUSB_DMA_STATUS_BUSY, - /* transaction(s) aborted due to ... dma or memory bus error */ - MUSB_DMA_STATUS_BUS_ABORT, - /* transaction(s) aborted due to ... core error or USB fault */ - MUSB_DMA_STATUS_CORE_ABORT -}; - -struct dma_controller; - -/** - * struct dma_channel - A DMA channel. - * @private_data: channel-private data - * @max_len: the maximum number of bytes the channel can move in one - * transaction (typically representing many USB maximum-sized packets) - * @actual_len: how many bytes have been transferred - * @status: current channel status (updated e.g. on interrupt) - * @desired_mode: true if mode 1 is desired; false if mode 0 is desired - * - * channels are associated with an endpoint for the duration of at least - * one usb transfer. - */ -struct dma_channel { - void *private_data; - /* FIXME not void* private_data, but a dma_controller * */ - size_t max_len; - size_t actual_len; - enum dma_channel_status status; - bool desired_mode; -}; - -/* - * dma_channel_status - return status of dma channel - * @c: the channel - * - * Returns the software's view of the channel status. If that status is BUSY - * then it's possible that the hardware has completed (or aborted) a transfer, - * so the driver needs to update that status. - */ -static inline enum dma_channel_status -dma_channel_status(struct dma_channel *c) -{ - return (is_dma_capable() && c) ? c->status : MUSB_DMA_STATUS_UNKNOWN; -} - -/** - * struct dma_controller - A DMA Controller. - * @start: call this to start a DMA controller; - * return 0 on success, else negative errno - * @stop: call this to stop a DMA controller - * return 0 on success, else negative errno - * @channel_alloc: call this to allocate a DMA channel - * @channel_release: call this to release a DMA channel - * @channel_abort: call this to abort a pending DMA transaction, - * returning it to FREE (but allocated) state - * - * Controllers manage dma channels. - */ -struct dma_controller { - int (*start)(struct dma_controller *); - int (*stop)(struct dma_controller *); - struct dma_channel *(*channel_alloc)(struct dma_controller *, - struct musb_hw_ep *, u8 is_tx); - void (*channel_release)(struct dma_channel *); - int (*channel_program)(struct dma_channel *channel, - u16 maxpacket, u8 mode, - dma_addr_t dma_addr, - u32 length); - int (*channel_abort)(struct dma_channel *); - int (*is_compatible)(struct dma_channel *channel, - u16 maxpacket, - void *buf, u32 length); -}; - -/* called after channel_program(), may indicate a fault */ -extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit); - - -extern struct dma_controller *__init -dma_controller_create(struct musb *, void __iomem *); - -extern void dma_controller_destroy(struct dma_controller *); - -#endif /* __MUSB_DMA_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_dsps.c b/qemu/roms/u-boot/drivers/usb/musb-new/musb_dsps.c deleted file mode 100644 index 9a03917e8..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_dsps.c +++ /dev/null @@ -1,771 +0,0 @@ -/* - * Texas Instruments DSPS platforms "glue layer" - * - * Copyright (C) 2012, by Texas Instruments - * - * Based on the am35x "glue layer" code. - * - * This file is part of the Inventra Controller Driver for Linux. - * - * The Inventra Controller Driver for Linux is free software; you - * can redistribute it and/or modify it under the terms of the GNU - * General Public License version 2 as published by the Free Software - * Foundation. - * - * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; if not, - * write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * musb_dsps.c will be a common file for all the TI DSPS platforms - * such as dm64x, dm36x, dm35x, da8x, am35x and ti81x. - * For now only ti81x is using this and in future davinci.c, am35x.c - * da8xx.c would be merged to this file after testing. - */ - -#define __UBOOT__ -#ifndef __UBOOT__ -#include <linux/init.h> -#include <linux/io.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/dma-mapping.h> -#include <linux/pm_runtime.h> -#include <linux/module.h> - -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_address.h> - -#include <plat/usb.h> -#else -#include <common.h> -#include <asm/omap_musb.h> -#include "linux-compat.h" -#endif - -#include "musb_core.h" - -/** - * avoid using musb_readx()/musb_writex() as glue layer should not be - * dependent on musb core layer symbols. - */ -static inline u8 dsps_readb(const void __iomem *addr, unsigned offset) - { return __raw_readb(addr + offset); } - -static inline u32 dsps_readl(const void __iomem *addr, unsigned offset) - { return __raw_readl(addr + offset); } - -static inline void dsps_writeb(void __iomem *addr, unsigned offset, u8 data) - { __raw_writeb(data, addr + offset); } - -static inline void dsps_writel(void __iomem *addr, unsigned offset, u32 data) - { __raw_writel(data, addr + offset); } - -/** - * DSPS musb wrapper register offset. - * FIXME: This should be expanded to have all the wrapper registers from TI DSPS - * musb ips. - */ -struct dsps_musb_wrapper { - u16 revision; - u16 control; - u16 status; - u16 eoi; - u16 epintr_set; - u16 epintr_clear; - u16 epintr_status; - u16 coreintr_set; - u16 coreintr_clear; - u16 coreintr_status; - u16 phy_utmi; - u16 mode; - - /* bit positions for control */ - unsigned reset:5; - - /* bit positions for interrupt */ - unsigned usb_shift:5; - u32 usb_mask; - u32 usb_bitmap; - unsigned drvvbus:5; - - unsigned txep_shift:5; - u32 txep_mask; - u32 txep_bitmap; - - unsigned rxep_shift:5; - u32 rxep_mask; - u32 rxep_bitmap; - - /* bit positions for phy_utmi */ - unsigned otg_disable:5; - - /* bit positions for mode */ - unsigned iddig:5; - /* miscellaneous stuff */ - u32 musb_core_offset; - u8 poll_seconds; -}; - -static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = { - .revision = 0x00, - .control = 0x14, - .status = 0x18, - .eoi = 0x24, - .epintr_set = 0x38, - .epintr_clear = 0x40, - .epintr_status = 0x30, - .coreintr_set = 0x3c, - .coreintr_clear = 0x44, - .coreintr_status = 0x34, - .phy_utmi = 0xe0, - .mode = 0xe8, - .reset = 0, - .otg_disable = 21, - .iddig = 8, - .usb_shift = 0, - .usb_mask = 0x1ff, - .usb_bitmap = (0x1ff << 0), - .drvvbus = 8, - .txep_shift = 0, - .txep_mask = 0xffff, - .txep_bitmap = (0xffff << 0), - .rxep_shift = 16, - .rxep_mask = 0xfffe, - .rxep_bitmap = (0xfffe << 16), - .musb_core_offset = 0x400, - .poll_seconds = 2, -}; - -/** - * DSPS glue structure. - */ -struct dsps_glue { - struct device *dev; - struct platform_device *musb; /* child musb pdev */ - const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ - struct timer_list timer; /* otg_workaround timer */ -}; - -/** - * dsps_musb_enable - enable interrupts - */ -static void dsps_musb_enable(struct musb *musb) -{ -#ifndef __UBOOT__ - struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); - const struct dsps_musb_wrapper *wrp = glue->wrp; -#else - const struct dsps_musb_wrapper *wrp = &ti81xx_driver_data; -#endif - void __iomem *reg_base = musb->ctrl_base; - u32 epmask, coremask; - - /* Workaround: setup IRQs through both register sets. */ - epmask = ((musb->epmask & wrp->txep_mask) << wrp->txep_shift) | - ((musb->epmask & wrp->rxep_mask) << wrp->rxep_shift); - coremask = (wrp->usb_bitmap & ~MUSB_INTR_SOF); - - dsps_writel(reg_base, wrp->epintr_set, epmask); - dsps_writel(reg_base, wrp->coreintr_set, coremask); - /* Force the DRVVBUS IRQ so we can start polling for ID change. */ -#ifndef __UBOOT__ - if (is_otg_enabled(musb)) - dsps_writel(reg_base, wrp->coreintr_set, - (1 << wrp->drvvbus) << wrp->usb_shift); -#endif -} - -/** - * dsps_musb_disable - disable HDRC and flush interrupts - */ -static void dsps_musb_disable(struct musb *musb) -{ -#ifndef __UBOOT__ - struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); - const struct dsps_musb_wrapper *wrp = glue->wrp; - void __iomem *reg_base = musb->ctrl_base; - - dsps_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap); - dsps_writel(reg_base, wrp->epintr_clear, - wrp->txep_bitmap | wrp->rxep_bitmap); - dsps_writeb(musb->mregs, MUSB_DEVCTL, 0); - dsps_writel(reg_base, wrp->eoi, 0); -#endif -} - -#ifndef __UBOOT__ -static void otg_timer(unsigned long _musb) -{ - struct musb *musb = (void *)_musb; - void __iomem *mregs = musb->mregs; - struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); - const struct dsps_musb_wrapper *wrp = glue->wrp; - u8 devctl; - unsigned long flags; - - /* - * We poll because DSPS IP's won't expose several OTG-critical - * status change events (from the transceiver) otherwise. - */ - devctl = dsps_readb(mregs, MUSB_DEVCTL); - dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, - otg_state_string(musb->xceiv->state)); - - spin_lock_irqsave(&musb->lock, flags); - switch (musb->xceiv->state) { - case OTG_STATE_A_WAIT_BCON: - devctl &= ~MUSB_DEVCTL_SESSION; - dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl); - - devctl = dsps_readb(musb->mregs, MUSB_DEVCTL); - if (devctl & MUSB_DEVCTL_BDEVICE) { - musb->xceiv->state = OTG_STATE_B_IDLE; - MUSB_DEV_MODE(musb); - } else { - musb->xceiv->state = OTG_STATE_A_IDLE; - MUSB_HST_MODE(musb); - } - break; - case OTG_STATE_A_WAIT_VFALL: - musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; - dsps_writel(musb->ctrl_base, wrp->coreintr_set, - MUSB_INTR_VBUSERROR << wrp->usb_shift); - break; - case OTG_STATE_B_IDLE: - if (!is_peripheral_enabled(musb)) - break; - - devctl = dsps_readb(mregs, MUSB_DEVCTL); - if (devctl & MUSB_DEVCTL_BDEVICE) - mod_timer(&glue->timer, - jiffies + wrp->poll_seconds * HZ); - else - musb->xceiv->state = OTG_STATE_A_IDLE; - break; - default: - break; - } - spin_unlock_irqrestore(&musb->lock, flags); -} - -static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) -{ - struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); - static unsigned long last_timer; - - if (!is_otg_enabled(musb)) - return; - - if (timeout == 0) - timeout = jiffies + msecs_to_jiffies(3); - - /* Never idle if active, or when VBUS timeout is not set as host */ - if (musb->is_active || (musb->a_wait_bcon == 0 && - musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { - dev_dbg(musb->controller, "%s active, deleting timer\n", - otg_state_string(musb->xceiv->state)); - del_timer(&glue->timer); - last_timer = jiffies; - return; - } - - if (time_after(last_timer, timeout) && timer_pending(&glue->timer)) { - dev_dbg(musb->controller, - "Longer idle timer already pending, ignoring...\n"); - return; - } - last_timer = timeout; - - dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", - otg_state_string(musb->xceiv->state), - jiffies_to_msecs(timeout - jiffies)); - mod_timer(&glue->timer, timeout); -} -#endif - -static irqreturn_t dsps_interrupt(int irq, void *hci) -{ - struct musb *musb = hci; - void __iomem *reg_base = musb->ctrl_base; -#ifndef __UBOOT__ - struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); - const struct dsps_musb_wrapper *wrp = glue->wrp; -#else - const struct dsps_musb_wrapper *wrp = &ti81xx_driver_data; -#endif - unsigned long flags; - irqreturn_t ret = IRQ_NONE; - u32 epintr, usbintr; - - spin_lock_irqsave(&musb->lock, flags); - - /* Get endpoint interrupts */ - epintr = dsps_readl(reg_base, wrp->epintr_status); - musb->int_rx = (epintr & wrp->rxep_bitmap) >> wrp->rxep_shift; - musb->int_tx = (epintr & wrp->txep_bitmap) >> wrp->txep_shift; - - if (epintr) - dsps_writel(reg_base, wrp->epintr_status, epintr); - - /* Get usb core interrupts */ - usbintr = dsps_readl(reg_base, wrp->coreintr_status); - if (!usbintr && !epintr) - goto eoi; - - musb->int_usb = (usbintr & wrp->usb_bitmap) >> wrp->usb_shift; - if (usbintr) - dsps_writel(reg_base, wrp->coreintr_status, usbintr); - - dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n", - usbintr, epintr); -#ifndef __UBOOT__ - /* - * DRVVBUS IRQs are the only proxy we have (a very poor one!) for - * DSPS IP's missing ID change IRQ. We need an ID change IRQ to - * switch appropriately between halves of the OTG state machine. - * Managing DEVCTL.SESSION per Mentor docs requires that we know its - * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set. - * Also, DRVVBUS pulses for SRP (but not at 5V) ... - */ - if ((usbintr & MUSB_INTR_BABBLE) && is_host_enabled(musb)) - pr_info("CAUTION: musb: Babble Interrupt Occured\n"); - - if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) { - int drvvbus = dsps_readl(reg_base, wrp->status); - void __iomem *mregs = musb->mregs; - u8 devctl = dsps_readb(mregs, MUSB_DEVCTL); - int err; - - err = is_host_enabled(musb) && (musb->int_usb & - MUSB_INTR_VBUSERROR); - if (err) { - /* - * The Mentor core doesn't debounce VBUS as needed - * to cope with device connect current spikes. This - * means it's not uncommon for bus-powered devices - * to get VBUS errors during enumeration. - * - * This is a workaround, but newer RTL from Mentor - * seems to allow a better one: "re"-starting sessions - * without waiting for VBUS to stop registering in - * devctl. - */ - musb->int_usb &= ~MUSB_INTR_VBUSERROR; - musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; - mod_timer(&glue->timer, - jiffies + wrp->poll_seconds * HZ); - WARNING("VBUS error workaround (delay coming)\n"); - } else if (is_host_enabled(musb) && drvvbus) { - musb->is_active = 1; - MUSB_HST_MODE(musb); - musb->xceiv->otg->default_a = 1; - musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; - del_timer(&glue->timer); - } else { - musb->is_active = 0; - MUSB_DEV_MODE(musb); - musb->xceiv->otg->default_a = 0; - musb->xceiv->state = OTG_STATE_B_IDLE; - } - - /* NOTE: this must complete power-on within 100 ms. */ - dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", - drvvbus ? "on" : "off", - otg_state_string(musb->xceiv->state), - err ? " ERROR" : "", - devctl); - ret = IRQ_HANDLED; - } -#endif - - if (musb->int_tx || musb->int_rx || musb->int_usb) - ret |= musb_interrupt(musb); - - eoi: - /* EOI needs to be written for the IRQ to be re-asserted. */ - if (ret == IRQ_HANDLED || epintr || usbintr) - dsps_writel(reg_base, wrp->eoi, 1); - -#ifndef __UBOOT__ - /* Poll for ID change */ - if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) - mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); -#endif - - spin_unlock_irqrestore(&musb->lock, flags); - - return ret; -} - -static int dsps_musb_init(struct musb *musb) -{ -#ifndef __UBOOT__ - struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); - const struct dsps_musb_wrapper *wrp = glue->wrp; - struct omap_musb_board_data *data = plat->board_data; -#else - struct omap_musb_board_data *data = - (struct omap_musb_board_data *)musb->controller; - const struct dsps_musb_wrapper *wrp = &ti81xx_driver_data; -#endif - void __iomem *reg_base = musb->ctrl_base; - u32 rev, val; - int status; - - /* mentor core register starts at offset of 0x400 from musb base */ - musb->mregs += wrp->musb_core_offset; - -#ifndef __UBOOT__ - /* NOP driver needs change if supporting dual instance */ - usb_nop_xceiv_register(); - musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(musb->xceiv)) - return -ENODEV; -#endif - - /* Returns zero if e.g. not clocked */ - rev = dsps_readl(reg_base, wrp->revision); - if (!rev) { - status = -ENODEV; - goto err0; - } - -#ifndef __UBOOT__ - if (is_host_enabled(musb)) - setup_timer(&glue->timer, otg_timer, (unsigned long) musb); -#endif - - /* Reset the musb */ - dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); - - /* Start the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(1); - - musb->isr = dsps_interrupt; - - /* reset the otgdisable bit, needed for host mode to work */ - val = dsps_readl(reg_base, wrp->phy_utmi); - val &= ~(1 << wrp->otg_disable); - dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); - - /* clear level interrupt */ - dsps_writel(reg_base, wrp->eoi, 0); - - return 0; -err0: -#ifndef __UBOOT__ - usb_put_phy(musb->xceiv); - usb_nop_xceiv_unregister(); -#endif - return status; -} - -static int dsps_musb_exit(struct musb *musb) -{ -#ifndef __UBOOT__ - struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); -#else - struct omap_musb_board_data *data = - (struct omap_musb_board_data *)musb->controller; -#endif - -#ifndef __UBOOT__ - if (is_host_enabled(musb)) - del_timer_sync(&glue->timer); -#endif - - /* Shutdown the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(0); - -#ifndef __UBOOT__ - /* NOP driver needs change if supporting dual instance */ - usb_put_phy(musb->xceiv); - usb_nop_xceiv_unregister(); -#endif - - return 0; -} - -#ifndef __UBOOT__ -static struct musb_platform_ops dsps_ops = { -#else -struct musb_platform_ops musb_dsps_ops = { -#endif - .init = dsps_musb_init, - .exit = dsps_musb_exit, - - .enable = dsps_musb_enable, - .disable = dsps_musb_disable, - -#ifndef __UBOOT__ - .try_idle = dsps_musb_try_idle, -#endif -}; - -#ifndef __UBOOT__ -static u64 musb_dmamask = DMA_BIT_MASK(32); -#endif - -#ifndef __UBOOT__ -static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) -{ - struct device *dev = glue->dev; - struct platform_device *pdev = to_platform_device(dev); - struct musb_hdrc_platform_data *pdata = dev->platform_data; - struct platform_device *musb; - struct resource *res; - struct resource resources[2]; - char res_name[10]; - int ret; - - /* get memory resource */ - sprintf(res_name, "musb%d", id); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); - if (!res) { - dev_err(dev, "%s get mem resource failed\n", res_name); - ret = -ENODEV; - goto err0; - } - res->parent = NULL; - resources[0] = *res; - - /* get irq resource */ - sprintf(res_name, "musb%d-irq", id); - res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name); - if (!res) { - dev_err(dev, "%s get irq resource failed\n", res_name); - ret = -ENODEV; - goto err0; - } - res->parent = NULL; - resources[1] = *res; - resources[1].name = "mc"; - - /* allocate the child platform device */ - musb = platform_device_alloc("musb-hdrc", -1); - if (!musb) { - dev_err(dev, "failed to allocate musb device\n"); - ret = -ENOMEM; - goto err0; - } - - musb->dev.parent = dev; - musb->dev.dma_mask = &musb_dmamask; - musb->dev.coherent_dma_mask = musb_dmamask; - - glue->musb = musb; - - pdata->platform_ops = &dsps_ops; - - ret = platform_device_add_resources(musb, resources, 2); - if (ret) { - dev_err(dev, "failed to add resources\n"); - goto err1; - } - - ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); - if (ret) { - dev_err(dev, "failed to add platform_data\n"); - goto err1; - } - - ret = platform_device_add(musb); - if (ret) { - dev_err(dev, "failed to register musb device\n"); - goto err1; - } - - return 0; - -err1: - platform_device_put(musb); -err0: - return ret; -} - -static void __devexit dsps_delete_musb_pdev(struct dsps_glue *glue) -{ - platform_device_del(glue->musb); - platform_device_put(glue->musb); -} - -static int __devinit dsps_probe(struct platform_device *pdev) -{ - const struct platform_device_id *id = platform_get_device_id(pdev); - const struct dsps_musb_wrapper *wrp = - (struct dsps_musb_wrapper *)id->driver_data; - struct dsps_glue *glue; - struct resource *iomem; - int ret; - - /* allocate glue */ - glue = kzalloc(sizeof(*glue), GFP_KERNEL); - if (!glue) { - dev_err(&pdev->dev, "unable to allocate glue memory\n"); - ret = -ENOMEM; - goto err0; - } - - /* get memory resource */ - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iomem) { - dev_err(&pdev->dev, "failed to get usbss mem resourse\n"); - ret = -ENODEV; - goto err1; - } - - glue->dev = &pdev->dev; - - glue->wrp = kmemdup(wrp, sizeof(*wrp), GFP_KERNEL); - if (!glue->wrp) { - dev_err(&pdev->dev, "failed to duplicate wrapper struct memory\n"); - ret = -ENOMEM; - goto err1; - } - platform_set_drvdata(pdev, glue); - - /* enable the usbss clocks */ - pm_runtime_enable(&pdev->dev); - - ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) { - dev_err(&pdev->dev, "pm_runtime_get_sync FAILED"); - goto err2; - } - - /* create the child platform device for first instances of musb */ - ret = dsps_create_musb_pdev(glue, 0); - if (ret != 0) { - dev_err(&pdev->dev, "failed to create child pdev\n"); - goto err3; - } - - return 0; - -err3: - pm_runtime_put(&pdev->dev); -err2: - pm_runtime_disable(&pdev->dev); - kfree(glue->wrp); -err1: - kfree(glue); -err0: - return ret; -} -static int __devexit dsps_remove(struct platform_device *pdev) -{ - struct dsps_glue *glue = platform_get_drvdata(pdev); - - /* delete the child platform device */ - dsps_delete_musb_pdev(glue); - - /* disable usbss clocks */ - pm_runtime_put(&pdev->dev); - pm_runtime_disable(&pdev->dev); - kfree(glue->wrp); - kfree(glue); - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int dsps_suspend(struct device *dev) -{ - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; - - /* Shutdown the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(0); - - return 0; -} - -static int dsps_resume(struct device *dev) -{ - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; - - /* Start the on-chip PHY and its PLL. */ - if (data->set_phy_power) - data->set_phy_power(1); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume); -#endif - -#ifndef __UBOOT__ -static const struct platform_device_id musb_dsps_id_table[] __devinitconst = { - { - .name = "musb-ti81xx", - .driver_data = (kernel_ulong_t) &ti81xx_driver_data, - }, - { }, /* Terminating Entry */ -}; -MODULE_DEVICE_TABLE(platform, musb_dsps_id_table); - -static const struct of_device_id musb_dsps_of_match[] __devinitconst = { - { .compatible = "musb-ti81xx", }, - { .compatible = "ti,ti81xx-musb", }, - { .compatible = "ti,am335x-musb", }, - { }, -}; -MODULE_DEVICE_TABLE(of, musb_dsps_of_match); - -static struct platform_driver dsps_usbss_driver = { - .probe = dsps_probe, - .remove = __devexit_p(dsps_remove), - .driver = { - .name = "musb-dsps", - .pm = &dsps_pm_ops, - .of_match_table = musb_dsps_of_match, - }, - .id_table = musb_dsps_id_table, -}; - -MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer"); -MODULE_AUTHOR("Ravi B <ravibabu@ti.com>"); -MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>"); -MODULE_LICENSE("GPL v2"); - -static int __init dsps_init(void) -{ - return platform_driver_register(&dsps_usbss_driver); -} -subsys_initcall(dsps_init); - -static void __exit dsps_exit(void) -{ - platform_driver_unregister(&dsps_usbss_driver); -} -module_exit(dsps_exit); -#endif diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_gadget.c b/qemu/roms/u-boot/drivers/usb/musb-new/musb_gadget.c deleted file mode 100644 index d2cb91a89..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_gadget.c +++ /dev/null @@ -1,2333 +0,0 @@ -/* - * MUSB OTG driver peripheral support - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * Copyright (C) 2009 MontaVista Software, Inc. <source@mvista.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#define __UBOOT__ -#ifndef __UBOOT__ -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/module.h> -#include <linux/smp.h> -#include <linux/spinlock.h> -#include <linux/delay.h> -#include <linux/dma-mapping.h> -#include <linux/slab.h> -#else -#include <common.h> -#include <linux/usb/ch9.h> -#include "linux-compat.h" -#endif - -#include "musb_core.h" - - -/* MUSB PERIPHERAL status 3-mar-2006: - * - * - EP0 seems solid. It passes both USBCV and usbtest control cases. - * Minor glitches: - * - * + remote wakeup to Linux hosts work, but saw USBCV failures; - * in one test run (operator error?) - * + endpoint halt tests -- in both usbtest and usbcv -- seem - * to break when dma is enabled ... is something wrongly - * clearing SENDSTALL? - * - * - Mass storage behaved ok when last tested. Network traffic patterns - * (with lots of short transfers etc) need retesting; they turn up the - * worst cases of the DMA, since short packets are typical but are not - * required. - * - * - TX/IN - * + both pio and dma behave in with network and g_zero tests - * + no cppi throughput issues other than no-hw-queueing - * + failed with FLAT_REG (DaVinci) - * + seems to behave with double buffering, PIO -and- CPPI - * + with gadgetfs + AIO, requests got lost? - * - * - RX/OUT - * + both pio and dma behave in with network and g_zero tests - * + dma is slow in typical case (short_not_ok is clear) - * + double buffering ok with PIO - * + double buffering *FAILS* with CPPI, wrong data bytes sometimes - * + request lossage observed with gadgetfs - * - * - ISO not tested ... might work, but only weakly isochronous - * - * - Gadget driver disabling of softconnect during bind() is ignored; so - * drivers can't hold off host requests until userspace is ready. - * (Workaround: they can turn it off later.) - * - * - PORTABILITY (assumes PIO works): - * + DaVinci, basically works with cppi dma - * + OMAP 2430, ditto with mentor dma - * + TUSB 6010, platform-specific dma in the works - */ - -/* ----------------------------------------------------------------------- */ - -#define is_buffer_mapped(req) (is_dma_capable() && \ - (req->map_state != UN_MAPPED)) - -#ifndef CONFIG_MUSB_PIO_ONLY -/* Maps the buffer to dma */ - -static inline void map_dma_buffer(struct musb_request *request, - struct musb *musb, struct musb_ep *musb_ep) -{ - int compatible = true; - struct dma_controller *dma = musb->dma_controller; - - request->map_state = UN_MAPPED; - - if (!is_dma_capable() || !musb_ep->dma) - return; - - /* Check if DMA engine can handle this request. - * DMA code must reject the USB request explicitly. - * Default behaviour is to map the request. - */ - if (dma->is_compatible) - compatible = dma->is_compatible(musb_ep->dma, - musb_ep->packet_sz, request->request.buf, - request->request.length); - if (!compatible) - return; - - if (request->request.dma == DMA_ADDR_INVALID) { - request->request.dma = dma_map_single( - musb->controller, - request->request.buf, - request->request.length, - request->tx - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - request->map_state = MUSB_MAPPED; - } else { - dma_sync_single_for_device(musb->controller, - request->request.dma, - request->request.length, - request->tx - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - request->map_state = PRE_MAPPED; - } -} - -/* Unmap the buffer from dma and maps it back to cpu */ -static inline void unmap_dma_buffer(struct musb_request *request, - struct musb *musb) -{ - if (!is_buffer_mapped(request)) - return; - - if (request->request.dma == DMA_ADDR_INVALID) { - dev_vdbg(musb->controller, - "not unmapping a never mapped buffer\n"); - return; - } - if (request->map_state == MUSB_MAPPED) { - dma_unmap_single(musb->controller, - request->request.dma, - request->request.length, - request->tx - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - request->request.dma = DMA_ADDR_INVALID; - } else { /* PRE_MAPPED */ - dma_sync_single_for_cpu(musb->controller, - request->request.dma, - request->request.length, - request->tx - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - } - request->map_state = UN_MAPPED; -} -#else -static inline void map_dma_buffer(struct musb_request *request, - struct musb *musb, struct musb_ep *musb_ep) -{ -} - -static inline void unmap_dma_buffer(struct musb_request *request, - struct musb *musb) -{ -} -#endif - -/* - * Immediately complete a request. - * - * @param request the request to complete - * @param status the status to complete the request with - * Context: controller locked, IRQs blocked. - */ -void musb_g_giveback( - struct musb_ep *ep, - struct usb_request *request, - int status) -__releases(ep->musb->lock) -__acquires(ep->musb->lock) -{ - struct musb_request *req; - struct musb *musb; - int busy = ep->busy; - - req = to_musb_request(request); - - list_del(&req->list); - if (req->request.status == -EINPROGRESS) - req->request.status = status; - musb = req->musb; - - ep->busy = 1; - spin_unlock(&musb->lock); - unmap_dma_buffer(req, musb); - if (request->status == 0) - dev_dbg(musb->controller, "%s done request %p, %d/%d\n", - ep->end_point.name, request, - req->request.actual, req->request.length); - else - dev_dbg(musb->controller, "%s request %p, %d/%d fault %d\n", - ep->end_point.name, request, - req->request.actual, req->request.length, - request->status); - req->request.complete(&req->ep->end_point, &req->request); - spin_lock(&musb->lock); - ep->busy = busy; -} - -/* ----------------------------------------------------------------------- */ - -/* - * Abort requests queued to an endpoint using the status. Synchronous. - * caller locked controller and blocked irqs, and selected this ep. - */ -static void nuke(struct musb_ep *ep, const int status) -{ - struct musb *musb = ep->musb; - struct musb_request *req = NULL; - void __iomem *epio = ep->musb->endpoints[ep->current_epnum].regs; - - ep->busy = 1; - - if (is_dma_capable() && ep->dma) { - struct dma_controller *c = ep->musb->dma_controller; - int value; - - if (ep->is_in) { - /* - * The programming guide says that we must not clear - * the DMAMODE bit before DMAENAB, so we only - * clear it in the second write... - */ - musb_writew(epio, MUSB_TXCSR, - MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO); - musb_writew(epio, MUSB_TXCSR, - 0 | MUSB_TXCSR_FLUSHFIFO); - } else { - musb_writew(epio, MUSB_RXCSR, - 0 | MUSB_RXCSR_FLUSHFIFO); - musb_writew(epio, MUSB_RXCSR, - 0 | MUSB_RXCSR_FLUSHFIFO); - } - - value = c->channel_abort(ep->dma); - dev_dbg(musb->controller, "%s: abort DMA --> %d\n", - ep->name, value); - c->channel_release(ep->dma); - ep->dma = NULL; - } - - while (!list_empty(&ep->req_list)) { - req = list_first_entry(&ep->req_list, struct musb_request, list); - musb_g_giveback(ep, &req->request, status); - } -} - -/* ----------------------------------------------------------------------- */ - -/* Data transfers - pure PIO, pure DMA, or mixed mode */ - -/* - * This assumes the separate CPPI engine is responding to DMA requests - * from the usb core ... sequenced a bit differently from mentor dma. - */ - -static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep) -{ - if (can_bulk_split(musb, ep->type)) - return ep->hw_ep->max_packet_sz_tx; - else - return ep->packet_sz; -} - - -#ifdef CONFIG_USB_INVENTRA_DMA - -/* Peripheral tx (IN) using Mentor DMA works as follows: - Only mode 0 is used for transfers <= wPktSize, - mode 1 is used for larger transfers, - - One of the following happens: - - Host sends IN token which causes an endpoint interrupt - -> TxAvail - -> if DMA is currently busy, exit. - -> if queue is non-empty, txstate(). - - - Request is queued by the gadget driver. - -> if queue was previously empty, txstate() - - txstate() - -> start - /\ -> setup DMA - | (data is transferred to the FIFO, then sent out when - | IN token(s) are recd from Host. - | -> DMA interrupt on completion - | calls TxAvail. - | -> stop DMA, ~DMAENAB, - | -> set TxPktRdy for last short pkt or zlp - | -> Complete Request - | -> Continue next request (call txstate) - |___________________________________| - - * Non-Mentor DMA engines can of course work differently, such as by - * upleveling from irq-per-packet to irq-per-buffer. - */ - -#endif - -/* - * An endpoint is transmitting data. This can be called either from - * the IRQ routine or from ep.queue() to kickstart a request on an - * endpoint. - * - * Context: controller locked, IRQs blocked, endpoint selected - */ -static void txstate(struct musb *musb, struct musb_request *req) -{ - u8 epnum = req->epnum; - struct musb_ep *musb_ep; - void __iomem *epio = musb->endpoints[epnum].regs; - struct usb_request *request; - u16 fifo_count = 0, csr; - int use_dma = 0; - - musb_ep = req->ep; - - /* Check if EP is disabled */ - if (!musb_ep->desc) { - dev_dbg(musb->controller, "ep:%s disabled - ignore request\n", - musb_ep->end_point.name); - return; - } - - /* we shouldn't get here while DMA is active ... but we do ... */ - if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { - dev_dbg(musb->controller, "dma pending...\n"); - return; - } - - /* read TXCSR before */ - csr = musb_readw(epio, MUSB_TXCSR); - - request = &req->request; - fifo_count = min(max_ep_writesize(musb, musb_ep), - (int)(request->length - request->actual)); - - if (csr & MUSB_TXCSR_TXPKTRDY) { - dev_dbg(musb->controller, "%s old packet still ready , txcsr %03x\n", - musb_ep->end_point.name, csr); - return; - } - - if (csr & MUSB_TXCSR_P_SENDSTALL) { - dev_dbg(musb->controller, "%s stalling, txcsr %03x\n", - musb_ep->end_point.name, csr); - return; - } - - dev_dbg(musb->controller, "hw_ep%d, maxpacket %d, fifo count %d, txcsr %03x\n", - epnum, musb_ep->packet_sz, fifo_count, - csr); - -#ifndef CONFIG_MUSB_PIO_ONLY - if (is_buffer_mapped(req)) { - struct dma_controller *c = musb->dma_controller; - size_t request_size; - - /* setup DMA, then program endpoint CSR */ - request_size = min_t(size_t, request->length - request->actual, - musb_ep->dma->max_len); - - use_dma = (request->dma != DMA_ADDR_INVALID); - - /* MUSB_TXCSR_P_ISO is still set correctly */ - -#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA) - { - if (request_size < musb_ep->packet_sz) - musb_ep->dma->desired_mode = 0; - else - musb_ep->dma->desired_mode = 1; - - use_dma = use_dma && c->channel_program( - musb_ep->dma, musb_ep->packet_sz, - musb_ep->dma->desired_mode, - request->dma + request->actual, request_size); - if (use_dma) { - if (musb_ep->dma->desired_mode == 0) { - /* - * We must not clear the DMAMODE bit - * before the DMAENAB bit -- and the - * latter doesn't always get cleared - * before we get here... - */ - csr &= ~(MUSB_TXCSR_AUTOSET - | MUSB_TXCSR_DMAENAB); - musb_writew(epio, MUSB_TXCSR, csr - | MUSB_TXCSR_P_WZC_BITS); - csr &= ~MUSB_TXCSR_DMAMODE; - csr |= (MUSB_TXCSR_DMAENAB | - MUSB_TXCSR_MODE); - /* against programming guide */ - } else { - csr |= (MUSB_TXCSR_DMAENAB - | MUSB_TXCSR_DMAMODE - | MUSB_TXCSR_MODE); - if (!musb_ep->hb_mult) - csr |= MUSB_TXCSR_AUTOSET; - } - csr &= ~MUSB_TXCSR_P_UNDERRUN; - - musb_writew(epio, MUSB_TXCSR, csr); - } - } - -#elif defined(CONFIG_USB_TI_CPPI_DMA) - /* program endpoint CSR first, then setup DMA */ - csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY); - csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE | - MUSB_TXCSR_MODE; - musb_writew(epio, MUSB_TXCSR, - (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) - | csr); - - /* ensure writebuffer is empty */ - csr = musb_readw(epio, MUSB_TXCSR); - - /* NOTE host side sets DMAENAB later than this; both are - * OK since the transfer dma glue (between CPPI and Mentor - * fifos) just tells CPPI it could start. Data only moves - * to the USB TX fifo when both fifos are ready. - */ - - /* "mode" is irrelevant here; handle terminating ZLPs like - * PIO does, since the hardware RNDIS mode seems unreliable - * except for the last-packet-is-already-short case. - */ - use_dma = use_dma && c->channel_program( - musb_ep->dma, musb_ep->packet_sz, - 0, - request->dma + request->actual, - request_size); - if (!use_dma) { - c->channel_release(musb_ep->dma); - musb_ep->dma = NULL; - csr &= ~MUSB_TXCSR_DMAENAB; - musb_writew(epio, MUSB_TXCSR, csr); - /* invariant: prequest->buf is non-null */ - } -#elif defined(CONFIG_USB_TUSB_OMAP_DMA) - use_dma = use_dma && c->channel_program( - musb_ep->dma, musb_ep->packet_sz, - request->zero, - request->dma + request->actual, - request_size); -#endif - } -#endif - - if (!use_dma) { - /* - * Unmap the dma buffer back to cpu if dma channel - * programming fails - */ - unmap_dma_buffer(req, musb); - - musb_write_fifo(musb_ep->hw_ep, fifo_count, - (u8 *) (request->buf + request->actual)); - request->actual += fifo_count; - csr |= MUSB_TXCSR_TXPKTRDY; - csr &= ~MUSB_TXCSR_P_UNDERRUN; - musb_writew(epio, MUSB_TXCSR, csr); - } - - /* host may already have the data when this message shows... */ - dev_dbg(musb->controller, "%s TX/IN %s len %d/%d, txcsr %04x, fifo %d/%d\n", - musb_ep->end_point.name, use_dma ? "dma" : "pio", - request->actual, request->length, - musb_readw(epio, MUSB_TXCSR), - fifo_count, - musb_readw(epio, MUSB_TXMAXP)); -} - -/* - * FIFO state update (e.g. data ready). - * Called from IRQ, with controller locked. - */ -void musb_g_tx(struct musb *musb, u8 epnum) -{ - u16 csr; - struct musb_request *req; - struct usb_request *request; - u8 __iomem *mbase = musb->mregs; - struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_in; - void __iomem *epio = musb->endpoints[epnum].regs; - struct dma_channel *dma; - - musb_ep_select(mbase, epnum); - req = next_request(musb_ep); - request = &req->request; - - csr = musb_readw(epio, MUSB_TXCSR); - dev_dbg(musb->controller, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr); - - dma = is_dma_capable() ? musb_ep->dma : NULL; - - /* - * REVISIT: for high bandwidth, MUSB_TXCSR_P_INCOMPTX - * probably rates reporting as a host error. - */ - if (csr & MUSB_TXCSR_P_SENTSTALL) { - csr |= MUSB_TXCSR_P_WZC_BITS; - csr &= ~MUSB_TXCSR_P_SENTSTALL; - musb_writew(epio, MUSB_TXCSR, csr); - return; - } - - if (csr & MUSB_TXCSR_P_UNDERRUN) { - /* We NAKed, no big deal... little reason to care. */ - csr |= MUSB_TXCSR_P_WZC_BITS; - csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY); - musb_writew(epio, MUSB_TXCSR, csr); - dev_vdbg(musb->controller, "underrun on ep%d, req %p\n", - epnum, request); - } - - if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { - /* - * SHOULD NOT HAPPEN... has with CPPI though, after - * changing SENDSTALL (and other cases); harmless? - */ - dev_dbg(musb->controller, "%s dma still busy?\n", musb_ep->end_point.name); - return; - } - - if (request) { - u8 is_dma = 0; - - if (dma && (csr & MUSB_TXCSR_DMAENAB)) { - is_dma = 1; - csr |= MUSB_TXCSR_P_WZC_BITS; - csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN | - MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET); - musb_writew(epio, MUSB_TXCSR, csr); - /* Ensure writebuffer is empty. */ - csr = musb_readw(epio, MUSB_TXCSR); - request->actual += musb_ep->dma->actual_len; - dev_dbg(musb->controller, "TXCSR%d %04x, DMA off, len %zu, req %p\n", - epnum, csr, musb_ep->dma->actual_len, request); - } - - /* - * First, maybe a terminating short packet. Some DMA - * engines might handle this by themselves. - */ - if ((request->zero && request->length - && (request->length % musb_ep->packet_sz == 0) - && (request->actual == request->length)) -#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA) - || (is_dma && (!dma->desired_mode || - (request->actual & - (musb_ep->packet_sz - 1)))) -#endif - ) { - /* - * On DMA completion, FIFO may not be - * available yet... - */ - if (csr & MUSB_TXCSR_TXPKTRDY) - return; - - dev_dbg(musb->controller, "sending zero pkt\n"); - musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE - | MUSB_TXCSR_TXPKTRDY); - request->zero = 0; - } - - if (request->actual == request->length) { - musb_g_giveback(musb_ep, request, 0); - /* - * In the giveback function the MUSB lock is - * released and acquired after sometime. During - * this time period the INDEX register could get - * changed by the gadget_queue function especially - * on SMP systems. Reselect the INDEX to be sure - * we are reading/modifying the right registers - */ - musb_ep_select(mbase, epnum); - req = musb_ep->desc ? next_request(musb_ep) : NULL; - if (!req) { - dev_dbg(musb->controller, "%s idle now\n", - musb_ep->end_point.name); - return; - } - } - - txstate(musb, req); - } -} - -/* ------------------------------------------------------------ */ - -#ifdef CONFIG_USB_INVENTRA_DMA - -/* Peripheral rx (OUT) using Mentor DMA works as follows: - - Only mode 0 is used. - - - Request is queued by the gadget class driver. - -> if queue was previously empty, rxstate() - - - Host sends OUT token which causes an endpoint interrupt - /\ -> RxReady - | -> if request queued, call rxstate - | /\ -> setup DMA - | | -> DMA interrupt on completion - | | -> RxReady - | | -> stop DMA - | | -> ack the read - | | -> if data recd = max expected - | | by the request, or host - | | sent a short packet, - | | complete the request, - | | and start the next one. - | |_____________________________________| - | else just wait for the host - | to send the next OUT token. - |__________________________________________________| - - * Non-Mentor DMA engines can of course work differently. - */ - -#endif - -/* - * Context: controller locked, IRQs blocked, endpoint selected - */ -static void rxstate(struct musb *musb, struct musb_request *req) -{ - const u8 epnum = req->epnum; - struct usb_request *request = &req->request; - struct musb_ep *musb_ep; - void __iomem *epio = musb->endpoints[epnum].regs; - unsigned fifo_count = 0; - u16 len; - u16 csr = musb_readw(epio, MUSB_RXCSR); - struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; - u8 use_mode_1; - - if (hw_ep->is_shared_fifo) - musb_ep = &hw_ep->ep_in; - else - musb_ep = &hw_ep->ep_out; - - len = musb_ep->packet_sz; - - /* Check if EP is disabled */ - if (!musb_ep->desc) { - dev_dbg(musb->controller, "ep:%s disabled - ignore request\n", - musb_ep->end_point.name); - return; - } - - /* We shouldn't get here while DMA is active, but we do... */ - if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { - dev_dbg(musb->controller, "DMA pending...\n"); - return; - } - - if (csr & MUSB_RXCSR_P_SENDSTALL) { - dev_dbg(musb->controller, "%s stalling, RXCSR %04x\n", - musb_ep->end_point.name, csr); - return; - } - - if (is_cppi_enabled() && is_buffer_mapped(req)) { - struct dma_controller *c = musb->dma_controller; - struct dma_channel *channel = musb_ep->dma; - - /* NOTE: CPPI won't actually stop advancing the DMA - * queue after short packet transfers, so this is almost - * always going to run as IRQ-per-packet DMA so that - * faults will be handled correctly. - */ - if (c->channel_program(channel, - musb_ep->packet_sz, - !request->short_not_ok, - request->dma + request->actual, - request->length - request->actual)) { - - /* make sure that if an rxpkt arrived after the irq, - * the cppi engine will be ready to take it as soon - * as DMA is enabled - */ - csr &= ~(MUSB_RXCSR_AUTOCLEAR - | MUSB_RXCSR_DMAMODE); - csr |= MUSB_RXCSR_DMAENAB | MUSB_RXCSR_P_WZC_BITS; - musb_writew(epio, MUSB_RXCSR, csr); - return; - } - } - - if (csr & MUSB_RXCSR_RXPKTRDY) { - len = musb_readw(epio, MUSB_RXCOUNT); - - /* - * Enable Mode 1 on RX transfers only when short_not_ok flag - * is set. Currently short_not_ok flag is set only from - * file_storage and f_mass_storage drivers - */ - - if (request->short_not_ok && len == musb_ep->packet_sz) - use_mode_1 = 1; - else - use_mode_1 = 0; - - if (request->actual < request->length) { -#ifdef CONFIG_USB_INVENTRA_DMA - if (is_buffer_mapped(req)) { - struct dma_controller *c; - struct dma_channel *channel; - int use_dma = 0; - - c = musb->dma_controller; - channel = musb_ep->dma; - - /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in - * mode 0 only. So we do not get endpoint interrupts due to DMA - * completion. We only get interrupts from DMA controller. - * - * We could operate in DMA mode 1 if we knew the size of the tranfer - * in advance. For mass storage class, request->length = what the host - * sends, so that'd work. But for pretty much everything else, - * request->length is routinely more than what the host sends. For - * most these gadgets, end of is signified either by a short packet, - * or filling the last byte of the buffer. (Sending extra data in - * that last pckate should trigger an overflow fault.) But in mode 1, - * we don't get DMA completion interrupt for short packets. - * - * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1), - * to get endpoint interrupt on every DMA req, but that didn't seem - * to work reliably. - * - * REVISIT an updated g_file_storage can set req->short_not_ok, which - * then becomes usable as a runtime "use mode 1" hint... - */ - - /* Experimental: Mode1 works with mass storage use cases */ - if (use_mode_1) { - csr |= MUSB_RXCSR_AUTOCLEAR; - musb_writew(epio, MUSB_RXCSR, csr); - csr |= MUSB_RXCSR_DMAENAB; - musb_writew(epio, MUSB_RXCSR, csr); - - /* - * this special sequence (enabling and then - * disabling MUSB_RXCSR_DMAMODE) is required - * to get DMAReq to activate - */ - musb_writew(epio, MUSB_RXCSR, - csr | MUSB_RXCSR_DMAMODE); - musb_writew(epio, MUSB_RXCSR, csr); - - } else { - if (!musb_ep->hb_mult && - musb_ep->hw_ep->rx_double_buffered) - csr |= MUSB_RXCSR_AUTOCLEAR; - csr |= MUSB_RXCSR_DMAENAB; - musb_writew(epio, MUSB_RXCSR, csr); - } - - if (request->actual < request->length) { - int transfer_size = 0; - if (use_mode_1) { - transfer_size = min(request->length - request->actual, - channel->max_len); - musb_ep->dma->desired_mode = 1; - } else { - transfer_size = min(request->length - request->actual, - (unsigned)len); - musb_ep->dma->desired_mode = 0; - } - - use_dma = c->channel_program( - channel, - musb_ep->packet_sz, - channel->desired_mode, - request->dma - + request->actual, - transfer_size); - } - - if (use_dma) - return; - } -#elif defined(CONFIG_USB_UX500_DMA) - if ((is_buffer_mapped(req)) && - (request->actual < request->length)) { - - struct dma_controller *c; - struct dma_channel *channel; - int transfer_size = 0; - - c = musb->dma_controller; - channel = musb_ep->dma; - - /* In case first packet is short */ - if (len < musb_ep->packet_sz) - transfer_size = len; - else if (request->short_not_ok) - transfer_size = min(request->length - - request->actual, - channel->max_len); - else - transfer_size = min(request->length - - request->actual, - (unsigned)len); - - csr &= ~MUSB_RXCSR_DMAMODE; - csr |= (MUSB_RXCSR_DMAENAB | - MUSB_RXCSR_AUTOCLEAR); - - musb_writew(epio, MUSB_RXCSR, csr); - - if (transfer_size <= musb_ep->packet_sz) { - musb_ep->dma->desired_mode = 0; - } else { - musb_ep->dma->desired_mode = 1; - /* Mode must be set after DMAENAB */ - csr |= MUSB_RXCSR_DMAMODE; - musb_writew(epio, MUSB_RXCSR, csr); - } - - if (c->channel_program(channel, - musb_ep->packet_sz, - channel->desired_mode, - request->dma - + request->actual, - transfer_size)) - - return; - } -#endif /* Mentor's DMA */ - - fifo_count = request->length - request->actual; - dev_dbg(musb->controller, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n", - musb_ep->end_point.name, - len, fifo_count, - musb_ep->packet_sz); - - fifo_count = min_t(unsigned, len, fifo_count); - -#ifdef CONFIG_USB_TUSB_OMAP_DMA - if (tusb_dma_omap() && is_buffer_mapped(req)) { - struct dma_controller *c = musb->dma_controller; - struct dma_channel *channel = musb_ep->dma; - u32 dma_addr = request->dma + request->actual; - int ret; - - ret = c->channel_program(channel, - musb_ep->packet_sz, - channel->desired_mode, - dma_addr, - fifo_count); - if (ret) - return; - } -#endif - /* - * Unmap the dma buffer back to cpu if dma channel - * programming fails. This buffer is mapped if the - * channel allocation is successful - */ - if (is_buffer_mapped(req)) { - unmap_dma_buffer(req, musb); - - /* - * Clear DMAENAB and AUTOCLEAR for the - * PIO mode transfer - */ - csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR); - musb_writew(epio, MUSB_RXCSR, csr); - } - - musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *) - (request->buf + request->actual)); - request->actual += fifo_count; - - /* REVISIT if we left anything in the fifo, flush - * it and report -EOVERFLOW - */ - - /* ack the read! */ - csr |= MUSB_RXCSR_P_WZC_BITS; - csr &= ~MUSB_RXCSR_RXPKTRDY; - musb_writew(epio, MUSB_RXCSR, csr); - } - } - - /* reach the end or short packet detected */ - if (request->actual == request->length || len < musb_ep->packet_sz) - musb_g_giveback(musb_ep, request, 0); -} - -/* - * Data ready for a request; called from IRQ - */ -void musb_g_rx(struct musb *musb, u8 epnum) -{ - u16 csr; - struct musb_request *req; - struct usb_request *request; - void __iomem *mbase = musb->mregs; - struct musb_ep *musb_ep; - void __iomem *epio = musb->endpoints[epnum].regs; - struct dma_channel *dma; - struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; - - if (hw_ep->is_shared_fifo) - musb_ep = &hw_ep->ep_in; - else - musb_ep = &hw_ep->ep_out; - - musb_ep_select(mbase, epnum); - - req = next_request(musb_ep); - if (!req) - return; - - request = &req->request; - - csr = musb_readw(epio, MUSB_RXCSR); - dma = is_dma_capable() ? musb_ep->dma : NULL; - - dev_dbg(musb->controller, "<== %s, rxcsr %04x%s %p\n", musb_ep->end_point.name, - csr, dma ? " (dma)" : "", request); - - if (csr & MUSB_RXCSR_P_SENTSTALL) { - csr |= MUSB_RXCSR_P_WZC_BITS; - csr &= ~MUSB_RXCSR_P_SENTSTALL; - musb_writew(epio, MUSB_RXCSR, csr); - return; - } - - if (csr & MUSB_RXCSR_P_OVERRUN) { - /* csr |= MUSB_RXCSR_P_WZC_BITS; */ - csr &= ~MUSB_RXCSR_P_OVERRUN; - musb_writew(epio, MUSB_RXCSR, csr); - - dev_dbg(musb->controller, "%s iso overrun on %p\n", musb_ep->name, request); - if (request->status == -EINPROGRESS) - request->status = -EOVERFLOW; - } - if (csr & MUSB_RXCSR_INCOMPRX) { - /* REVISIT not necessarily an error */ - dev_dbg(musb->controller, "%s, incomprx\n", musb_ep->end_point.name); - } - - if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { - /* "should not happen"; likely RXPKTRDY pending for DMA */ - dev_dbg(musb->controller, "%s busy, csr %04x\n", - musb_ep->end_point.name, csr); - return; - } - - if (dma && (csr & MUSB_RXCSR_DMAENAB)) { - csr &= ~(MUSB_RXCSR_AUTOCLEAR - | MUSB_RXCSR_DMAENAB - | MUSB_RXCSR_DMAMODE); - musb_writew(epio, MUSB_RXCSR, - MUSB_RXCSR_P_WZC_BITS | csr); - - request->actual += musb_ep->dma->actual_len; - - dev_dbg(musb->controller, "RXCSR%d %04x, dma off, %04x, len %zu, req %p\n", - epnum, csr, - musb_readw(epio, MUSB_RXCSR), - musb_ep->dma->actual_len, request); - -#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) || \ - defined(CONFIG_USB_UX500_DMA) - /* Autoclear doesn't clear RxPktRdy for short packets */ - if ((dma->desired_mode == 0 && !hw_ep->rx_double_buffered) - || (dma->actual_len - & (musb_ep->packet_sz - 1))) { - /* ack the read! */ - csr &= ~MUSB_RXCSR_RXPKTRDY; - musb_writew(epio, MUSB_RXCSR, csr); - } - - /* incomplete, and not short? wait for next IN packet */ - if ((request->actual < request->length) - && (musb_ep->dma->actual_len - == musb_ep->packet_sz)) { - /* In double buffer case, continue to unload fifo if - * there is Rx packet in FIFO. - **/ - csr = musb_readw(epio, MUSB_RXCSR); - if ((csr & MUSB_RXCSR_RXPKTRDY) && - hw_ep->rx_double_buffered) - goto exit; - return; - } -#endif - musb_g_giveback(musb_ep, request, 0); - /* - * In the giveback function the MUSB lock is - * released and acquired after sometime. During - * this time period the INDEX register could get - * changed by the gadget_queue function especially - * on SMP systems. Reselect the INDEX to be sure - * we are reading/modifying the right registers - */ - musb_ep_select(mbase, epnum); - - req = next_request(musb_ep); - if (!req) - return; - } -#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) || \ - defined(CONFIG_USB_UX500_DMA) -exit: -#endif - /* Analyze request */ - rxstate(musb, req); -} - -/* ------------------------------------------------------------ */ - -static int musb_gadget_enable(struct usb_ep *ep, - const struct usb_endpoint_descriptor *desc) -{ - unsigned long flags; - struct musb_ep *musb_ep; - struct musb_hw_ep *hw_ep; - void __iomem *regs; - struct musb *musb; - void __iomem *mbase; - u8 epnum; - u16 csr; - unsigned tmp; - int status = -EINVAL; - - if (!ep || !desc) - return -EINVAL; - - musb_ep = to_musb_ep(ep); - hw_ep = musb_ep->hw_ep; - regs = hw_ep->regs; - musb = musb_ep->musb; - mbase = musb->mregs; - epnum = musb_ep->current_epnum; - - spin_lock_irqsave(&musb->lock, flags); - - if (musb_ep->desc) { - status = -EBUSY; - goto fail; - } - musb_ep->type = usb_endpoint_type(desc); - - /* check direction and (later) maxpacket size against endpoint */ - if (usb_endpoint_num(desc) != epnum) - goto fail; - - /* REVISIT this rules out high bandwidth periodic transfers */ - tmp = usb_endpoint_maxp(desc); - if (tmp & ~0x07ff) { - int ok; - - if (usb_endpoint_dir_in(desc)) - ok = musb->hb_iso_tx; - else - ok = musb->hb_iso_rx; - - if (!ok) { - dev_dbg(musb->controller, "no support for high bandwidth ISO\n"); - goto fail; - } - musb_ep->hb_mult = (tmp >> 11) & 3; - } else { - musb_ep->hb_mult = 0; - } - - musb_ep->packet_sz = tmp & 0x7ff; - tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1); - - /* enable the interrupts for the endpoint, set the endpoint - * packet size (or fail), set the mode, clear the fifo - */ - musb_ep_select(mbase, epnum); - if (usb_endpoint_dir_in(desc)) { - u16 int_txe = musb_readw(mbase, MUSB_INTRTXE); - - if (hw_ep->is_shared_fifo) - musb_ep->is_in = 1; - if (!musb_ep->is_in) - goto fail; - - if (tmp > hw_ep->max_packet_sz_tx) { - dev_dbg(musb->controller, "packet size beyond hardware FIFO size\n"); - goto fail; - } - - int_txe |= (1 << epnum); - musb_writew(mbase, MUSB_INTRTXE, int_txe); - - /* REVISIT if can_bulk_split(), use by updating "tmp"; - * likewise high bandwidth periodic tx - */ - /* Set TXMAXP with the FIFO size of the endpoint - * to disable double buffering mode. - */ - if (musb->double_buffer_not_ok) - musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx); - else - musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz - | (musb_ep->hb_mult << 11)); - - csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG; - if (musb_readw(regs, MUSB_TXCSR) - & MUSB_TXCSR_FIFONOTEMPTY) - csr |= MUSB_TXCSR_FLUSHFIFO; - if (musb_ep->type == USB_ENDPOINT_XFER_ISOC) - csr |= MUSB_TXCSR_P_ISO; - - /* set twice in case of double buffering */ - musb_writew(regs, MUSB_TXCSR, csr); - /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */ - musb_writew(regs, MUSB_TXCSR, csr); - - } else { - u16 int_rxe = musb_readw(mbase, MUSB_INTRRXE); - - if (hw_ep->is_shared_fifo) - musb_ep->is_in = 0; - if (musb_ep->is_in) - goto fail; - - if (tmp > hw_ep->max_packet_sz_rx) { - dev_dbg(musb->controller, "packet size beyond hardware FIFO size\n"); - goto fail; - } - - int_rxe |= (1 << epnum); - musb_writew(mbase, MUSB_INTRRXE, int_rxe); - - /* REVISIT if can_bulk_combine() use by updating "tmp" - * likewise high bandwidth periodic rx - */ - /* Set RXMAXP with the FIFO size of the endpoint - * to disable double buffering mode. - */ - if (musb->double_buffer_not_ok) - musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_tx); - else - musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz - | (musb_ep->hb_mult << 11)); - - /* force shared fifo to OUT-only mode */ - if (hw_ep->is_shared_fifo) { - csr = musb_readw(regs, MUSB_TXCSR); - csr &= ~(MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY); - musb_writew(regs, MUSB_TXCSR, csr); - } - - csr = MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_CLRDATATOG; - if (musb_ep->type == USB_ENDPOINT_XFER_ISOC) - csr |= MUSB_RXCSR_P_ISO; - else if (musb_ep->type == USB_ENDPOINT_XFER_INT) - csr |= MUSB_RXCSR_DISNYET; - - /* set twice in case of double buffering */ - musb_writew(regs, MUSB_RXCSR, csr); - musb_writew(regs, MUSB_RXCSR, csr); - } - - /* NOTE: all the I/O code _should_ work fine without DMA, in case - * for some reason you run out of channels here. - */ - if (is_dma_capable() && musb->dma_controller) { - struct dma_controller *c = musb->dma_controller; - - musb_ep->dma = c->channel_alloc(c, hw_ep, - (desc->bEndpointAddress & USB_DIR_IN)); - } else - musb_ep->dma = NULL; - - musb_ep->desc = desc; - musb_ep->busy = 0; - musb_ep->wedged = 0; - status = 0; - - pr_debug("%s periph: enabled %s for %s %s, %smaxpacket %d\n", - musb_driver_name, musb_ep->end_point.name, - ({ char *s; switch (musb_ep->type) { - case USB_ENDPOINT_XFER_BULK: s = "bulk"; break; - case USB_ENDPOINT_XFER_INT: s = "int"; break; - default: s = "iso"; break; - }; s; }), - musb_ep->is_in ? "IN" : "OUT", - musb_ep->dma ? "dma, " : "", - musb_ep->packet_sz); - - schedule_work(&musb->irq_work); - -fail: - spin_unlock_irqrestore(&musb->lock, flags); - return status; -} - -/* - * Disable an endpoint flushing all requests queued. - */ -static int musb_gadget_disable(struct usb_ep *ep) -{ - unsigned long flags; - struct musb *musb; - u8 epnum; - struct musb_ep *musb_ep; - void __iomem *epio; - int status = 0; - - musb_ep = to_musb_ep(ep); - musb = musb_ep->musb; - epnum = musb_ep->current_epnum; - epio = musb->endpoints[epnum].regs; - - spin_lock_irqsave(&musb->lock, flags); - musb_ep_select(musb->mregs, epnum); - - /* zero the endpoint sizes */ - if (musb_ep->is_in) { - u16 int_txe = musb_readw(musb->mregs, MUSB_INTRTXE); - int_txe &= ~(1 << epnum); - musb_writew(musb->mregs, MUSB_INTRTXE, int_txe); - musb_writew(epio, MUSB_TXMAXP, 0); - } else { - u16 int_rxe = musb_readw(musb->mregs, MUSB_INTRRXE); - int_rxe &= ~(1 << epnum); - musb_writew(musb->mregs, MUSB_INTRRXE, int_rxe); - musb_writew(epio, MUSB_RXMAXP, 0); - } - - musb_ep->desc = NULL; -#ifndef __UBOOT__ - musb_ep->end_point.desc = NULL; -#endif - - /* abort all pending DMA and requests */ - nuke(musb_ep, -ESHUTDOWN); - - schedule_work(&musb->irq_work); - - spin_unlock_irqrestore(&(musb->lock), flags); - - dev_dbg(musb->controller, "%s\n", musb_ep->end_point.name); - - return status; -} - -/* - * Allocate a request for an endpoint. - * Reused by ep0 code. - */ -struct usb_request *musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) -{ - struct musb_ep *musb_ep = to_musb_ep(ep); - struct musb *musb = musb_ep->musb; - struct musb_request *request = NULL; - - request = kzalloc(sizeof *request, gfp_flags); - if (!request) { - dev_dbg(musb->controller, "not enough memory\n"); - return NULL; - } - - request->request.dma = DMA_ADDR_INVALID; - request->epnum = musb_ep->current_epnum; - request->ep = musb_ep; - - return &request->request; -} - -/* - * Free a request - * Reused by ep0 code. - */ -void musb_free_request(struct usb_ep *ep, struct usb_request *req) -{ - kfree(to_musb_request(req)); -} - -static LIST_HEAD(buffers); - -struct free_record { - struct list_head list; - struct device *dev; - unsigned bytes; - dma_addr_t dma; -}; - -/* - * Context: controller locked, IRQs blocked. - */ -void musb_ep_restart(struct musb *musb, struct musb_request *req) -{ - dev_dbg(musb->controller, "<== %s request %p len %u on hw_ep%d\n", - req->tx ? "TX/IN" : "RX/OUT", - &req->request, req->request.length, req->epnum); - - musb_ep_select(musb->mregs, req->epnum); - if (req->tx) - txstate(musb, req); - else - rxstate(musb, req); -} - -static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, - gfp_t gfp_flags) -{ - struct musb_ep *musb_ep; - struct musb_request *request; - struct musb *musb; - int status = 0; - unsigned long lockflags; - - if (!ep || !req) - return -EINVAL; - if (!req->buf) - return -ENODATA; - - musb_ep = to_musb_ep(ep); - musb = musb_ep->musb; - - request = to_musb_request(req); - request->musb = musb; - - if (request->ep != musb_ep) - return -EINVAL; - - dev_dbg(musb->controller, "<== to %s request=%p\n", ep->name, req); - - /* request is mine now... */ - request->request.actual = 0; - request->request.status = -EINPROGRESS; - request->epnum = musb_ep->current_epnum; - request->tx = musb_ep->is_in; - - map_dma_buffer(request, musb, musb_ep); - - spin_lock_irqsave(&musb->lock, lockflags); - - /* don't queue if the ep is down */ - if (!musb_ep->desc) { - dev_dbg(musb->controller, "req %p queued to %s while ep %s\n", - req, ep->name, "disabled"); - status = -ESHUTDOWN; - goto cleanup; - } - - /* add request to the list */ - list_add_tail(&request->list, &musb_ep->req_list); - - /* it this is the head of the queue, start i/o ... */ - if (!musb_ep->busy && &request->list == musb_ep->req_list.next) - musb_ep_restart(musb, request); - -cleanup: - spin_unlock_irqrestore(&musb->lock, lockflags); - return status; -} - -static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request) -{ - struct musb_ep *musb_ep = to_musb_ep(ep); - struct musb_request *req = to_musb_request(request); - struct musb_request *r; - unsigned long flags; - int status = 0; - struct musb *musb = musb_ep->musb; - - if (!ep || !request || to_musb_request(request)->ep != musb_ep) - return -EINVAL; - - spin_lock_irqsave(&musb->lock, flags); - - list_for_each_entry(r, &musb_ep->req_list, list) { - if (r == req) - break; - } - if (r != req) { - dev_dbg(musb->controller, "request %p not queued to %s\n", request, ep->name); - status = -EINVAL; - goto done; - } - - /* if the hardware doesn't have the request, easy ... */ - if (musb_ep->req_list.next != &req->list || musb_ep->busy) - musb_g_giveback(musb_ep, request, -ECONNRESET); - - /* ... else abort the dma transfer ... */ - else if (is_dma_capable() && musb_ep->dma) { - struct dma_controller *c = musb->dma_controller; - - musb_ep_select(musb->mregs, musb_ep->current_epnum); - if (c->channel_abort) - status = c->channel_abort(musb_ep->dma); - else - status = -EBUSY; - if (status == 0) - musb_g_giveback(musb_ep, request, -ECONNRESET); - } else { - /* NOTE: by sticking to easily tested hardware/driver states, - * we leave counting of in-flight packets imprecise. - */ - musb_g_giveback(musb_ep, request, -ECONNRESET); - } - -done: - spin_unlock_irqrestore(&musb->lock, flags); - return status; -} - -/* - * Set or clear the halt bit of an endpoint. A halted enpoint won't tx/rx any - * data but will queue requests. - * - * exported to ep0 code - */ -static int musb_gadget_set_halt(struct usb_ep *ep, int value) -{ - struct musb_ep *musb_ep = to_musb_ep(ep); - u8 epnum = musb_ep->current_epnum; - struct musb *musb = musb_ep->musb; - void __iomem *epio = musb->endpoints[epnum].regs; - void __iomem *mbase; - unsigned long flags; - u16 csr; - struct musb_request *request; - int status = 0; - - if (!ep) - return -EINVAL; - mbase = musb->mregs; - - spin_lock_irqsave(&musb->lock, flags); - - if ((USB_ENDPOINT_XFER_ISOC == musb_ep->type)) { - status = -EINVAL; - goto done; - } - - musb_ep_select(mbase, epnum); - - request = next_request(musb_ep); - if (value) { - if (request) { - dev_dbg(musb->controller, "request in progress, cannot halt %s\n", - ep->name); - status = -EAGAIN; - goto done; - } - /* Cannot portably stall with non-empty FIFO */ - if (musb_ep->is_in) { - csr = musb_readw(epio, MUSB_TXCSR); - if (csr & MUSB_TXCSR_FIFONOTEMPTY) { - dev_dbg(musb->controller, "FIFO busy, cannot halt %s\n", ep->name); - status = -EAGAIN; - goto done; - } - } - } else - musb_ep->wedged = 0; - - /* set/clear the stall and toggle bits */ - dev_dbg(musb->controller, "%s: %s stall\n", ep->name, value ? "set" : "clear"); - if (musb_ep->is_in) { - csr = musb_readw(epio, MUSB_TXCSR); - csr |= MUSB_TXCSR_P_WZC_BITS - | MUSB_TXCSR_CLRDATATOG; - if (value) - csr |= MUSB_TXCSR_P_SENDSTALL; - else - csr &= ~(MUSB_TXCSR_P_SENDSTALL - | MUSB_TXCSR_P_SENTSTALL); - csr &= ~MUSB_TXCSR_TXPKTRDY; - musb_writew(epio, MUSB_TXCSR, csr); - } else { - csr = musb_readw(epio, MUSB_RXCSR); - csr |= MUSB_RXCSR_P_WZC_BITS - | MUSB_RXCSR_FLUSHFIFO - | MUSB_RXCSR_CLRDATATOG; - if (value) - csr |= MUSB_RXCSR_P_SENDSTALL; - else - csr &= ~(MUSB_RXCSR_P_SENDSTALL - | MUSB_RXCSR_P_SENTSTALL); - musb_writew(epio, MUSB_RXCSR, csr); - } - - /* maybe start the first request in the queue */ - if (!musb_ep->busy && !value && request) { - dev_dbg(musb->controller, "restarting the request\n"); - musb_ep_restart(musb, request); - } - -done: - spin_unlock_irqrestore(&musb->lock, flags); - return status; -} - -#ifndef __UBOOT__ -/* - * Sets the halt feature with the clear requests ignored - */ -static int musb_gadget_set_wedge(struct usb_ep *ep) -{ - struct musb_ep *musb_ep = to_musb_ep(ep); - - if (!ep) - return -EINVAL; - - musb_ep->wedged = 1; - - return usb_ep_set_halt(ep); -} -#endif - -static int musb_gadget_fifo_status(struct usb_ep *ep) -{ - struct musb_ep *musb_ep = to_musb_ep(ep); - void __iomem *epio = musb_ep->hw_ep->regs; - int retval = -EINVAL; - - if (musb_ep->desc && !musb_ep->is_in) { - struct musb *musb = musb_ep->musb; - int epnum = musb_ep->current_epnum; - void __iomem *mbase = musb->mregs; - unsigned long flags; - - spin_lock_irqsave(&musb->lock, flags); - - musb_ep_select(mbase, epnum); - /* FIXME return zero unless RXPKTRDY is set */ - retval = musb_readw(epio, MUSB_RXCOUNT); - - spin_unlock_irqrestore(&musb->lock, flags); - } - return retval; -} - -static void musb_gadget_fifo_flush(struct usb_ep *ep) -{ - struct musb_ep *musb_ep = to_musb_ep(ep); - struct musb *musb = musb_ep->musb; - u8 epnum = musb_ep->current_epnum; - void __iomem *epio = musb->endpoints[epnum].regs; - void __iomem *mbase; - unsigned long flags; - u16 csr, int_txe; - - mbase = musb->mregs; - - spin_lock_irqsave(&musb->lock, flags); - musb_ep_select(mbase, (u8) epnum); - - /* disable interrupts */ - int_txe = musb_readw(mbase, MUSB_INTRTXE); - musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum)); - - if (musb_ep->is_in) { - csr = musb_readw(epio, MUSB_TXCSR); - if (csr & MUSB_TXCSR_FIFONOTEMPTY) { - csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_P_WZC_BITS; - /* - * Setting both TXPKTRDY and FLUSHFIFO makes controller - * to interrupt current FIFO loading, but not flushing - * the already loaded ones. - */ - csr &= ~MUSB_TXCSR_TXPKTRDY; - musb_writew(epio, MUSB_TXCSR, csr); - /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */ - musb_writew(epio, MUSB_TXCSR, csr); - } - } else { - csr = musb_readw(epio, MUSB_RXCSR); - csr |= MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_P_WZC_BITS; - musb_writew(epio, MUSB_RXCSR, csr); - musb_writew(epio, MUSB_RXCSR, csr); - } - - /* re-enable interrupt */ - musb_writew(mbase, MUSB_INTRTXE, int_txe); - spin_unlock_irqrestore(&musb->lock, flags); -} - -static const struct usb_ep_ops musb_ep_ops = { - .enable = musb_gadget_enable, - .disable = musb_gadget_disable, - .alloc_request = musb_alloc_request, - .free_request = musb_free_request, - .queue = musb_gadget_queue, - .dequeue = musb_gadget_dequeue, - .set_halt = musb_gadget_set_halt, -#ifndef __UBOOT__ - .set_wedge = musb_gadget_set_wedge, -#endif - .fifo_status = musb_gadget_fifo_status, - .fifo_flush = musb_gadget_fifo_flush -}; - -/* ----------------------------------------------------------------------- */ - -static int musb_gadget_get_frame(struct usb_gadget *gadget) -{ - struct musb *musb = gadget_to_musb(gadget); - - return (int)musb_readw(musb->mregs, MUSB_FRAME); -} - -static int musb_gadget_wakeup(struct usb_gadget *gadget) -{ -#ifndef __UBOOT__ - struct musb *musb = gadget_to_musb(gadget); - void __iomem *mregs = musb->mregs; - unsigned long flags; - int status = -EINVAL; - u8 power, devctl; - int retries; - - spin_lock_irqsave(&musb->lock, flags); - - switch (musb->xceiv->state) { - case OTG_STATE_B_PERIPHERAL: - /* NOTE: OTG state machine doesn't include B_SUSPENDED; - * that's part of the standard usb 1.1 state machine, and - * doesn't affect OTG transitions. - */ - if (musb->may_wakeup && musb->is_suspended) - break; - goto done; - case OTG_STATE_B_IDLE: - /* Start SRP ... OTG not required. */ - devctl = musb_readb(mregs, MUSB_DEVCTL); - dev_dbg(musb->controller, "Sending SRP: devctl: %02x\n", devctl); - devctl |= MUSB_DEVCTL_SESSION; - musb_writeb(mregs, MUSB_DEVCTL, devctl); - devctl = musb_readb(mregs, MUSB_DEVCTL); - retries = 100; - while (!(devctl & MUSB_DEVCTL_SESSION)) { - devctl = musb_readb(mregs, MUSB_DEVCTL); - if (retries-- < 1) - break; - } - retries = 10000; - while (devctl & MUSB_DEVCTL_SESSION) { - devctl = musb_readb(mregs, MUSB_DEVCTL); - if (retries-- < 1) - break; - } - - spin_unlock_irqrestore(&musb->lock, flags); - otg_start_srp(musb->xceiv->otg); - spin_lock_irqsave(&musb->lock, flags); - - /* Block idling for at least 1s */ - musb_platform_try_idle(musb, - jiffies + msecs_to_jiffies(1 * HZ)); - - status = 0; - goto done; - default: - dev_dbg(musb->controller, "Unhandled wake: %s\n", - otg_state_string(musb->xceiv->state)); - goto done; - } - - status = 0; - - power = musb_readb(mregs, MUSB_POWER); - power |= MUSB_POWER_RESUME; - musb_writeb(mregs, MUSB_POWER, power); - dev_dbg(musb->controller, "issue wakeup\n"); - - /* FIXME do this next chunk in a timer callback, no udelay */ - mdelay(2); - - power = musb_readb(mregs, MUSB_POWER); - power &= ~MUSB_POWER_RESUME; - musb_writeb(mregs, MUSB_POWER, power); -done: - spin_unlock_irqrestore(&musb->lock, flags); - return status; -#else - return 0; -#endif -} - -static int -musb_gadget_set_self_powered(struct usb_gadget *gadget, int is_selfpowered) -{ - struct musb *musb = gadget_to_musb(gadget); - - musb->is_self_powered = !!is_selfpowered; - return 0; -} - -static void musb_pullup(struct musb *musb, int is_on) -{ - u8 power; - - power = musb_readb(musb->mregs, MUSB_POWER); - if (is_on) - power |= MUSB_POWER_SOFTCONN; - else - power &= ~MUSB_POWER_SOFTCONN; - - /* FIXME if on, HdrcStart; if off, HdrcStop */ - - dev_dbg(musb->controller, "gadget D+ pullup %s\n", - is_on ? "on" : "off"); - musb_writeb(musb->mregs, MUSB_POWER, power); -} - -#if 0 -static int musb_gadget_vbus_session(struct usb_gadget *gadget, int is_active) -{ - dev_dbg(musb->controller, "<= %s =>\n", __func__); - - /* - * FIXME iff driver's softconnect flag is set (as it is during probe, - * though that can clear it), just musb_pullup(). - */ - - return -EINVAL; -} -#endif - -static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) -{ -#ifndef __UBOOT__ - struct musb *musb = gadget_to_musb(gadget); - - if (!musb->xceiv->set_power) - return -EOPNOTSUPP; - return usb_phy_set_power(musb->xceiv, mA); -#else - return 0; -#endif -} - -static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on) -{ - struct musb *musb = gadget_to_musb(gadget); - unsigned long flags; - - is_on = !!is_on; - - pm_runtime_get_sync(musb->controller); - - /* NOTE: this assumes we are sensing vbus; we'd rather - * not pullup unless the B-session is active. - */ - spin_lock_irqsave(&musb->lock, flags); - if (is_on != musb->softconnect) { - musb->softconnect = is_on; - musb_pullup(musb, is_on); - } - spin_unlock_irqrestore(&musb->lock, flags); - - pm_runtime_put(musb->controller); - - return 0; -} - -#ifndef __UBOOT__ -static int musb_gadget_start(struct usb_gadget *g, - struct usb_gadget_driver *driver); -static int musb_gadget_stop(struct usb_gadget *g, - struct usb_gadget_driver *driver); -#endif - -static const struct usb_gadget_ops musb_gadget_operations = { - .get_frame = musb_gadget_get_frame, - .wakeup = musb_gadget_wakeup, - .set_selfpowered = musb_gadget_set_self_powered, - /* .vbus_session = musb_gadget_vbus_session, */ - .vbus_draw = musb_gadget_vbus_draw, - .pullup = musb_gadget_pullup, -#ifndef __UBOOT__ - .udc_start = musb_gadget_start, - .udc_stop = musb_gadget_stop, -#endif -}; - -/* ----------------------------------------------------------------------- */ - -/* Registration */ - -/* Only this registration code "knows" the rule (from USB standards) - * about there being only one external upstream port. It assumes - * all peripheral ports are external... - */ - -#ifndef __UBOOT__ -static void musb_gadget_release(struct device *dev) -{ - /* kref_put(WHAT) */ - dev_dbg(dev, "%s\n", __func__); -} -#endif - - -static void __devinit -init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in) -{ - struct musb_hw_ep *hw_ep = musb->endpoints + epnum; - - memset(ep, 0, sizeof *ep); - - ep->current_epnum = epnum; - ep->musb = musb; - ep->hw_ep = hw_ep; - ep->is_in = is_in; - - INIT_LIST_HEAD(&ep->req_list); - - sprintf(ep->name, "ep%d%s", epnum, - (!epnum || hw_ep->is_shared_fifo) ? "" : ( - is_in ? "in" : "out")); - ep->end_point.name = ep->name; - INIT_LIST_HEAD(&ep->end_point.ep_list); - if (!epnum) { - ep->end_point.maxpacket = 64; - ep->end_point.ops = &musb_g_ep0_ops; - musb->g.ep0 = &ep->end_point; - } else { - if (is_in) - ep->end_point.maxpacket = hw_ep->max_packet_sz_tx; - else - ep->end_point.maxpacket = hw_ep->max_packet_sz_rx; - ep->end_point.ops = &musb_ep_ops; - list_add_tail(&ep->end_point.ep_list, &musb->g.ep_list); - } -} - -/* - * Initialize the endpoints exposed to peripheral drivers, with backlinks - * to the rest of the driver state. - */ -static inline void __devinit musb_g_init_endpoints(struct musb *musb) -{ - u8 epnum; - struct musb_hw_ep *hw_ep; - unsigned count = 0; - - /* initialize endpoint list just once */ - INIT_LIST_HEAD(&(musb->g.ep_list)); - - for (epnum = 0, hw_ep = musb->endpoints; - epnum < musb->nr_endpoints; - epnum++, hw_ep++) { - if (hw_ep->is_shared_fifo /* || !epnum */) { - init_peripheral_ep(musb, &hw_ep->ep_in, epnum, 0); - count++; - } else { - if (hw_ep->max_packet_sz_tx) { - init_peripheral_ep(musb, &hw_ep->ep_in, - epnum, 1); - count++; - } - if (hw_ep->max_packet_sz_rx) { - init_peripheral_ep(musb, &hw_ep->ep_out, - epnum, 0); - count++; - } - } - } -} - -/* called once during driver setup to initialize and link into - * the driver model; memory is zeroed. - */ -int __devinit musb_gadget_setup(struct musb *musb) -{ - int status; - - /* REVISIT minor race: if (erroneously) setting up two - * musb peripherals at the same time, only the bus lock - * is probably held. - */ - - musb->g.ops = &musb_gadget_operations; -#ifndef __UBOOT__ - musb->g.max_speed = USB_SPEED_HIGH; -#endif - musb->g.speed = USB_SPEED_UNKNOWN; - -#ifndef __UBOOT__ - /* this "gadget" abstracts/virtualizes the controller */ - dev_set_name(&musb->g.dev, "gadget"); - musb->g.dev.parent = musb->controller; - musb->g.dev.dma_mask = musb->controller->dma_mask; - musb->g.dev.release = musb_gadget_release; -#endif - musb->g.name = musb_driver_name; - -#ifndef __UBOOT__ - if (is_otg_enabled(musb)) - musb->g.is_otg = 1; -#endif - - musb_g_init_endpoints(musb); - - musb->is_active = 0; - musb_platform_try_idle(musb, 0); - -#ifndef __UBOOT__ - status = device_register(&musb->g.dev); - if (status != 0) { - put_device(&musb->g.dev); - return status; - } - status = usb_add_gadget_udc(musb->controller, &musb->g); - if (status) - goto err; -#endif - - return 0; -#ifndef __UBOOT__ -err: - musb->g.dev.parent = NULL; - device_unregister(&musb->g.dev); - return status; -#endif -} - -void musb_gadget_cleanup(struct musb *musb) -{ -#ifndef __UBOOT__ - usb_del_gadget_udc(&musb->g); - if (musb->g.dev.parent) - device_unregister(&musb->g.dev); -#endif -} - -/* - * Register the gadget driver. Used by gadget drivers when - * registering themselves with the controller. - * - * -EINVAL something went wrong (not driver) - * -EBUSY another gadget is already using the controller - * -ENOMEM no memory to perform the operation - * - * @param driver the gadget driver - * @return <0 if error, 0 if everything is fine - */ -#ifndef __UBOOT__ -static int musb_gadget_start(struct usb_gadget *g, - struct usb_gadget_driver *driver) -#else -int musb_gadget_start(struct usb_gadget *g, - struct usb_gadget_driver *driver) -#endif -{ - struct musb *musb = gadget_to_musb(g); -#ifndef __UBOOT__ - struct usb_otg *otg = musb->xceiv->otg; -#endif - unsigned long flags; - int retval = -EINVAL; - -#ifndef __UBOOT__ - if (driver->max_speed < USB_SPEED_HIGH) - goto err0; -#endif - - pm_runtime_get_sync(musb->controller); - -#ifndef __UBOOT__ - dev_dbg(musb->controller, "registering driver %s\n", driver->function); -#endif - - musb->softconnect = 0; - musb->gadget_driver = driver; - - spin_lock_irqsave(&musb->lock, flags); - musb->is_active = 1; - -#ifndef __UBOOT__ - otg_set_peripheral(otg, &musb->g); - musb->xceiv->state = OTG_STATE_B_IDLE; - - /* - * FIXME this ignores the softconnect flag. Drivers are - * allowed hold the peripheral inactive until for example - * userspace hooks up printer hardware or DSP codecs, so - * hosts only see fully functional devices. - */ - - if (!is_otg_enabled(musb)) -#endif - musb_start(musb); - - spin_unlock_irqrestore(&musb->lock, flags); - -#ifndef __UBOOT__ - if (is_otg_enabled(musb)) { - struct usb_hcd *hcd = musb_to_hcd(musb); - - dev_dbg(musb->controller, "OTG startup...\n"); - - /* REVISIT: funcall to other code, which also - * handles power budgeting ... this way also - * ensures HdrcStart is indirectly called. - */ - retval = usb_add_hcd(musb_to_hcd(musb), 0, 0); - if (retval < 0) { - dev_dbg(musb->controller, "add_hcd failed, %d\n", retval); - goto err2; - } - - if ((musb->xceiv->last_event == USB_EVENT_ID) - && otg->set_vbus) - otg_set_vbus(otg, 1); - - hcd->self.uses_pio_for_control = 1; - } - if (musb->xceiv->last_event == USB_EVENT_NONE) - pm_runtime_put(musb->controller); -#endif - - return 0; - -#ifndef __UBOOT__ -err2: - if (!is_otg_enabled(musb)) - musb_stop(musb); -err0: - return retval; -#endif -} - -#ifndef __UBOOT__ -static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver) -{ - int i; - struct musb_hw_ep *hw_ep; - - /* don't disconnect if it's not connected */ - if (musb->g.speed == USB_SPEED_UNKNOWN) - driver = NULL; - else - musb->g.speed = USB_SPEED_UNKNOWN; - - /* deactivate the hardware */ - if (musb->softconnect) { - musb->softconnect = 0; - musb_pullup(musb, 0); - } - musb_stop(musb); - - /* killing any outstanding requests will quiesce the driver; - * then report disconnect - */ - if (driver) { - for (i = 0, hw_ep = musb->endpoints; - i < musb->nr_endpoints; - i++, hw_ep++) { - musb_ep_select(musb->mregs, i); - if (hw_ep->is_shared_fifo /* || !epnum */) { - nuke(&hw_ep->ep_in, -ESHUTDOWN); - } else { - if (hw_ep->max_packet_sz_tx) - nuke(&hw_ep->ep_in, -ESHUTDOWN); - if (hw_ep->max_packet_sz_rx) - nuke(&hw_ep->ep_out, -ESHUTDOWN); - } - } - } -} - -/* - * Unregister the gadget driver. Used by gadget drivers when - * unregistering themselves from the controller. - * - * @param driver the gadget driver to unregister - */ -static int musb_gadget_stop(struct usb_gadget *g, - struct usb_gadget_driver *driver) -{ - struct musb *musb = gadget_to_musb(g); - unsigned long flags; - - if (musb->xceiv->last_event == USB_EVENT_NONE) - pm_runtime_get_sync(musb->controller); - - /* - * REVISIT always use otg_set_peripheral() here too; - * this needs to shut down the OTG engine. - */ - - spin_lock_irqsave(&musb->lock, flags); - - musb_hnp_stop(musb); - - (void) musb_gadget_vbus_draw(&musb->g, 0); - - musb->xceiv->state = OTG_STATE_UNDEFINED; - stop_activity(musb, driver); - otg_set_peripheral(musb->xceiv->otg, NULL); - - dev_dbg(musb->controller, "unregistering driver %s\n", driver->function); - - musb->is_active = 0; - musb_platform_try_idle(musb, 0); - spin_unlock_irqrestore(&musb->lock, flags); - - if (is_otg_enabled(musb)) { - usb_remove_hcd(musb_to_hcd(musb)); - /* FIXME we need to be able to register another - * gadget driver here and have everything work; - * that currently misbehaves. - */ - } - - if (!is_otg_enabled(musb)) - musb_stop(musb); - - pm_runtime_put(musb->controller); - - return 0; -} -#endif - -/* ----------------------------------------------------------------------- */ - -/* lifecycle operations called through plat_uds.c */ - -void musb_g_resume(struct musb *musb) -{ -#ifndef __UBOOT__ - musb->is_suspended = 0; - switch (musb->xceiv->state) { - case OTG_STATE_B_IDLE: - break; - case OTG_STATE_B_WAIT_ACON: - case OTG_STATE_B_PERIPHERAL: - musb->is_active = 1; - if (musb->gadget_driver && musb->gadget_driver->resume) { - spin_unlock(&musb->lock); - musb->gadget_driver->resume(&musb->g); - spin_lock(&musb->lock); - } - break; - default: - WARNING("unhandled RESUME transition (%s)\n", - otg_state_string(musb->xceiv->state)); - } -#endif -} - -/* called when SOF packets stop for 3+ msec */ -void musb_g_suspend(struct musb *musb) -{ -#ifndef __UBOOT__ - u8 devctl; - - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - dev_dbg(musb->controller, "devctl %02x\n", devctl); - - switch (musb->xceiv->state) { - case OTG_STATE_B_IDLE: - if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) - musb->xceiv->state = OTG_STATE_B_PERIPHERAL; - break; - case OTG_STATE_B_PERIPHERAL: - musb->is_suspended = 1; - if (musb->gadget_driver && musb->gadget_driver->suspend) { - spin_unlock(&musb->lock); - musb->gadget_driver->suspend(&musb->g); - spin_lock(&musb->lock); - } - break; - default: - /* REVISIT if B_HOST, clear DEVCTL.HOSTREQ; - * A_PERIPHERAL may need care too - */ - WARNING("unhandled SUSPEND transition (%s)\n", - otg_state_string(musb->xceiv->state)); - } -#endif -} - -/* Called during SRP */ -void musb_g_wakeup(struct musb *musb) -{ - musb_gadget_wakeup(&musb->g); -} - -/* called when VBUS drops below session threshold, and in other cases */ -void musb_g_disconnect(struct musb *musb) -{ - void __iomem *mregs = musb->mregs; - u8 devctl = musb_readb(mregs, MUSB_DEVCTL); - - dev_dbg(musb->controller, "devctl %02x\n", devctl); - - /* clear HR */ - musb_writeb(mregs, MUSB_DEVCTL, devctl & MUSB_DEVCTL_SESSION); - - /* don't draw vbus until new b-default session */ - (void) musb_gadget_vbus_draw(&musb->g, 0); - - musb->g.speed = USB_SPEED_UNKNOWN; - if (musb->gadget_driver && musb->gadget_driver->disconnect) { - spin_unlock(&musb->lock); - musb->gadget_driver->disconnect(&musb->g); - spin_lock(&musb->lock); - } - -#ifndef __UBOOT__ - switch (musb->xceiv->state) { - default: - dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n", - otg_state_string(musb->xceiv->state)); - musb->xceiv->state = OTG_STATE_A_IDLE; - MUSB_HST_MODE(musb); - break; - case OTG_STATE_A_PERIPHERAL: - musb->xceiv->state = OTG_STATE_A_WAIT_BCON; - MUSB_HST_MODE(musb); - break; - case OTG_STATE_B_WAIT_ACON: - case OTG_STATE_B_HOST: - case OTG_STATE_B_PERIPHERAL: - case OTG_STATE_B_IDLE: - musb->xceiv->state = OTG_STATE_B_IDLE; - break; - case OTG_STATE_B_SRP_INIT: - break; - } -#endif - - musb->is_active = 0; -} - -void musb_g_reset(struct musb *musb) -__releases(musb->lock) -__acquires(musb->lock) -{ - void __iomem *mbase = musb->mregs; - u8 devctl = musb_readb(mbase, MUSB_DEVCTL); - u8 power; - -#ifndef __UBOOT__ - dev_dbg(musb->controller, "<== %s addr=%x driver '%s'\n", - (devctl & MUSB_DEVCTL_BDEVICE) - ? "B-Device" : "A-Device", - musb_readb(mbase, MUSB_FADDR), - musb->gadget_driver - ? musb->gadget_driver->driver.name - : NULL - ); -#endif - - /* report disconnect, if we didn't already (flushing EP state) */ - if (musb->g.speed != USB_SPEED_UNKNOWN) - musb_g_disconnect(musb); - - /* clear HR */ - else if (devctl & MUSB_DEVCTL_HR) - musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); - - - /* what speed did we negotiate? */ - power = musb_readb(mbase, MUSB_POWER); - musb->g.speed = (power & MUSB_POWER_HSMODE) - ? USB_SPEED_HIGH : USB_SPEED_FULL; - - /* start in USB_STATE_DEFAULT */ - musb->is_active = 1; - musb->is_suspended = 0; - MUSB_DEV_MODE(musb); - musb->address = 0; - musb->ep0_state = MUSB_EP0_STAGE_SETUP; - - musb->may_wakeup = 0; - musb->g.b_hnp_enable = 0; - musb->g.a_alt_hnp_support = 0; - musb->g.a_hnp_support = 0; - -#ifndef __UBOOT__ - /* Normal reset, as B-Device; - * or else after HNP, as A-Device - */ - if (devctl & MUSB_DEVCTL_BDEVICE) { - musb->xceiv->state = OTG_STATE_B_PERIPHERAL; - musb->g.is_a_peripheral = 0; - } else if (is_otg_enabled(musb)) { - musb->xceiv->state = OTG_STATE_A_PERIPHERAL; - musb->g.is_a_peripheral = 1; - } else - WARN_ON(1); - - /* start with default limits on VBUS power draw */ - (void) musb_gadget_vbus_draw(&musb->g, - is_otg_enabled(musb) ? 8 : 100); -#endif -} diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_gadget.h b/qemu/roms/u-boot/drivers/usb/musb-new/musb_gadget.h deleted file mode 100644 index 392f701a8..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_gadget.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * MUSB OTG driver peripheral defines - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __MUSB_GADGET_H -#define __MUSB_GADGET_H - -#include <linux/list.h> -#ifdef __UBOOT__ -#include <asm/byteorder.h> -#include <asm/errno.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#endif - -enum buffer_map_state { - UN_MAPPED = 0, - PRE_MAPPED, - MUSB_MAPPED -}; - -struct musb_request { - struct usb_request request; - struct list_head list; - struct musb_ep *ep; - struct musb *musb; - u8 tx; /* endpoint direction */ - u8 epnum; - enum buffer_map_state map_state; -}; - -static inline struct musb_request *to_musb_request(struct usb_request *req) -{ - return req ? container_of(req, struct musb_request, request) : NULL; -} - -extern struct usb_request * -musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags); -extern void musb_free_request(struct usb_ep *ep, struct usb_request *req); - - -/* - * struct musb_ep - peripheral side view of endpoint rx or tx side - */ -struct musb_ep { - /* stuff towards the head is basically write-once. */ - struct usb_ep end_point; - char name[12]; - struct musb_hw_ep *hw_ep; - struct musb *musb; - u8 current_epnum; - - /* ... when enabled/disabled ... */ - u8 type; - u8 is_in; - u16 packet_sz; - const struct usb_endpoint_descriptor *desc; - struct dma_channel *dma; - - /* later things are modified based on usage */ - struct list_head req_list; - - u8 wedged; - - /* true if lock must be dropped but req_list may not be advanced */ - u8 busy; - - u8 hb_mult; -}; - -static inline struct musb_ep *to_musb_ep(struct usb_ep *ep) -{ - return ep ? container_of(ep, struct musb_ep, end_point) : NULL; -} - -static inline struct musb_request *next_request(struct musb_ep *ep) -{ - struct list_head *queue = &ep->req_list; - - if (list_empty(queue)) - return NULL; - return container_of(queue->next, struct musb_request, list); -} - -extern void musb_g_tx(struct musb *musb, u8 epnum); -extern void musb_g_rx(struct musb *musb, u8 epnum); - -extern const struct usb_ep_ops musb_g_ep0_ops; - -extern int musb_gadget_setup(struct musb *); -extern void musb_gadget_cleanup(struct musb *); - -extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int); - -extern void musb_ep_restart(struct musb *, struct musb_request *); - -#ifdef __UBOOT__ -int musb_gadget_start(struct usb_gadget *g, struct usb_gadget_driver *driver); -#endif -#endif /* __MUSB_GADGET_H */ diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_gadget_ep0.c b/qemu/roms/u-boot/drivers/usb/musb-new/musb_gadget_ep0.c deleted file mode 100644 index 6599d386d..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_gadget_ep0.c +++ /dev/null @@ -1,1089 +0,0 @@ -/* - * MUSB OTG peripheral driver ep0 handling - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#define __UBOOT__ -#ifndef __UBOOT__ -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/spinlock.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#else -#include <common.h> -#include "linux-compat.h" -#endif - -#include "musb_core.h" - -/* ep0 is always musb->endpoints[0].ep_in */ -#define next_ep0_request(musb) next_in_request(&(musb)->endpoints[0]) - -/* - * locking note: we use only the controller lock, for simpler correctness. - * It's always held with IRQs blocked. - * - * It protects the ep0 request queue as well as ep0_state, not just the - * controller and indexed registers. And that lock stays held unless it - * needs to be dropped to allow reentering this driver ... like upcalls to - * the gadget driver, or adjusting endpoint halt status. - */ - -static char *decode_ep0stage(u8 stage) -{ - switch (stage) { - case MUSB_EP0_STAGE_IDLE: return "idle"; - case MUSB_EP0_STAGE_SETUP: return "setup"; - case MUSB_EP0_STAGE_TX: return "in"; - case MUSB_EP0_STAGE_RX: return "out"; - case MUSB_EP0_STAGE_ACKWAIT: return "wait"; - case MUSB_EP0_STAGE_STATUSIN: return "in/status"; - case MUSB_EP0_STAGE_STATUSOUT: return "out/status"; - default: return "?"; - } -} - -/* handle a standard GET_STATUS request - * Context: caller holds controller lock - */ -static int service_tx_status_request( - struct musb *musb, - const struct usb_ctrlrequest *ctrlrequest) -{ - void __iomem *mbase = musb->mregs; - int handled = 1; - u8 result[2], epnum = 0; - const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK; - - result[1] = 0; - - switch (recip) { - case USB_RECIP_DEVICE: - result[0] = musb->is_self_powered << USB_DEVICE_SELF_POWERED; - result[0] |= musb->may_wakeup << USB_DEVICE_REMOTE_WAKEUP; - if (musb->g.is_otg) { - result[0] |= musb->g.b_hnp_enable - << USB_DEVICE_B_HNP_ENABLE; - result[0] |= musb->g.a_alt_hnp_support - << USB_DEVICE_A_ALT_HNP_SUPPORT; - result[0] |= musb->g.a_hnp_support - << USB_DEVICE_A_HNP_SUPPORT; - } - break; - - case USB_RECIP_INTERFACE: - result[0] = 0; - break; - - case USB_RECIP_ENDPOINT: { - int is_in; - struct musb_ep *ep; - u16 tmp; - void __iomem *regs; - - epnum = (u8) ctrlrequest->wIndex; - if (!epnum) { - result[0] = 0; - break; - } - - is_in = epnum & USB_DIR_IN; - if (is_in) { - epnum &= 0x0f; - ep = &musb->endpoints[epnum].ep_in; - } else { - ep = &musb->endpoints[epnum].ep_out; - } - regs = musb->endpoints[epnum].regs; - - if (epnum >= MUSB_C_NUM_EPS || !ep->desc) { - handled = -EINVAL; - break; - } - - musb_ep_select(mbase, epnum); - if (is_in) - tmp = musb_readw(regs, MUSB_TXCSR) - & MUSB_TXCSR_P_SENDSTALL; - else - tmp = musb_readw(regs, MUSB_RXCSR) - & MUSB_RXCSR_P_SENDSTALL; - musb_ep_select(mbase, 0); - - result[0] = tmp ? 1 : 0; - } break; - - default: - /* class, vendor, etc ... delegate */ - handled = 0; - break; - } - - /* fill up the fifo; caller updates csr0 */ - if (handled > 0) { - u16 len = le16_to_cpu(ctrlrequest->wLength); - - if (len > 2) - len = 2; - musb_write_fifo(&musb->endpoints[0], len, result); - } - - return handled; -} - -/* - * handle a control-IN request, the end0 buffer contains the current request - * that is supposed to be a standard control request. Assumes the fifo to - * be at least 2 bytes long. - * - * @return 0 if the request was NOT HANDLED, - * < 0 when error - * > 0 when the request is processed - * - * Context: caller holds controller lock - */ -static int -service_in_request(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest) -{ - int handled = 0; /* not handled */ - - if ((ctrlrequest->bRequestType & USB_TYPE_MASK) - == USB_TYPE_STANDARD) { - switch (ctrlrequest->bRequest) { - case USB_REQ_GET_STATUS: - handled = service_tx_status_request(musb, - ctrlrequest); - break; - - /* case USB_REQ_SYNC_FRAME: */ - - default: - break; - } - } - return handled; -} - -/* - * Context: caller holds controller lock - */ -static void musb_g_ep0_giveback(struct musb *musb, struct usb_request *req) -{ - musb_g_giveback(&musb->endpoints[0].ep_in, req, 0); -} - -/* - * Tries to start B-device HNP negotiation if enabled via sysfs - */ -static inline void musb_try_b_hnp_enable(struct musb *musb) -{ - void __iomem *mbase = musb->mregs; - u8 devctl; - - dev_dbg(musb->controller, "HNP: Setting HR\n"); - devctl = musb_readb(mbase, MUSB_DEVCTL); - musb_writeb(mbase, MUSB_DEVCTL, devctl | MUSB_DEVCTL_HR); -} - -/* - * Handle all control requests with no DATA stage, including standard - * requests such as: - * USB_REQ_SET_CONFIGURATION, USB_REQ_SET_INTERFACE, unrecognized - * always delegated to the gadget driver - * USB_REQ_SET_ADDRESS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE - * always handled here, except for class/vendor/... features - * - * Context: caller holds controller lock - */ -static int -service_zero_data_request(struct musb *musb, - struct usb_ctrlrequest *ctrlrequest) -__releases(musb->lock) -__acquires(musb->lock) -{ - int handled = -EINVAL; - void __iomem *mbase = musb->mregs; - const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK; - - /* the gadget driver handles everything except what we MUST handle */ - if ((ctrlrequest->bRequestType & USB_TYPE_MASK) - == USB_TYPE_STANDARD) { - switch (ctrlrequest->bRequest) { - case USB_REQ_SET_ADDRESS: - /* change it after the status stage */ - musb->set_address = true; - musb->address = (u8) (ctrlrequest->wValue & 0x7f); - handled = 1; - break; - - case USB_REQ_CLEAR_FEATURE: - switch (recip) { - case USB_RECIP_DEVICE: - if (ctrlrequest->wValue - != USB_DEVICE_REMOTE_WAKEUP) - break; - musb->may_wakeup = 0; - handled = 1; - break; - case USB_RECIP_INTERFACE: - break; - case USB_RECIP_ENDPOINT:{ - const u8 epnum = - ctrlrequest->wIndex & 0x0f; - struct musb_ep *musb_ep; - struct musb_hw_ep *ep; - struct musb_request *request; - void __iomem *regs; - int is_in; - u16 csr; - - if (epnum == 0 || epnum >= MUSB_C_NUM_EPS || - ctrlrequest->wValue != USB_ENDPOINT_HALT) - break; - - ep = musb->endpoints + epnum; - regs = ep->regs; - is_in = ctrlrequest->wIndex & USB_DIR_IN; - if (is_in) - musb_ep = &ep->ep_in; - else - musb_ep = &ep->ep_out; - if (!musb_ep->desc) - break; - - handled = 1; - /* Ignore request if endpoint is wedged */ - if (musb_ep->wedged) - break; - - musb_ep_select(mbase, epnum); - if (is_in) { - csr = musb_readw(regs, MUSB_TXCSR); - csr |= MUSB_TXCSR_CLRDATATOG | - MUSB_TXCSR_P_WZC_BITS; - csr &= ~(MUSB_TXCSR_P_SENDSTALL | - MUSB_TXCSR_P_SENTSTALL | - MUSB_TXCSR_TXPKTRDY); - musb_writew(regs, MUSB_TXCSR, csr); - } else { - csr = musb_readw(regs, MUSB_RXCSR); - csr |= MUSB_RXCSR_CLRDATATOG | - MUSB_RXCSR_P_WZC_BITS; - csr &= ~(MUSB_RXCSR_P_SENDSTALL | - MUSB_RXCSR_P_SENTSTALL); - musb_writew(regs, MUSB_RXCSR, csr); - } - - /* Maybe start the first request in the queue */ - request = next_request(musb_ep); - if (!musb_ep->busy && request) { - dev_dbg(musb->controller, "restarting the request\n"); - musb_ep_restart(musb, request); - } - - /* select ep0 again */ - musb_ep_select(mbase, 0); - } break; - default: - /* class, vendor, etc ... delegate */ - handled = 0; - break; - } - break; - - case USB_REQ_SET_FEATURE: - switch (recip) { - case USB_RECIP_DEVICE: - handled = 1; - switch (ctrlrequest->wValue) { - case USB_DEVICE_REMOTE_WAKEUP: - musb->may_wakeup = 1; - break; - case USB_DEVICE_TEST_MODE: - if (musb->g.speed != USB_SPEED_HIGH) - goto stall; - if (ctrlrequest->wIndex & 0xff) - goto stall; - - switch (ctrlrequest->wIndex >> 8) { - case 1: - pr_debug("TEST_J\n"); - /* TEST_J */ - musb->test_mode_nr = - MUSB_TEST_J; - break; - case 2: - /* TEST_K */ - pr_debug("TEST_K\n"); - musb->test_mode_nr = - MUSB_TEST_K; - break; - case 3: - /* TEST_SE0_NAK */ - pr_debug("TEST_SE0_NAK\n"); - musb->test_mode_nr = - MUSB_TEST_SE0_NAK; - break; - case 4: - /* TEST_PACKET */ - pr_debug("TEST_PACKET\n"); - musb->test_mode_nr = - MUSB_TEST_PACKET; - break; - - case 0xc0: - /* TEST_FORCE_HS */ - pr_debug("TEST_FORCE_HS\n"); - musb->test_mode_nr = - MUSB_TEST_FORCE_HS; - break; - case 0xc1: - /* TEST_FORCE_FS */ - pr_debug("TEST_FORCE_FS\n"); - musb->test_mode_nr = - MUSB_TEST_FORCE_FS; - break; - case 0xc2: - /* TEST_FIFO_ACCESS */ - pr_debug("TEST_FIFO_ACCESS\n"); - musb->test_mode_nr = - MUSB_TEST_FIFO_ACCESS; - break; - case 0xc3: - /* TEST_FORCE_HOST */ - pr_debug("TEST_FORCE_HOST\n"); - musb->test_mode_nr = - MUSB_TEST_FORCE_HOST; - break; - default: - goto stall; - } - - /* enter test mode after irq */ - if (handled > 0) - musb->test_mode = true; - break; - case USB_DEVICE_B_HNP_ENABLE: - if (!musb->g.is_otg) - goto stall; - musb->g.b_hnp_enable = 1; - musb_try_b_hnp_enable(musb); - break; - case USB_DEVICE_A_HNP_SUPPORT: - if (!musb->g.is_otg) - goto stall; - musb->g.a_hnp_support = 1; - break; - case USB_DEVICE_A_ALT_HNP_SUPPORT: - if (!musb->g.is_otg) - goto stall; - musb->g.a_alt_hnp_support = 1; - break; - case USB_DEVICE_DEBUG_MODE: - handled = 0; - break; -stall: - default: - handled = -EINVAL; - break; - } - break; - - case USB_RECIP_INTERFACE: - break; - - case USB_RECIP_ENDPOINT:{ - const u8 epnum = - ctrlrequest->wIndex & 0x0f; - struct musb_ep *musb_ep; - struct musb_hw_ep *ep; - void __iomem *regs; - int is_in; - u16 csr; - - if (epnum == 0 || epnum >= MUSB_C_NUM_EPS || - ctrlrequest->wValue != USB_ENDPOINT_HALT) - break; - - ep = musb->endpoints + epnum; - regs = ep->regs; - is_in = ctrlrequest->wIndex & USB_DIR_IN; - if (is_in) - musb_ep = &ep->ep_in; - else - musb_ep = &ep->ep_out; - if (!musb_ep->desc) - break; - - musb_ep_select(mbase, epnum); - if (is_in) { - csr = musb_readw(regs, MUSB_TXCSR); - if (csr & MUSB_TXCSR_FIFONOTEMPTY) - csr |= MUSB_TXCSR_FLUSHFIFO; - csr |= MUSB_TXCSR_P_SENDSTALL - | MUSB_TXCSR_CLRDATATOG - | MUSB_TXCSR_P_WZC_BITS; - musb_writew(regs, MUSB_TXCSR, csr); - } else { - csr = musb_readw(regs, MUSB_RXCSR); - csr |= MUSB_RXCSR_P_SENDSTALL - | MUSB_RXCSR_FLUSHFIFO - | MUSB_RXCSR_CLRDATATOG - | MUSB_RXCSR_P_WZC_BITS; - musb_writew(regs, MUSB_RXCSR, csr); - } - - /* select ep0 again */ - musb_ep_select(mbase, 0); - handled = 1; - } break; - - default: - /* class, vendor, etc ... delegate */ - handled = 0; - break; - } - break; - default: - /* delegate SET_CONFIGURATION, etc */ - handled = 0; - } - } else - handled = 0; - return handled; -} - -/* we have an ep0out data packet - * Context: caller holds controller lock - */ -static void ep0_rxstate(struct musb *musb) -{ - void __iomem *regs = musb->control_ep->regs; - struct musb_request *request; - struct usb_request *req; - u16 count, csr; - - request = next_ep0_request(musb); - req = &request->request; - - /* read packet and ack; or stall because of gadget driver bug: - * should have provided the rx buffer before setup() returned. - */ - if (req) { - void *buf = req->buf + req->actual; - unsigned len = req->length - req->actual; - - /* read the buffer */ - count = musb_readb(regs, MUSB_COUNT0); - if (count > len) { - req->status = -EOVERFLOW; - count = len; - } - musb_read_fifo(&musb->endpoints[0], count, buf); - req->actual += count; - csr = MUSB_CSR0_P_SVDRXPKTRDY; - if (count < 64 || req->actual == req->length) { - musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; - csr |= MUSB_CSR0_P_DATAEND; - } else - req = NULL; - } else - csr = MUSB_CSR0_P_SVDRXPKTRDY | MUSB_CSR0_P_SENDSTALL; - - - /* Completion handler may choose to stall, e.g. because the - * message just received holds invalid data. - */ - if (req) { - musb->ackpend = csr; - musb_g_ep0_giveback(musb, req); - if (!musb->ackpend) - return; - musb->ackpend = 0; - } - musb_ep_select(musb->mregs, 0); - musb_writew(regs, MUSB_CSR0, csr); -} - -/* - * transmitting to the host (IN), this code might be called from IRQ - * and from kernel thread. - * - * Context: caller holds controller lock - */ -static void ep0_txstate(struct musb *musb) -{ - void __iomem *regs = musb->control_ep->regs; - struct musb_request *req = next_ep0_request(musb); - struct usb_request *request; - u16 csr = MUSB_CSR0_TXPKTRDY; - u8 *fifo_src; - u8 fifo_count; - - if (!req) { - /* WARN_ON(1); */ - dev_dbg(musb->controller, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0)); - return; - } - - request = &req->request; - - /* load the data */ - fifo_src = (u8 *) request->buf + request->actual; - fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE, - request->length - request->actual); - musb_write_fifo(&musb->endpoints[0], fifo_count, fifo_src); - request->actual += fifo_count; - - /* update the flags */ - if (fifo_count < MUSB_MAX_END0_PACKET - || (request->actual == request->length - && !request->zero)) { - musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT; - csr |= MUSB_CSR0_P_DATAEND; - } else - request = NULL; - - /* report completions as soon as the fifo's loaded; there's no - * win in waiting till this last packet gets acked. (other than - * very precise fault reporting, needed by USB TMC; possible with - * this hardware, but not usable from portable gadget drivers.) - */ - if (request) { - musb->ackpend = csr; - musb_g_ep0_giveback(musb, request); - if (!musb->ackpend) - return; - musb->ackpend = 0; - } - - /* send it out, triggering a "txpktrdy cleared" irq */ - musb_ep_select(musb->mregs, 0); - musb_writew(regs, MUSB_CSR0, csr); -} - -/* - * Read a SETUP packet (struct usb_ctrlrequest) from the hardware. - * Fields are left in USB byte-order. - * - * Context: caller holds controller lock. - */ -static void -musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req) -{ - struct musb_request *r; - void __iomem *regs = musb->control_ep->regs; - - musb_read_fifo(&musb->endpoints[0], sizeof *req, (u8 *)req); - - /* NOTE: earlier 2.6 versions changed setup packets to host - * order, but now USB packets always stay in USB byte order. - */ - dev_dbg(musb->controller, "SETUP req%02x.%02x v%04x i%04x l%d\n", - req->bRequestType, - req->bRequest, - le16_to_cpu(req->wValue), - le16_to_cpu(req->wIndex), - le16_to_cpu(req->wLength)); - - /* clean up any leftover transfers */ - r = next_ep0_request(musb); - if (r) - musb_g_ep0_giveback(musb, &r->request); - - /* For zero-data requests we want to delay the STATUS stage to - * avoid SETUPEND errors. If we read data (OUT), delay accepting - * packets until there's a buffer to store them in. - * - * If we write data, the controller acts happier if we enable - * the TX FIFO right away, and give the controller a moment - * to switch modes... - */ - musb->set_address = false; - musb->ackpend = MUSB_CSR0_P_SVDRXPKTRDY; - if (req->wLength == 0) { - if (req->bRequestType & USB_DIR_IN) - musb->ackpend |= MUSB_CSR0_TXPKTRDY; - musb->ep0_state = MUSB_EP0_STAGE_ACKWAIT; - } else if (req->bRequestType & USB_DIR_IN) { - musb->ep0_state = MUSB_EP0_STAGE_TX; - musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDRXPKTRDY); - while ((musb_readw(regs, MUSB_CSR0) - & MUSB_CSR0_RXPKTRDY) != 0) - cpu_relax(); - musb->ackpend = 0; - } else - musb->ep0_state = MUSB_EP0_STAGE_RX; -} - -static int -forward_to_driver(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest) -__releases(musb->lock) -__acquires(musb->lock) -{ - int retval; - if (!musb->gadget_driver) - return -EOPNOTSUPP; - spin_unlock(&musb->lock); - retval = musb->gadget_driver->setup(&musb->g, ctrlrequest); - spin_lock(&musb->lock); - return retval; -} - -/* - * Handle peripheral ep0 interrupt - * - * Context: irq handler; we won't re-enter the driver that way. - */ -irqreturn_t musb_g_ep0_irq(struct musb *musb) -{ - u16 csr; - u16 len; - void __iomem *mbase = musb->mregs; - void __iomem *regs = musb->endpoints[0].regs; - irqreturn_t retval = IRQ_NONE; - - musb_ep_select(mbase, 0); /* select ep0 */ - csr = musb_readw(regs, MUSB_CSR0); - len = musb_readb(regs, MUSB_COUNT0); - - dev_dbg(musb->controller, "csr %04x, count %d, myaddr %d, ep0stage %s\n", - csr, len, - musb_readb(mbase, MUSB_FADDR), - decode_ep0stage(musb->ep0_state)); - - if (csr & MUSB_CSR0_P_DATAEND) { - /* - * If DATAEND is set we should not call the callback, - * hence the status stage is not complete. - */ - return IRQ_HANDLED; - } - - /* I sent a stall.. need to acknowledge it now.. */ - if (csr & MUSB_CSR0_P_SENTSTALL) { - musb_writew(regs, MUSB_CSR0, - csr & ~MUSB_CSR0_P_SENTSTALL); - retval = IRQ_HANDLED; - musb->ep0_state = MUSB_EP0_STAGE_IDLE; - csr = musb_readw(regs, MUSB_CSR0); - } - - /* request ended "early" */ - if (csr & MUSB_CSR0_P_SETUPEND) { - musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDSETUPEND); - retval = IRQ_HANDLED; - /* Transition into the early status phase */ - switch (musb->ep0_state) { - case MUSB_EP0_STAGE_TX: - musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT; - break; - case MUSB_EP0_STAGE_RX: - musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; - break; - default: - ERR("SetupEnd came in a wrong ep0stage %s\n", - decode_ep0stage(musb->ep0_state)); - } - csr = musb_readw(regs, MUSB_CSR0); - /* NOTE: request may need completion */ - } - - /* docs from Mentor only describe tx, rx, and idle/setup states. - * we need to handle nuances around status stages, and also the - * case where status and setup stages come back-to-back ... - */ - switch (musb->ep0_state) { - - case MUSB_EP0_STAGE_TX: - /* irq on clearing txpktrdy */ - if ((csr & MUSB_CSR0_TXPKTRDY) == 0) { - ep0_txstate(musb); - retval = IRQ_HANDLED; - } - break; - - case MUSB_EP0_STAGE_RX: - /* irq on set rxpktrdy */ - if (csr & MUSB_CSR0_RXPKTRDY) { - ep0_rxstate(musb); - retval = IRQ_HANDLED; - } - break; - - case MUSB_EP0_STAGE_STATUSIN: - /* end of sequence #2 (OUT/RX state) or #3 (no data) */ - - /* update address (if needed) only @ the end of the - * status phase per usb spec, which also guarantees - * we get 10 msec to receive this irq... until this - * is done we won't see the next packet. - */ - if (musb->set_address) { - musb->set_address = false; - musb_writeb(mbase, MUSB_FADDR, musb->address); - } - - /* enter test mode if needed (exit by reset) */ - else if (musb->test_mode) { - dev_dbg(musb->controller, "entering TESTMODE\n"); - - if (MUSB_TEST_PACKET == musb->test_mode_nr) - musb_load_testpacket(musb); - - musb_writeb(mbase, MUSB_TESTMODE, - musb->test_mode_nr); - } - /* FALLTHROUGH */ - - case MUSB_EP0_STAGE_STATUSOUT: - /* end of sequence #1: write to host (TX state) */ - { - struct musb_request *req; - - req = next_ep0_request(musb); - if (req) - musb_g_ep0_giveback(musb, &req->request); - } - - /* - * In case when several interrupts can get coalesced, - * check to see if we've already received a SETUP packet... - */ - if (csr & MUSB_CSR0_RXPKTRDY) - goto setup; - - retval = IRQ_HANDLED; - musb->ep0_state = MUSB_EP0_STAGE_IDLE; - break; - - case MUSB_EP0_STAGE_IDLE: - /* - * This state is typically (but not always) indiscernible - * from the status states since the corresponding interrupts - * tend to happen within too little period of time (with only - * a zero-length packet in between) and so get coalesced... - */ - retval = IRQ_HANDLED; - musb->ep0_state = MUSB_EP0_STAGE_SETUP; - /* FALLTHROUGH */ - - case MUSB_EP0_STAGE_SETUP: -setup: - if (csr & MUSB_CSR0_RXPKTRDY) { - struct usb_ctrlrequest setup; - int handled = 0; - - if (len != 8) { - ERR("SETUP packet len %d != 8 ?\n", len); - break; - } - musb_read_setup(musb, &setup); - retval = IRQ_HANDLED; - - /* sometimes the RESET won't be reported */ - if (unlikely(musb->g.speed == USB_SPEED_UNKNOWN)) { - u8 power; - - printk(KERN_NOTICE "%s: peripheral reset " - "irq lost!\n", - musb_driver_name); - power = musb_readb(mbase, MUSB_POWER); - musb->g.speed = (power & MUSB_POWER_HSMODE) - ? USB_SPEED_HIGH : USB_SPEED_FULL; - - } - - switch (musb->ep0_state) { - - /* sequence #3 (no data stage), includes requests - * we can't forward (notably SET_ADDRESS and the - * device/endpoint feature set/clear operations) - * plus SET_CONFIGURATION and others we must - */ - case MUSB_EP0_STAGE_ACKWAIT: - handled = service_zero_data_request( - musb, &setup); - - /* - * We're expecting no data in any case, so - * always set the DATAEND bit -- doing this - * here helps avoid SetupEnd interrupt coming - * in the idle stage when we're stalling... - */ - musb->ackpend |= MUSB_CSR0_P_DATAEND; - - /* status stage might be immediate */ - if (handled > 0) - musb->ep0_state = - MUSB_EP0_STAGE_STATUSIN; - break; - - /* sequence #1 (IN to host), includes GET_STATUS - * requests that we can't forward, GET_DESCRIPTOR - * and others that we must - */ - case MUSB_EP0_STAGE_TX: - handled = service_in_request(musb, &setup); - if (handled > 0) { - musb->ackpend = MUSB_CSR0_TXPKTRDY - | MUSB_CSR0_P_DATAEND; - musb->ep0_state = - MUSB_EP0_STAGE_STATUSOUT; - } - break; - - /* sequence #2 (OUT from host), always forward */ - default: /* MUSB_EP0_STAGE_RX */ - break; - } - - dev_dbg(musb->controller, "handled %d, csr %04x, ep0stage %s\n", - handled, csr, - decode_ep0stage(musb->ep0_state)); - - /* unless we need to delegate this to the gadget - * driver, we know how to wrap this up: csr0 has - * not yet been written. - */ - if (handled < 0) - goto stall; - else if (handled > 0) - goto finish; - - handled = forward_to_driver(musb, &setup); - if (handled < 0) { - musb_ep_select(mbase, 0); -stall: - dev_dbg(musb->controller, "stall (%d)\n", handled); - musb->ackpend |= MUSB_CSR0_P_SENDSTALL; - musb->ep0_state = MUSB_EP0_STAGE_IDLE; -finish: - musb_writew(regs, MUSB_CSR0, - musb->ackpend); - musb->ackpend = 0; - } - } - break; - - case MUSB_EP0_STAGE_ACKWAIT: - /* This should not happen. But happens with tusb6010 with - * g_file_storage and high speed. Do nothing. - */ - retval = IRQ_HANDLED; - break; - - default: - /* "can't happen" */ - WARN_ON(1); - musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SENDSTALL); - musb->ep0_state = MUSB_EP0_STAGE_IDLE; - break; - } - - return retval; -} - - -static int -musb_g_ep0_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) -{ - /* always enabled */ - return -EINVAL; -} - -static int musb_g_ep0_disable(struct usb_ep *e) -{ - /* always enabled */ - return -EINVAL; -} - -static int -musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags) -{ - struct musb_ep *ep; - struct musb_request *req; - struct musb *musb; - int status; - unsigned long lockflags; - void __iomem *regs; - - if (!e || !r) - return -EINVAL; - - ep = to_musb_ep(e); - musb = ep->musb; - regs = musb->control_ep->regs; - - req = to_musb_request(r); - req->musb = musb; - req->request.actual = 0; - req->request.status = -EINPROGRESS; - req->tx = ep->is_in; - - spin_lock_irqsave(&musb->lock, lockflags); - - if (!list_empty(&ep->req_list)) { - status = -EBUSY; - goto cleanup; - } - - switch (musb->ep0_state) { - case MUSB_EP0_STAGE_RX: /* control-OUT data */ - case MUSB_EP0_STAGE_TX: /* control-IN data */ - case MUSB_EP0_STAGE_ACKWAIT: /* zero-length data */ - status = 0; - break; - default: - dev_dbg(musb->controller, "ep0 request queued in state %d\n", - musb->ep0_state); - status = -EINVAL; - goto cleanup; - } - - /* add request to the list */ - list_add_tail(&req->list, &ep->req_list); - - dev_dbg(musb->controller, "queue to %s (%s), length=%d\n", - ep->name, ep->is_in ? "IN/TX" : "OUT/RX", - req->request.length); - - musb_ep_select(musb->mregs, 0); - - /* sequence #1, IN ... start writing the data */ - if (musb->ep0_state == MUSB_EP0_STAGE_TX) - ep0_txstate(musb); - - /* sequence #3, no-data ... issue IN status */ - else if (musb->ep0_state == MUSB_EP0_STAGE_ACKWAIT) { - if (req->request.length) - status = -EINVAL; - else { - musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; - musb_writew(regs, MUSB_CSR0, - musb->ackpend | MUSB_CSR0_P_DATAEND); - musb->ackpend = 0; - musb_g_ep0_giveback(ep->musb, r); - } - - /* else for sequence #2 (OUT), caller provides a buffer - * before the next packet arrives. deferred responses - * (after SETUP is acked) are racey. - */ - } else if (musb->ackpend) { - musb_writew(regs, MUSB_CSR0, musb->ackpend); - musb->ackpend = 0; - } - -cleanup: - spin_unlock_irqrestore(&musb->lock, lockflags); - return status; -} - -static int musb_g_ep0_dequeue(struct usb_ep *ep, struct usb_request *req) -{ - /* we just won't support this */ - return -EINVAL; -} - -static int musb_g_ep0_halt(struct usb_ep *e, int value) -{ - struct musb_ep *ep; - struct musb *musb; - void __iomem *base, *regs; - unsigned long flags; - int status; - u16 csr; - - if (!e || !value) - return -EINVAL; - - ep = to_musb_ep(e); - musb = ep->musb; - base = musb->mregs; - regs = musb->control_ep->regs; - status = 0; - - spin_lock_irqsave(&musb->lock, flags); - - if (!list_empty(&ep->req_list)) { - status = -EBUSY; - goto cleanup; - } - - musb_ep_select(base, 0); - csr = musb->ackpend; - - switch (musb->ep0_state) { - - /* Stalls are usually issued after parsing SETUP packet, either - * directly in irq context from setup() or else later. - */ - case MUSB_EP0_STAGE_TX: /* control-IN data */ - case MUSB_EP0_STAGE_ACKWAIT: /* STALL for zero-length data */ - case MUSB_EP0_STAGE_RX: /* control-OUT data */ - csr = musb_readw(regs, MUSB_CSR0); - /* FALLTHROUGH */ - - /* It's also OK to issue stalls during callbacks when a non-empty - * DATA stage buffer has been read (or even written). - */ - case MUSB_EP0_STAGE_STATUSIN: /* control-OUT status */ - case MUSB_EP0_STAGE_STATUSOUT: /* control-IN status */ - - csr |= MUSB_CSR0_P_SENDSTALL; - musb_writew(regs, MUSB_CSR0, csr); - musb->ep0_state = MUSB_EP0_STAGE_IDLE; - musb->ackpend = 0; - break; - default: - dev_dbg(musb->controller, "ep0 can't halt in state %d\n", musb->ep0_state); - status = -EINVAL; - } - -cleanup: - spin_unlock_irqrestore(&musb->lock, flags); - return status; -} - -const struct usb_ep_ops musb_g_ep0_ops = { - .enable = musb_g_ep0_enable, - .disable = musb_g_ep0_disable, - .alloc_request = musb_alloc_request, - .free_request = musb_free_request, - .queue = musb_g_ep0_queue, - .dequeue = musb_g_ep0_dequeue, - .set_halt = musb_g_ep0_halt, -}; diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_host.c b/qemu/roms/u-boot/drivers/usb/musb-new/musb_host.c deleted file mode 100644 index 9a2cf59d9..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_host.c +++ /dev/null @@ -1,2400 +0,0 @@ -/* - * MUSB OTG driver host support - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#define __UBOOT__ -#ifndef __UBOOT__ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/dma-mapping.h> -#else -#include <common.h> -#include <usb.h> -#include "linux-compat.h" -#include "usb-compat.h" -#endif - -#include "musb_core.h" -#include "musb_host.h" - - -/* MUSB HOST status 22-mar-2006 - * - * - There's still lots of partial code duplication for fault paths, so - * they aren't handled as consistently as they need to be. - * - * - PIO mostly behaved when last tested. - * + including ep0, with all usbtest cases 9, 10 - * + usbtest 14 (ep0out) doesn't seem to run at all - * + double buffered OUT/TX endpoints saw stalls(!) with certain usbtest - * configurations, but otherwise double buffering passes basic tests. - * + for 2.6.N, for N > ~10, needs API changes for hcd framework. - * - * - DMA (CPPI) ... partially behaves, not currently recommended - * + about 1/15 the speed of typical EHCI implementations (PCI) - * + RX, all too often reqpkt seems to misbehave after tx - * + TX, no known issues (other than evident silicon issue) - * - * - DMA (Mentor/OMAP) ...has at least toggle update problems - * - * - [23-feb-2009] minimal traffic scheduling to avoid bulk RX packet - * starvation ... nothing yet for TX, interrupt, or bulk. - * - * - Not tested with HNP, but some SRP paths seem to behave. - * - * NOTE 24-August-2006: - * - * - Bulk traffic finally uses both sides of hardware ep1, freeing up an - * extra endpoint for periodic use enabling hub + keybd + mouse. That - * mostly works, except that with "usbnet" it's easy to trigger cases - * with "ping" where RX loses. (a) ping to davinci, even "ping -f", - * fine; but (b) ping _from_ davinci, even "ping -c 1", ICMP RX loses - * although ARP RX wins. (That test was done with a full speed link.) - */ - - -/* - * NOTE on endpoint usage: - * - * CONTROL transfers all go through ep0. BULK ones go through dedicated IN - * and OUT endpoints ... hardware is dedicated for those "async" queue(s). - * (Yes, bulk _could_ use more of the endpoints than that, and would even - * benefit from it.) - * - * INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints. - * So far that scheduling is both dumb and optimistic: the endpoint will be - * "claimed" until its software queue is no longer refilled. No multiplexing - * of transfers between endpoints, or anything clever. - */ - - -static void musb_ep_program(struct musb *musb, u8 epnum, - struct urb *urb, int is_out, - u8 *buf, u32 offset, u32 len); - -/* - * Clear TX fifo. Needed to avoid BABBLE errors. - */ -static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) -{ - struct musb *musb = ep->musb; - void __iomem *epio = ep->regs; - u16 csr; - u16 lastcsr = 0; - int retries = 1000; - - csr = musb_readw(epio, MUSB_TXCSR); - while (csr & MUSB_TXCSR_FIFONOTEMPTY) { - if (csr != lastcsr) - dev_dbg(musb->controller, "Host TX FIFONOTEMPTY csr: %02x\n", csr); - lastcsr = csr; - csr |= MUSB_TXCSR_FLUSHFIFO; - musb_writew(epio, MUSB_TXCSR, csr); - csr = musb_readw(epio, MUSB_TXCSR); - if (WARN(retries-- < 1, - "Could not flush host TX%d fifo: csr: %04x\n", - ep->epnum, csr)) - return; - mdelay(1); - } -} - -static void musb_h_ep0_flush_fifo(struct musb_hw_ep *ep) -{ - void __iomem *epio = ep->regs; - u16 csr; - int retries = 5; - - /* scrub any data left in the fifo */ - do { - csr = musb_readw(epio, MUSB_TXCSR); - if (!(csr & (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_RXPKTRDY))) - break; - musb_writew(epio, MUSB_TXCSR, MUSB_CSR0_FLUSHFIFO); - csr = musb_readw(epio, MUSB_TXCSR); - udelay(10); - } while (--retries); - - WARN(!retries, "Could not flush host TX%d fifo: csr: %04x\n", - ep->epnum, csr); - - /* and reset for the next transfer */ - musb_writew(epio, MUSB_TXCSR, 0); -} - -/* - * Start transmit. Caller is responsible for locking shared resources. - * musb must be locked. - */ -static inline void musb_h_tx_start(struct musb_hw_ep *ep) -{ - u16 txcsr; - - /* NOTE: no locks here; caller should lock and select EP */ - if (ep->epnum) { - txcsr = musb_readw(ep->regs, MUSB_TXCSR); - txcsr |= MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_H_WZC_BITS; - musb_writew(ep->regs, MUSB_TXCSR, txcsr); - } else { - txcsr = MUSB_CSR0_H_SETUPPKT | MUSB_CSR0_TXPKTRDY; - musb_writew(ep->regs, MUSB_CSR0, txcsr); - } - -} - -static inline void musb_h_tx_dma_start(struct musb_hw_ep *ep) -{ - u16 txcsr; - - /* NOTE: no locks here; caller should lock and select EP */ - txcsr = musb_readw(ep->regs, MUSB_TXCSR); - txcsr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_H_WZC_BITS; - if (is_cppi_enabled()) - txcsr |= MUSB_TXCSR_DMAMODE; - musb_writew(ep->regs, MUSB_TXCSR, txcsr); -} - -static void musb_ep_set_qh(struct musb_hw_ep *ep, int is_in, struct musb_qh *qh) -{ - if (is_in != 0 || ep->is_shared_fifo) - ep->in_qh = qh; - if (is_in == 0 || ep->is_shared_fifo) - ep->out_qh = qh; -} - -static struct musb_qh *musb_ep_get_qh(struct musb_hw_ep *ep, int is_in) -{ - return is_in ? ep->in_qh : ep->out_qh; -} - -/* - * Start the URB at the front of an endpoint's queue - * end must be claimed from the caller. - * - * Context: controller locked, irqs blocked - */ -static void -musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) -{ - u16 frame; - u32 len; - void __iomem *mbase = musb->mregs; - struct urb *urb = next_urb(qh); - void *buf = urb->transfer_buffer; - u32 offset = 0; - struct musb_hw_ep *hw_ep = qh->hw_ep; - unsigned pipe = urb->pipe; - u8 address = usb_pipedevice(pipe); - int epnum = hw_ep->epnum; - - /* initialize software qh state */ - qh->offset = 0; - qh->segsize = 0; - - /* gather right source of data */ - switch (qh->type) { - case USB_ENDPOINT_XFER_CONTROL: - /* control transfers always start with SETUP */ - is_in = 0; - musb->ep0_stage = MUSB_EP0_START; - buf = urb->setup_packet; - len = 8; - break; -#ifndef __UBOOT__ - case USB_ENDPOINT_XFER_ISOC: - qh->iso_idx = 0; - qh->frame = 0; - offset = urb->iso_frame_desc[0].offset; - len = urb->iso_frame_desc[0].length; - break; -#endif - default: /* bulk, interrupt */ - /* actual_length may be nonzero on retry paths */ - buf = urb->transfer_buffer + urb->actual_length; - len = urb->transfer_buffer_length - urb->actual_length; - } - - dev_dbg(musb->controller, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n", - qh, urb, address, qh->epnum, - is_in ? "in" : "out", - ({char *s; switch (qh->type) { - case USB_ENDPOINT_XFER_CONTROL: s = ""; break; - case USB_ENDPOINT_XFER_BULK: s = "-bulk"; break; -#ifndef __UBOOT__ - case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break; -#endif - default: s = "-intr"; break; - }; s; }), - epnum, buf + offset, len); - - /* Configure endpoint */ - musb_ep_set_qh(hw_ep, is_in, qh); - musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len); - - /* transmit may have more work: start it when it is time */ - if (is_in) - return; - - /* determine if the time is right for a periodic transfer */ - switch (qh->type) { -#ifndef __UBOOT__ - case USB_ENDPOINT_XFER_ISOC: -#endif - case USB_ENDPOINT_XFER_INT: - dev_dbg(musb->controller, "check whether there's still time for periodic Tx\n"); - frame = musb_readw(mbase, MUSB_FRAME); - /* FIXME this doesn't implement that scheduling policy ... - * or handle framecounter wrapping - */ -#ifndef __UBOOT__ - if ((urb->transfer_flags & URB_ISO_ASAP) - || (frame >= urb->start_frame)) { - /* REVISIT the SOF irq handler shouldn't duplicate - * this code; and we don't init urb->start_frame... - */ - qh->frame = 0; - goto start; - } else { -#endif - qh->frame = urb->start_frame; - /* enable SOF interrupt so we can count down */ - dev_dbg(musb->controller, "SOF for %d\n", epnum); -#if 1 /* ifndef CONFIG_ARCH_DAVINCI */ - musb_writeb(mbase, MUSB_INTRUSBE, 0xff); -#endif -#ifndef __UBOOT__ - } -#endif - break; - default: -start: - dev_dbg(musb->controller, "Start TX%d %s\n", epnum, - hw_ep->tx_channel ? "dma" : "pio"); - - if (!hw_ep->tx_channel) - musb_h_tx_start(hw_ep); - else if (is_cppi_enabled() || tusb_dma_omap()) - musb_h_tx_dma_start(hw_ep); - } -} - -/* Context: caller owns controller lock, IRQs are blocked */ -static void musb_giveback(struct musb *musb, struct urb *urb, int status) -__releases(musb->lock) -__acquires(musb->lock) -{ - dev_dbg(musb->controller, - "complete %p %pF (%d), dev%d ep%d%s, %d/%d\n", - urb, urb->complete, status, - usb_pipedevice(urb->pipe), - usb_pipeendpoint(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out", - urb->actual_length, urb->transfer_buffer_length - ); - - usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb); - spin_unlock(&musb->lock); - usb_hcd_giveback_urb(musb_to_hcd(musb), urb, status); - spin_lock(&musb->lock); -} - -/* For bulk/interrupt endpoints only */ -static inline void musb_save_toggle(struct musb_qh *qh, int is_in, - struct urb *urb) -{ - void __iomem *epio = qh->hw_ep->regs; - u16 csr; - - /* - * FIXME: the current Mentor DMA code seems to have - * problems getting toggle correct. - */ - - if (is_in) - csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE; - else - csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE; - - usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0); -} - -/* - * Advance this hardware endpoint's queue, completing the specified URB and - * advancing to either the next URB queued to that qh, or else invalidating - * that qh and advancing to the next qh scheduled after the current one. - * - * Context: caller owns controller lock, IRQs are blocked - */ -static void musb_advance_schedule(struct musb *musb, struct urb *urb, - struct musb_hw_ep *hw_ep, int is_in) -{ - struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in); - struct musb_hw_ep *ep = qh->hw_ep; - int ready = qh->is_ready; - int status; - - status = (urb->status == -EINPROGRESS) ? 0 : urb->status; - - /* save toggle eagerly, for paranoia */ - switch (qh->type) { - case USB_ENDPOINT_XFER_BULK: - case USB_ENDPOINT_XFER_INT: - musb_save_toggle(qh, is_in, urb); - break; -#ifndef __UBOOT__ - case USB_ENDPOINT_XFER_ISOC: - if (status == 0 && urb->error_count) - status = -EXDEV; - break; -#endif - } - - qh->is_ready = 0; - musb_giveback(musb, urb, status); - qh->is_ready = ready; - - /* reclaim resources (and bandwidth) ASAP; deschedule it, and - * invalidate qh as soon as list_empty(&hep->urb_list) - */ - if (list_empty(&qh->hep->urb_list)) { - struct list_head *head; - struct dma_controller *dma = musb->dma_controller; - - if (is_in) { - ep->rx_reinit = 1; - if (ep->rx_channel) { - dma->channel_release(ep->rx_channel); - ep->rx_channel = NULL; - } - } else { - ep->tx_reinit = 1; - if (ep->tx_channel) { - dma->channel_release(ep->tx_channel); - ep->tx_channel = NULL; - } - } - - /* Clobber old pointers to this qh */ - musb_ep_set_qh(ep, is_in, NULL); - qh->hep->hcpriv = NULL; - - switch (qh->type) { - - case USB_ENDPOINT_XFER_CONTROL: - case USB_ENDPOINT_XFER_BULK: - /* fifo policy for these lists, except that NAKing - * should rotate a qh to the end (for fairness). - */ - if (qh->mux == 1) { - head = qh->ring.prev; - list_del(&qh->ring); - kfree(qh); - qh = first_qh(head); - break; - } - - case USB_ENDPOINT_XFER_ISOC: - case USB_ENDPOINT_XFER_INT: - /* this is where periodic bandwidth should be - * de-allocated if it's tracked and allocated; - * and where we'd update the schedule tree... - */ - kfree(qh); - qh = NULL; - break; - } - } - - if (qh != NULL && qh->is_ready) { - dev_dbg(musb->controller, "... next ep%d %cX urb %p\n", - hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh)); - musb_start_urb(musb, is_in, qh); - } -} - -static u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr) -{ - /* we don't want fifo to fill itself again; - * ignore dma (various models), - * leave toggle alone (may not have been saved yet) - */ - csr |= MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_RXPKTRDY; - csr &= ~(MUSB_RXCSR_H_REQPKT - | MUSB_RXCSR_H_AUTOREQ - | MUSB_RXCSR_AUTOCLEAR); - - /* write 2x to allow double buffering */ - musb_writew(hw_ep->regs, MUSB_RXCSR, csr); - musb_writew(hw_ep->regs, MUSB_RXCSR, csr); - - /* flush writebuffer */ - return musb_readw(hw_ep->regs, MUSB_RXCSR); -} - -/* - * PIO RX for a packet (or part of it). - */ -static bool -musb_host_packet_rx(struct musb *musb, struct urb *urb, u8 epnum, u8 iso_err) -{ - u16 rx_count; - u8 *buf; - u16 csr; - bool done = false; - u32 length; - int do_flush = 0; - struct musb_hw_ep *hw_ep = musb->endpoints + epnum; - void __iomem *epio = hw_ep->regs; - struct musb_qh *qh = hw_ep->in_qh; - int pipe = urb->pipe; - void *buffer = urb->transfer_buffer; - - /* musb_ep_select(mbase, epnum); */ - rx_count = musb_readw(epio, MUSB_RXCOUNT); - dev_dbg(musb->controller, "RX%d count %d, buffer %p len %d/%d\n", epnum, rx_count, - urb->transfer_buffer, qh->offset, - urb->transfer_buffer_length); - - /* unload FIFO */ -#ifndef __UBOOT__ - if (usb_pipeisoc(pipe)) { - int status = 0; - struct usb_iso_packet_descriptor *d; - - if (iso_err) { - status = -EILSEQ; - urb->error_count++; - } - - d = urb->iso_frame_desc + qh->iso_idx; - buf = buffer + d->offset; - length = d->length; - if (rx_count > length) { - if (status == 0) { - status = -EOVERFLOW; - urb->error_count++; - } - dev_dbg(musb->controller, "** OVERFLOW %d into %d\n", rx_count, length); - do_flush = 1; - } else - length = rx_count; - urb->actual_length += length; - d->actual_length = length; - - d->status = status; - - /* see if we are done */ - done = (++qh->iso_idx >= urb->number_of_packets); - } else { -#endif - /* non-isoch */ - buf = buffer + qh->offset; - length = urb->transfer_buffer_length - qh->offset; - if (rx_count > length) { - if (urb->status == -EINPROGRESS) - urb->status = -EOVERFLOW; - dev_dbg(musb->controller, "** OVERFLOW %d into %d\n", rx_count, length); - do_flush = 1; - } else - length = rx_count; - urb->actual_length += length; - qh->offset += length; - - /* see if we are done */ - done = (urb->actual_length == urb->transfer_buffer_length) - || (rx_count < qh->maxpacket) - || (urb->status != -EINPROGRESS); - if (done - && (urb->status == -EINPROGRESS) - && (urb->transfer_flags & URB_SHORT_NOT_OK) - && (urb->actual_length - < urb->transfer_buffer_length)) - urb->status = -EREMOTEIO; -#ifndef __UBOOT__ - } -#endif - - musb_read_fifo(hw_ep, length, buf); - - csr = musb_readw(epio, MUSB_RXCSR); - csr |= MUSB_RXCSR_H_WZC_BITS; - if (unlikely(do_flush)) - musb_h_flush_rxfifo(hw_ep, csr); - else { - /* REVISIT this assumes AUTOCLEAR is never set */ - csr &= ~(MUSB_RXCSR_RXPKTRDY | MUSB_RXCSR_H_REQPKT); - if (!done) - csr |= MUSB_RXCSR_H_REQPKT; - musb_writew(epio, MUSB_RXCSR, csr); - } - - return done; -} - -/* we don't always need to reinit a given side of an endpoint... - * when we do, use tx/rx reinit routine and then construct a new CSR - * to address data toggle, NYET, and DMA or PIO. - * - * it's possible that driver bugs (especially for DMA) or aborting a - * transfer might have left the endpoint busier than it should be. - * the busy/not-empty tests are basically paranoia. - */ -static void -musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) -{ - u16 csr; - - /* NOTE: we know the "rx" fifo reinit never triggers for ep0. - * That always uses tx_reinit since ep0 repurposes TX register - * offsets; the initial SETUP packet is also a kind of OUT. - */ - - /* if programmed for Tx, put it in RX mode */ - if (ep->is_shared_fifo) { - csr = musb_readw(ep->regs, MUSB_TXCSR); - if (csr & MUSB_TXCSR_MODE) { - musb_h_tx_flush_fifo(ep); - csr = musb_readw(ep->regs, MUSB_TXCSR); - musb_writew(ep->regs, MUSB_TXCSR, - csr | MUSB_TXCSR_FRCDATATOG); - } - - /* - * Clear the MODE bit (and everything else) to enable Rx. - * NOTE: we mustn't clear the DMAMODE bit before DMAENAB. - */ - if (csr & MUSB_TXCSR_DMAMODE) - musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE); - musb_writew(ep->regs, MUSB_TXCSR, 0); - - /* scrub all previous state, clearing toggle */ - } else { - csr = musb_readw(ep->regs, MUSB_RXCSR); - if (csr & MUSB_RXCSR_RXPKTRDY) - WARNING("rx%d, packet/%d ready?\n", ep->epnum, - musb_readw(ep->regs, MUSB_RXCOUNT)); - - musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG); - } - - /* target addr and (for multipoint) hub addr/port */ - if (musb->is_multipoint) { - musb_write_rxfunaddr(ep->target_regs, qh->addr_reg); - musb_write_rxhubaddr(ep->target_regs, qh->h_addr_reg); - musb_write_rxhubport(ep->target_regs, qh->h_port_reg); - - } else - musb_writeb(musb->mregs, MUSB_FADDR, qh->addr_reg); - - /* protocol/endpoint, interval/NAKlimit, i/o size */ - musb_writeb(ep->regs, MUSB_RXTYPE, qh->type_reg); - musb_writeb(ep->regs, MUSB_RXINTERVAL, qh->intv_reg); - /* NOTE: bulk combining rewrites high bits of maxpacket */ - /* Set RXMAXP with the FIFO size of the endpoint - * to disable double buffer mode. - */ - if (musb->double_buffer_not_ok) - musb_writew(ep->regs, MUSB_RXMAXP, ep->max_packet_sz_rx); - else - musb_writew(ep->regs, MUSB_RXMAXP, - qh->maxpacket | ((qh->hb_mult - 1) << 11)); - - ep->rx_reinit = 0; -} - -static bool musb_tx_dma_program(struct dma_controller *dma, - struct musb_hw_ep *hw_ep, struct musb_qh *qh, - struct urb *urb, u32 offset, u32 length) -{ - struct dma_channel *channel = hw_ep->tx_channel; - void __iomem *epio = hw_ep->regs; - u16 pkt_size = qh->maxpacket; - u16 csr; - u8 mode; - -#ifdef CONFIG_USB_INVENTRA_DMA - if (length > channel->max_len) - length = channel->max_len; - - csr = musb_readw(epio, MUSB_TXCSR); - if (length > pkt_size) { - mode = 1; - csr |= MUSB_TXCSR_DMAMODE | MUSB_TXCSR_DMAENAB; - /* autoset shouldn't be set in high bandwidth */ - if (qh->hb_mult == 1) - csr |= MUSB_TXCSR_AUTOSET; - } else { - mode = 0; - csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE); - csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */ - } - channel->desired_mode = mode; - musb_writew(epio, MUSB_TXCSR, csr); -#else - if (!is_cppi_enabled() && !tusb_dma_omap()) - return false; - - channel->actual_len = 0; - - /* - * TX uses "RNDIS" mode automatically but needs help - * to identify the zero-length-final-packet case. - */ - mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0; -#endif - - qh->segsize = length; - - /* - * Ensure the data reaches to main memory before starting - * DMA transfer - */ - wmb(); - - if (!dma->channel_program(channel, pkt_size, mode, - urb->transfer_dma + offset, length)) { - dma->channel_release(channel); - hw_ep->tx_channel = NULL; - - csr = musb_readw(epio, MUSB_TXCSR); - csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB); - musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_H_WZC_BITS); - return false; - } - return true; -} - -/* - * Program an HDRC endpoint as per the given URB - * Context: irqs blocked, controller lock held - */ -static void musb_ep_program(struct musb *musb, u8 epnum, - struct urb *urb, int is_out, - u8 *buf, u32 offset, u32 len) -{ - struct dma_controller *dma_controller; - struct dma_channel *dma_channel; - u8 dma_ok; - void __iomem *mbase = musb->mregs; - struct musb_hw_ep *hw_ep = musb->endpoints + epnum; - void __iomem *epio = hw_ep->regs; - struct musb_qh *qh = musb_ep_get_qh(hw_ep, !is_out); - u16 packet_sz = qh->maxpacket; - - dev_dbg(musb->controller, "%s hw%d urb %p spd%d dev%d ep%d%s " - "h_addr%02x h_port%02x bytes %d\n", - is_out ? "-->" : "<--", - epnum, urb, urb->dev->speed, - qh->addr_reg, qh->epnum, is_out ? "out" : "in", - qh->h_addr_reg, qh->h_port_reg, - len); - - musb_ep_select(mbase, epnum); - - /* candidate for DMA? */ - dma_controller = musb->dma_controller; - if (is_dma_capable() && epnum && dma_controller) { - dma_channel = is_out ? hw_ep->tx_channel : hw_ep->rx_channel; - if (!dma_channel) { - dma_channel = dma_controller->channel_alloc( - dma_controller, hw_ep, is_out); - if (is_out) - hw_ep->tx_channel = dma_channel; - else - hw_ep->rx_channel = dma_channel; - } - } else - dma_channel = NULL; - - /* make sure we clear DMAEnab, autoSet bits from previous run */ - - /* OUT/transmit/EP0 or IN/receive? */ - if (is_out) { - u16 csr; - u16 int_txe; - u16 load_count; - - csr = musb_readw(epio, MUSB_TXCSR); - - /* disable interrupt in case we flush */ - int_txe = musb_readw(mbase, MUSB_INTRTXE); - musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum)); - - /* general endpoint setup */ - if (epnum) { - /* flush all old state, set default */ - musb_h_tx_flush_fifo(hw_ep); - - /* - * We must not clear the DMAMODE bit before or in - * the same cycle with the DMAENAB bit, so we clear - * the latter first... - */ - csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT - | MUSB_TXCSR_AUTOSET - | MUSB_TXCSR_DMAENAB - | MUSB_TXCSR_FRCDATATOG - | MUSB_TXCSR_H_RXSTALL - | MUSB_TXCSR_H_ERROR - | MUSB_TXCSR_TXPKTRDY - ); - csr |= MUSB_TXCSR_MODE; - - if (usb_gettoggle(urb->dev, qh->epnum, 1)) - csr |= MUSB_TXCSR_H_WR_DATATOGGLE - | MUSB_TXCSR_H_DATATOGGLE; - else - csr |= MUSB_TXCSR_CLRDATATOG; - - musb_writew(epio, MUSB_TXCSR, csr); - /* REVISIT may need to clear FLUSHFIFO ... */ - csr &= ~MUSB_TXCSR_DMAMODE; - musb_writew(epio, MUSB_TXCSR, csr); - csr = musb_readw(epio, MUSB_TXCSR); - } else { - /* endpoint 0: just flush */ - musb_h_ep0_flush_fifo(hw_ep); - } - - /* target addr and (for multipoint) hub addr/port */ - if (musb->is_multipoint) { - musb_write_txfunaddr(mbase, epnum, qh->addr_reg); - musb_write_txhubaddr(mbase, epnum, qh->h_addr_reg); - musb_write_txhubport(mbase, epnum, qh->h_port_reg); -/* FIXME if !epnum, do the same for RX ... */ - } else - musb_writeb(mbase, MUSB_FADDR, qh->addr_reg); - - /* protocol/endpoint/interval/NAKlimit */ - if (epnum) { - musb_writeb(epio, MUSB_TXTYPE, qh->type_reg); - if (musb->double_buffer_not_ok) - musb_writew(epio, MUSB_TXMAXP, - hw_ep->max_packet_sz_tx); - else if (can_bulk_split(musb, qh->type)) - musb_writew(epio, MUSB_TXMAXP, packet_sz - | ((hw_ep->max_packet_sz_tx / - packet_sz) - 1) << 11); - else - musb_writew(epio, MUSB_TXMAXP, - qh->maxpacket | - ((qh->hb_mult - 1) << 11)); - musb_writeb(epio, MUSB_TXINTERVAL, qh->intv_reg); - } else { - musb_writeb(epio, MUSB_NAKLIMIT0, qh->intv_reg); - if (musb->is_multipoint) - musb_writeb(epio, MUSB_TYPE0, - qh->type_reg); - } - - if (can_bulk_split(musb, qh->type)) - load_count = min((u32) hw_ep->max_packet_sz_tx, - len); - else - load_count = min((u32) packet_sz, len); - - if (dma_channel && musb_tx_dma_program(dma_controller, - hw_ep, qh, urb, offset, len)) - load_count = 0; - - if (load_count) { - /* PIO to load FIFO */ - qh->segsize = load_count; - musb_write_fifo(hw_ep, load_count, buf); - } - - /* re-enable interrupt */ - musb_writew(mbase, MUSB_INTRTXE, int_txe); - - /* IN/receive */ - } else { - u16 csr; - - if (hw_ep->rx_reinit) { - musb_rx_reinit(musb, qh, hw_ep); - - /* init new state: toggle and NYET, maybe DMA later */ - if (usb_gettoggle(urb->dev, qh->epnum, 0)) - csr = MUSB_RXCSR_H_WR_DATATOGGLE - | MUSB_RXCSR_H_DATATOGGLE; - else - csr = 0; - if (qh->type == USB_ENDPOINT_XFER_INT) - csr |= MUSB_RXCSR_DISNYET; - - } else { - csr = musb_readw(hw_ep->regs, MUSB_RXCSR); - - if (csr & (MUSB_RXCSR_RXPKTRDY - | MUSB_RXCSR_DMAENAB - | MUSB_RXCSR_H_REQPKT)) - ERR("broken !rx_reinit, ep%d csr %04x\n", - hw_ep->epnum, csr); - - /* scrub any stale state, leaving toggle alone */ - csr &= MUSB_RXCSR_DISNYET; - } - - /* kick things off */ - - if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) { - /* Candidate for DMA */ - dma_channel->actual_len = 0L; - qh->segsize = len; - - /* AUTOREQ is in a DMA register */ - musb_writew(hw_ep->regs, MUSB_RXCSR, csr); - csr = musb_readw(hw_ep->regs, MUSB_RXCSR); - - /* - * Unless caller treats short RX transfers as - * errors, we dare not queue multiple transfers. - */ - dma_ok = dma_controller->channel_program(dma_channel, - packet_sz, !(urb->transfer_flags & - URB_SHORT_NOT_OK), - urb->transfer_dma + offset, - qh->segsize); - if (!dma_ok) { - dma_controller->channel_release(dma_channel); - hw_ep->rx_channel = dma_channel = NULL; - } else - csr |= MUSB_RXCSR_DMAENAB; - } - - csr |= MUSB_RXCSR_H_REQPKT; - dev_dbg(musb->controller, "RXCSR%d := %04x\n", epnum, csr); - musb_writew(hw_ep->regs, MUSB_RXCSR, csr); - csr = musb_readw(hw_ep->regs, MUSB_RXCSR); - } -} - - -/* - * Service the default endpoint (ep0) as host. - * Return true until it's time to start the status stage. - */ -static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) -{ - bool more = false; - u8 *fifo_dest = NULL; - u16 fifo_count = 0; - struct musb_hw_ep *hw_ep = musb->control_ep; - struct musb_qh *qh = hw_ep->in_qh; - struct usb_ctrlrequest *request; - - switch (musb->ep0_stage) { - case MUSB_EP0_IN: - fifo_dest = urb->transfer_buffer + urb->actual_length; - fifo_count = min_t(size_t, len, urb->transfer_buffer_length - - urb->actual_length); - if (fifo_count < len) - urb->status = -EOVERFLOW; - - musb_read_fifo(hw_ep, fifo_count, fifo_dest); - - urb->actual_length += fifo_count; - if (len < qh->maxpacket) { - /* always terminate on short read; it's - * rarely reported as an error. - */ - } else if (urb->actual_length < - urb->transfer_buffer_length) - more = true; - break; - case MUSB_EP0_START: - request = (struct usb_ctrlrequest *) urb->setup_packet; - - if (!request->wLength) { - dev_dbg(musb->controller, "start no-DATA\n"); - break; - } else if (request->bRequestType & USB_DIR_IN) { - dev_dbg(musb->controller, "start IN-DATA\n"); - musb->ep0_stage = MUSB_EP0_IN; - more = true; - break; - } else { - dev_dbg(musb->controller, "start OUT-DATA\n"); - musb->ep0_stage = MUSB_EP0_OUT; - more = true; - } - /* FALLTHROUGH */ - case MUSB_EP0_OUT: - fifo_count = min_t(size_t, qh->maxpacket, - urb->transfer_buffer_length - - urb->actual_length); - if (fifo_count) { - fifo_dest = (u8 *) (urb->transfer_buffer - + urb->actual_length); - dev_dbg(musb->controller, "Sending %d byte%s to ep0 fifo %p\n", - fifo_count, - (fifo_count == 1) ? "" : "s", - fifo_dest); - musb_write_fifo(hw_ep, fifo_count, fifo_dest); - - urb->actual_length += fifo_count; - more = true; - } - break; - default: - ERR("bogus ep0 stage %d\n", musb->ep0_stage); - break; - } - - return more; -} - -/* - * Handle default endpoint interrupt as host. Only called in IRQ time - * from musb_interrupt(). - * - * called with controller irqlocked - */ -irqreturn_t musb_h_ep0_irq(struct musb *musb) -{ - struct urb *urb; - u16 csr, len; - int status = 0; - void __iomem *mbase = musb->mregs; - struct musb_hw_ep *hw_ep = musb->control_ep; - void __iomem *epio = hw_ep->regs; - struct musb_qh *qh = hw_ep->in_qh; - bool complete = false; - irqreturn_t retval = IRQ_NONE; - - /* ep0 only has one queue, "in" */ - urb = next_urb(qh); - - musb_ep_select(mbase, 0); - csr = musb_readw(epio, MUSB_CSR0); - len = (csr & MUSB_CSR0_RXPKTRDY) - ? musb_readb(epio, MUSB_COUNT0) - : 0; - - dev_dbg(musb->controller, "<== csr0 %04x, qh %p, count %d, urb %p, stage %d\n", - csr, qh, len, urb, musb->ep0_stage); - - /* if we just did status stage, we are done */ - if (MUSB_EP0_STATUS == musb->ep0_stage) { - retval = IRQ_HANDLED; - complete = true; - } - - /* prepare status */ - if (csr & MUSB_CSR0_H_RXSTALL) { - dev_dbg(musb->controller, "STALLING ENDPOINT\n"); - status = -EPIPE; - - } else if (csr & MUSB_CSR0_H_ERROR) { - dev_dbg(musb->controller, "no response, csr0 %04x\n", csr); - status = -EPROTO; - - } else if (csr & MUSB_CSR0_H_NAKTIMEOUT) { - dev_dbg(musb->controller, "control NAK timeout\n"); - - /* NOTE: this code path would be a good place to PAUSE a - * control transfer, if another one is queued, so that - * ep0 is more likely to stay busy. That's already done - * for bulk RX transfers. - * - * if (qh->ring.next != &musb->control), then - * we have a candidate... NAKing is *NOT* an error - */ - musb_writew(epio, MUSB_CSR0, 0); - retval = IRQ_HANDLED; - } - - if (status) { - dev_dbg(musb->controller, "aborting\n"); - retval = IRQ_HANDLED; - if (urb) - urb->status = status; - complete = true; - - /* use the proper sequence to abort the transfer */ - if (csr & MUSB_CSR0_H_REQPKT) { - csr &= ~MUSB_CSR0_H_REQPKT; - musb_writew(epio, MUSB_CSR0, csr); - csr &= ~MUSB_CSR0_H_NAKTIMEOUT; - musb_writew(epio, MUSB_CSR0, csr); - } else { - musb_h_ep0_flush_fifo(hw_ep); - } - - musb_writeb(epio, MUSB_NAKLIMIT0, 0); - - /* clear it */ - musb_writew(epio, MUSB_CSR0, 0); - } - - if (unlikely(!urb)) { - /* stop endpoint since we have no place for its data, this - * SHOULD NEVER HAPPEN! */ - ERR("no URB for end 0\n"); - - musb_h_ep0_flush_fifo(hw_ep); - goto done; - } - - if (!complete) { - /* call common logic and prepare response */ - if (musb_h_ep0_continue(musb, len, urb)) { - /* more packets required */ - csr = (MUSB_EP0_IN == musb->ep0_stage) - ? MUSB_CSR0_H_REQPKT : MUSB_CSR0_TXPKTRDY; - } else { - /* data transfer complete; perform status phase */ - if (usb_pipeout(urb->pipe) - || !urb->transfer_buffer_length) - csr = MUSB_CSR0_H_STATUSPKT - | MUSB_CSR0_H_REQPKT; - else - csr = MUSB_CSR0_H_STATUSPKT - | MUSB_CSR0_TXPKTRDY; - - /* flag status stage */ - musb->ep0_stage = MUSB_EP0_STATUS; - - dev_dbg(musb->controller, "ep0 STATUS, csr %04x\n", csr); - - } - musb_writew(epio, MUSB_CSR0, csr); - retval = IRQ_HANDLED; - } else - musb->ep0_stage = MUSB_EP0_IDLE; - - /* call completion handler if done */ - if (complete) - musb_advance_schedule(musb, urb, hw_ep, 1); -done: - return retval; -} - - -#ifdef CONFIG_USB_INVENTRA_DMA - -/* Host side TX (OUT) using Mentor DMA works as follows: - submit_urb -> - - if queue was empty, Program Endpoint - - ... which starts DMA to fifo in mode 1 or 0 - - DMA Isr (transfer complete) -> TxAvail() - - Stop DMA (~DmaEnab) (<--- Alert ... currently happens - only in musb_cleanup_urb) - - TxPktRdy has to be set in mode 0 or for - short packets in mode 1. -*/ - -#endif - -/* Service a Tx-Available or dma completion irq for the endpoint */ -void musb_host_tx(struct musb *musb, u8 epnum) -{ - int pipe; - bool done = false; - u16 tx_csr; - size_t length = 0; - size_t offset = 0; - struct musb_hw_ep *hw_ep = musb->endpoints + epnum; - void __iomem *epio = hw_ep->regs; - struct musb_qh *qh = hw_ep->out_qh; - struct urb *urb = next_urb(qh); - u32 status = 0; - void __iomem *mbase = musb->mregs; - struct dma_channel *dma; - bool transfer_pending = false; - - musb_ep_select(mbase, epnum); - tx_csr = musb_readw(epio, MUSB_TXCSR); - - /* with CPPI, DMA sometimes triggers "extra" irqs */ - if (!urb) { - dev_dbg(musb->controller, "extra TX%d ready, csr %04x\n", epnum, tx_csr); - return; - } - - pipe = urb->pipe; - dma = is_dma_capable() ? hw_ep->tx_channel : NULL; - dev_dbg(musb->controller, "OUT/TX%d end, csr %04x%s\n", epnum, tx_csr, - dma ? ", dma" : ""); - - /* check for errors */ - if (tx_csr & MUSB_TXCSR_H_RXSTALL) { - /* dma was disabled, fifo flushed */ - dev_dbg(musb->controller, "TX end %d stall\n", epnum); - - /* stall; record URB status */ - status = -EPIPE; - - } else if (tx_csr & MUSB_TXCSR_H_ERROR) { - /* (NON-ISO) dma was disabled, fifo flushed */ - dev_dbg(musb->controller, "TX 3strikes on ep=%d\n", epnum); - - status = -ETIMEDOUT; - - } else if (tx_csr & MUSB_TXCSR_H_NAKTIMEOUT) { - dev_dbg(musb->controller, "TX end=%d device not responding\n", epnum); - - /* NOTE: this code path would be a good place to PAUSE a - * transfer, if there's some other (nonperiodic) tx urb - * that could use this fifo. (dma complicates it...) - * That's already done for bulk RX transfers. - * - * if (bulk && qh->ring.next != &musb->out_bulk), then - * we have a candidate... NAKing is *NOT* an error - */ - musb_ep_select(mbase, epnum); - musb_writew(epio, MUSB_TXCSR, - MUSB_TXCSR_H_WZC_BITS - | MUSB_TXCSR_TXPKTRDY); - return; - } - - if (status) { - if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { - dma->status = MUSB_DMA_STATUS_CORE_ABORT; - (void) musb->dma_controller->channel_abort(dma); - } - - /* do the proper sequence to abort the transfer in the - * usb core; the dma engine should already be stopped. - */ - musb_h_tx_flush_fifo(hw_ep); - tx_csr &= ~(MUSB_TXCSR_AUTOSET - | MUSB_TXCSR_DMAENAB - | MUSB_TXCSR_H_ERROR - | MUSB_TXCSR_H_RXSTALL - | MUSB_TXCSR_H_NAKTIMEOUT - ); - - musb_ep_select(mbase, epnum); - musb_writew(epio, MUSB_TXCSR, tx_csr); - /* REVISIT may need to clear FLUSHFIFO ... */ - musb_writew(epio, MUSB_TXCSR, tx_csr); - musb_writeb(epio, MUSB_TXINTERVAL, 0); - - done = true; - } - - /* second cppi case */ - if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { - dev_dbg(musb->controller, "extra TX%d ready, csr %04x\n", epnum, tx_csr); - return; - } - - if (is_dma_capable() && dma && !status) { - /* - * DMA has completed. But if we're using DMA mode 1 (multi - * packet DMA), we need a terminal TXPKTRDY interrupt before - * we can consider this transfer completed, lest we trash - * its last packet when writing the next URB's data. So we - * switch back to mode 0 to get that interrupt; we'll come - * back here once it happens. - */ - if (tx_csr & MUSB_TXCSR_DMAMODE) { - /* - * We shouldn't clear DMAMODE with DMAENAB set; so - * clear them in a safe order. That should be OK - * once TXPKTRDY has been set (and I've never seen - * it being 0 at this moment -- DMA interrupt latency - * is significant) but if it hasn't been then we have - * no choice but to stop being polite and ignore the - * programmer's guide... :-) - * - * Note that we must write TXCSR with TXPKTRDY cleared - * in order not to re-trigger the packet send (this bit - * can't be cleared by CPU), and there's another caveat: - * TXPKTRDY may be set shortly and then cleared in the - * double-buffered FIFO mode, so we do an extra TXCSR - * read for debouncing... - */ - tx_csr &= musb_readw(epio, MUSB_TXCSR); - if (tx_csr & MUSB_TXCSR_TXPKTRDY) { - tx_csr &= ~(MUSB_TXCSR_DMAENAB | - MUSB_TXCSR_TXPKTRDY); - musb_writew(epio, MUSB_TXCSR, - tx_csr | MUSB_TXCSR_H_WZC_BITS); - } - tx_csr &= ~(MUSB_TXCSR_DMAMODE | - MUSB_TXCSR_TXPKTRDY); - musb_writew(epio, MUSB_TXCSR, - tx_csr | MUSB_TXCSR_H_WZC_BITS); - - /* - * There is no guarantee that we'll get an interrupt - * after clearing DMAMODE as we might have done this - * too late (after TXPKTRDY was cleared by controller). - * Re-read TXCSR as we have spoiled its previous value. - */ - tx_csr = musb_readw(epio, MUSB_TXCSR); - } - - /* - * We may get here from a DMA completion or TXPKTRDY interrupt. - * In any case, we must check the FIFO status here and bail out - * only if the FIFO still has data -- that should prevent the - * "missed" TXPKTRDY interrupts and deal with double-buffered - * FIFO mode too... - */ - if (tx_csr & (MUSB_TXCSR_FIFONOTEMPTY | MUSB_TXCSR_TXPKTRDY)) { - dev_dbg(musb->controller, "DMA complete but packet still in FIFO, " - "CSR %04x\n", tx_csr); - return; - } - } - - if (!status || dma || usb_pipeisoc(pipe)) { - if (dma) - length = dma->actual_len; - else - length = qh->segsize; - qh->offset += length; - - if (usb_pipeisoc(pipe)) { -#ifndef __UBOOT__ - struct usb_iso_packet_descriptor *d; - - d = urb->iso_frame_desc + qh->iso_idx; - d->actual_length = length; - d->status = status; - if (++qh->iso_idx >= urb->number_of_packets) { - done = true; - } else { - d++; - offset = d->offset; - length = d->length; - } -#endif - } else if (dma && urb->transfer_buffer_length == qh->offset) { - done = true; - } else { - /* see if we need to send more data, or ZLP */ - if (qh->segsize < qh->maxpacket) - done = true; - else if (qh->offset == urb->transfer_buffer_length - && !(urb->transfer_flags - & URB_ZERO_PACKET)) - done = true; - if (!done) { - offset = qh->offset; - length = urb->transfer_buffer_length - offset; - transfer_pending = true; - } - } - } - - /* urb->status != -EINPROGRESS means request has been faulted, - * so we must abort this transfer after cleanup - */ - if (urb->status != -EINPROGRESS) { - done = true; - if (status == 0) - status = urb->status; - } - - if (done) { - /* set status */ - urb->status = status; - urb->actual_length = qh->offset; - musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT); - return; - } else if ((usb_pipeisoc(pipe) || transfer_pending) && dma) { - if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb, - offset, length)) { - if (is_cppi_enabled() || tusb_dma_omap()) - musb_h_tx_dma_start(hw_ep); - return; - } - } else if (tx_csr & MUSB_TXCSR_DMAENAB) { - dev_dbg(musb->controller, "not complete, but DMA enabled?\n"); - return; - } - - /* - * PIO: start next packet in this URB. - * - * REVISIT: some docs say that when hw_ep->tx_double_buffered, - * (and presumably, FIFO is not half-full) we should write *two* - * packets before updating TXCSR; other docs disagree... - */ - if (length > qh->maxpacket) - length = qh->maxpacket; - /* Unmap the buffer so that CPU can use it */ - usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb); - musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset); - qh->segsize = length; - - musb_ep_select(mbase, epnum); - musb_writew(epio, MUSB_TXCSR, - MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY); -} - - -#ifdef CONFIG_USB_INVENTRA_DMA - -/* Host side RX (IN) using Mentor DMA works as follows: - submit_urb -> - - if queue was empty, ProgramEndpoint - - first IN token is sent out (by setting ReqPkt) - LinuxIsr -> RxReady() - /\ => first packet is received - | - Set in mode 0 (DmaEnab, ~ReqPkt) - | -> DMA Isr (transfer complete) -> RxReady() - | - Ack receive (~RxPktRdy), turn off DMA (~DmaEnab) - | - if urb not complete, send next IN token (ReqPkt) - | | else complete urb. - | | - --------------------------- - * - * Nuances of mode 1: - * For short packets, no ack (+RxPktRdy) is sent automatically - * (even if AutoClear is ON) - * For full packets, ack (~RxPktRdy) and next IN token (+ReqPkt) is sent - * automatically => major problem, as collecting the next packet becomes - * difficult. Hence mode 1 is not used. - * - * REVISIT - * All we care about at this driver level is that - * (a) all URBs terminate with REQPKT cleared and fifo(s) empty; - * (b) termination conditions are: short RX, or buffer full; - * (c) fault modes include - * - iff URB_SHORT_NOT_OK, short RX status is -EREMOTEIO. - * (and that endpoint's dma queue stops immediately) - * - overflow (full, PLUS more bytes in the terminal packet) - * - * So for example, usb-storage sets URB_SHORT_NOT_OK, and would - * thus be a great candidate for using mode 1 ... for all but the - * last packet of one URB's transfer. - */ - -#endif - -/* Schedule next QH from musb->in_bulk and move the current qh to - * the end; avoids starvation for other endpoints. - */ -static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep) -{ - struct dma_channel *dma; - struct urb *urb; - void __iomem *mbase = musb->mregs; - void __iomem *epio = ep->regs; - struct musb_qh *cur_qh, *next_qh; - u16 rx_csr; - - musb_ep_select(mbase, ep->epnum); - dma = is_dma_capable() ? ep->rx_channel : NULL; - - /* clear nak timeout bit */ - rx_csr = musb_readw(epio, MUSB_RXCSR); - rx_csr |= MUSB_RXCSR_H_WZC_BITS; - rx_csr &= ~MUSB_RXCSR_DATAERROR; - musb_writew(epio, MUSB_RXCSR, rx_csr); - - cur_qh = first_qh(&musb->in_bulk); - if (cur_qh) { - urb = next_urb(cur_qh); - if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { - dma->status = MUSB_DMA_STATUS_CORE_ABORT; - musb->dma_controller->channel_abort(dma); - urb->actual_length += dma->actual_len; - dma->actual_len = 0L; - } - musb_save_toggle(cur_qh, 1, urb); - - /* move cur_qh to end of queue */ - list_move_tail(&cur_qh->ring, &musb->in_bulk); - - /* get the next qh from musb->in_bulk */ - next_qh = first_qh(&musb->in_bulk); - - /* set rx_reinit and schedule the next qh */ - ep->rx_reinit = 1; - musb_start_urb(musb, 1, next_qh); - } -} - -/* - * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso, - * and high-bandwidth IN transfer cases. - */ -void musb_host_rx(struct musb *musb, u8 epnum) -{ - struct urb *urb; - struct musb_hw_ep *hw_ep = musb->endpoints + epnum; - void __iomem *epio = hw_ep->regs; - struct musb_qh *qh = hw_ep->in_qh; - size_t xfer_len; - void __iomem *mbase = musb->mregs; - int pipe; - u16 rx_csr, val; - bool iso_err = false; - bool done = false; - u32 status; - struct dma_channel *dma; - - musb_ep_select(mbase, epnum); - - urb = next_urb(qh); - dma = is_dma_capable() ? hw_ep->rx_channel : NULL; - status = 0; - xfer_len = 0; - - rx_csr = musb_readw(epio, MUSB_RXCSR); - val = rx_csr; - - if (unlikely(!urb)) { - /* REVISIT -- THIS SHOULD NEVER HAPPEN ... but, at least - * usbtest #11 (unlinks) triggers it regularly, sometimes - * with fifo full. (Only with DMA??) - */ - dev_dbg(musb->controller, "BOGUS RX%d ready, csr %04x, count %d\n", epnum, val, - musb_readw(epio, MUSB_RXCOUNT)); - musb_h_flush_rxfifo(hw_ep, MUSB_RXCSR_CLRDATATOG); - return; - } - - pipe = urb->pipe; - - dev_dbg(musb->controller, "<== hw %d rxcsr %04x, urb actual %d (+dma %zu)\n", - epnum, rx_csr, urb->actual_length, - dma ? dma->actual_len : 0); - - /* check for errors, concurrent stall & unlink is not really - * handled yet! */ - if (rx_csr & MUSB_RXCSR_H_RXSTALL) { - dev_dbg(musb->controller, "RX end %d STALL\n", epnum); - - /* stall; record URB status */ - status = -EPIPE; - - } else if (rx_csr & MUSB_RXCSR_H_ERROR) { - dev_dbg(musb->controller, "end %d RX proto error\n", epnum); - - status = -EPROTO; - musb_writeb(epio, MUSB_RXINTERVAL, 0); - - } else if (rx_csr & MUSB_RXCSR_DATAERROR) { - - if (USB_ENDPOINT_XFER_ISOC != qh->type) { - dev_dbg(musb->controller, "RX end %d NAK timeout\n", epnum); - - /* NOTE: NAKing is *NOT* an error, so we want to - * continue. Except ... if there's a request for - * another QH, use that instead of starving it. - * - * Devices like Ethernet and serial adapters keep - * reads posted at all times, which will starve - * other devices without this logic. - */ - if (usb_pipebulk(urb->pipe) - && qh->mux == 1 - && !list_is_singular(&musb->in_bulk)) { - musb_bulk_rx_nak_timeout(musb, hw_ep); - return; - } - musb_ep_select(mbase, epnum); - rx_csr |= MUSB_RXCSR_H_WZC_BITS; - rx_csr &= ~MUSB_RXCSR_DATAERROR; - musb_writew(epio, MUSB_RXCSR, rx_csr); - - goto finish; - } else { - dev_dbg(musb->controller, "RX end %d ISO data error\n", epnum); - /* packet error reported later */ - iso_err = true; - } - } else if (rx_csr & MUSB_RXCSR_INCOMPRX) { - dev_dbg(musb->controller, "end %d high bandwidth incomplete ISO packet RX\n", - epnum); - status = -EPROTO; - } - - /* faults abort the transfer */ - if (status) { - /* clean up dma and collect transfer count */ - if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { - dma->status = MUSB_DMA_STATUS_CORE_ABORT; - (void) musb->dma_controller->channel_abort(dma); - xfer_len = dma->actual_len; - } - musb_h_flush_rxfifo(hw_ep, MUSB_RXCSR_CLRDATATOG); - musb_writeb(epio, MUSB_RXINTERVAL, 0); - done = true; - goto finish; - } - - if (unlikely(dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY)) { - /* SHOULD NEVER HAPPEN ... but at least DaVinci has done it */ - ERR("RX%d dma busy, csr %04x\n", epnum, rx_csr); - goto finish; - } - - /* thorough shutdown for now ... given more precise fault handling - * and better queueing support, we might keep a DMA pipeline going - * while processing this irq for earlier completions. - */ - - /* FIXME this is _way_ too much in-line logic for Mentor DMA */ - -#ifndef CONFIG_USB_INVENTRA_DMA - if (rx_csr & MUSB_RXCSR_H_REQPKT) { - /* REVISIT this happened for a while on some short reads... - * the cleanup still needs investigation... looks bad... - * and also duplicates dma cleanup code above ... plus, - * shouldn't this be the "half full" double buffer case? - */ - if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { - dma->status = MUSB_DMA_STATUS_CORE_ABORT; - (void) musb->dma_controller->channel_abort(dma); - xfer_len = dma->actual_len; - done = true; - } - - dev_dbg(musb->controller, "RXCSR%d %04x, reqpkt, len %zu%s\n", epnum, rx_csr, - xfer_len, dma ? ", dma" : ""); - rx_csr &= ~MUSB_RXCSR_H_REQPKT; - - musb_ep_select(mbase, epnum); - musb_writew(epio, MUSB_RXCSR, - MUSB_RXCSR_H_WZC_BITS | rx_csr); - } -#endif - if (dma && (rx_csr & MUSB_RXCSR_DMAENAB)) { - xfer_len = dma->actual_len; - - val &= ~(MUSB_RXCSR_DMAENAB - | MUSB_RXCSR_H_AUTOREQ - | MUSB_RXCSR_AUTOCLEAR - | MUSB_RXCSR_RXPKTRDY); - musb_writew(hw_ep->regs, MUSB_RXCSR, val); - -#ifdef CONFIG_USB_INVENTRA_DMA - if (usb_pipeisoc(pipe)) { - struct usb_iso_packet_descriptor *d; - - d = urb->iso_frame_desc + qh->iso_idx; - d->actual_length = xfer_len; - - /* even if there was an error, we did the dma - * for iso_frame_desc->length - */ - if (d->status != -EILSEQ && d->status != -EOVERFLOW) - d->status = 0; - - if (++qh->iso_idx >= urb->number_of_packets) - done = true; - else - done = false; - - } else { - /* done if urb buffer is full or short packet is recd */ - done = (urb->actual_length + xfer_len >= - urb->transfer_buffer_length - || dma->actual_len < qh->maxpacket); - } - - /* send IN token for next packet, without AUTOREQ */ - if (!done) { - val |= MUSB_RXCSR_H_REQPKT; - musb_writew(epio, MUSB_RXCSR, - MUSB_RXCSR_H_WZC_BITS | val); - } - - dev_dbg(musb->controller, "ep %d dma %s, rxcsr %04x, rxcount %d\n", epnum, - done ? "off" : "reset", - musb_readw(epio, MUSB_RXCSR), - musb_readw(epio, MUSB_RXCOUNT)); -#else - done = true; -#endif - } else if (urb->status == -EINPROGRESS) { - /* if no errors, be sure a packet is ready for unloading */ - if (unlikely(!(rx_csr & MUSB_RXCSR_RXPKTRDY))) { - status = -EPROTO; - ERR("Rx interrupt with no errors or packet!\n"); - - /* FIXME this is another "SHOULD NEVER HAPPEN" */ - -/* SCRUB (RX) */ - /* do the proper sequence to abort the transfer */ - musb_ep_select(mbase, epnum); - val &= ~MUSB_RXCSR_H_REQPKT; - musb_writew(epio, MUSB_RXCSR, val); - goto finish; - } - - /* we are expecting IN packets */ -#ifdef CONFIG_USB_INVENTRA_DMA - if (dma) { - struct dma_controller *c; - u16 rx_count; - int ret, length; - dma_addr_t buf; - - rx_count = musb_readw(epio, MUSB_RXCOUNT); - - dev_dbg(musb->controller, "RX%d count %d, buffer 0x%x len %d/%d\n", - epnum, rx_count, - urb->transfer_dma - + urb->actual_length, - qh->offset, - urb->transfer_buffer_length); - - c = musb->dma_controller; - - if (usb_pipeisoc(pipe)) { - int d_status = 0; - struct usb_iso_packet_descriptor *d; - - d = urb->iso_frame_desc + qh->iso_idx; - - if (iso_err) { - d_status = -EILSEQ; - urb->error_count++; - } - if (rx_count > d->length) { - if (d_status == 0) { - d_status = -EOVERFLOW; - urb->error_count++; - } - dev_dbg(musb->controller, "** OVERFLOW %d into %d\n",\ - rx_count, d->length); - - length = d->length; - } else - length = rx_count; - d->status = d_status; - buf = urb->transfer_dma + d->offset; - } else { - length = rx_count; - buf = urb->transfer_dma + - urb->actual_length; - } - - dma->desired_mode = 0; -#ifdef USE_MODE1 - /* because of the issue below, mode 1 will - * only rarely behave with correct semantics. - */ - if ((urb->transfer_flags & - URB_SHORT_NOT_OK) - && (urb->transfer_buffer_length - - urb->actual_length) - > qh->maxpacket) - dma->desired_mode = 1; - if (rx_count < hw_ep->max_packet_sz_rx) { - length = rx_count; - dma->desired_mode = 0; - } else { - length = urb->transfer_buffer_length; - } -#endif - -/* Disadvantage of using mode 1: - * It's basically usable only for mass storage class; essentially all - * other protocols also terminate transfers on short packets. - * - * Details: - * An extra IN token is sent at the end of the transfer (due to AUTOREQ) - * If you try to use mode 1 for (transfer_buffer_length - 512), and try - * to use the extra IN token to grab the last packet using mode 0, then - * the problem is that you cannot be sure when the device will send the - * last packet and RxPktRdy set. Sometimes the packet is recd too soon - * such that it gets lost when RxCSR is re-set at the end of the mode 1 - * transfer, while sometimes it is recd just a little late so that if you - * try to configure for mode 0 soon after the mode 1 transfer is - * completed, you will find rxcount 0. Okay, so you might think why not - * wait for an interrupt when the pkt is recd. Well, you won't get any! - */ - - val = musb_readw(epio, MUSB_RXCSR); - val &= ~MUSB_RXCSR_H_REQPKT; - - if (dma->desired_mode == 0) - val &= ~MUSB_RXCSR_H_AUTOREQ; - else - val |= MUSB_RXCSR_H_AUTOREQ; - val |= MUSB_RXCSR_DMAENAB; - - /* autoclear shouldn't be set in high bandwidth */ - if (qh->hb_mult == 1) - val |= MUSB_RXCSR_AUTOCLEAR; - - musb_writew(epio, MUSB_RXCSR, - MUSB_RXCSR_H_WZC_BITS | val); - - /* REVISIT if when actual_length != 0, - * transfer_buffer_length needs to be - * adjusted first... - */ - ret = c->channel_program( - dma, qh->maxpacket, - dma->desired_mode, buf, length); - - if (!ret) { - c->channel_release(dma); - hw_ep->rx_channel = NULL; - dma = NULL; - val = musb_readw(epio, MUSB_RXCSR); - val &= ~(MUSB_RXCSR_DMAENAB - | MUSB_RXCSR_H_AUTOREQ - | MUSB_RXCSR_AUTOCLEAR); - musb_writew(epio, MUSB_RXCSR, val); - } - } -#endif /* Mentor DMA */ - - if (!dma) { - /* Unmap the buffer so that CPU can use it */ - usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb); - done = musb_host_packet_rx(musb, urb, - epnum, iso_err); - dev_dbg(musb->controller, "read %spacket\n", done ? "last " : ""); - } - } - -finish: - urb->actual_length += xfer_len; - qh->offset += xfer_len; - if (done) { - if (urb->status == -EINPROGRESS) - urb->status = status; - musb_advance_schedule(musb, urb, hw_ep, USB_DIR_IN); - } -} - -/* schedule nodes correspond to peripheral endpoints, like an OHCI QH. - * the software schedule associates multiple such nodes with a given - * host side hardware endpoint + direction; scheduling may activate - * that hardware endpoint. - */ -static int musb_schedule( - struct musb *musb, - struct musb_qh *qh, - int is_in) -{ - int idle; - int best_diff; - int best_end, epnum; - struct musb_hw_ep *hw_ep = NULL; - struct list_head *head = NULL; - u8 toggle; - u8 txtype; - struct urb *urb = next_urb(qh); - - /* use fixed hardware for control and bulk */ - if (qh->type == USB_ENDPOINT_XFER_CONTROL) { - head = &musb->control; - hw_ep = musb->control_ep; - goto success; - } - - /* else, periodic transfers get muxed to other endpoints */ - - /* - * We know this qh hasn't been scheduled, so all we need to do - * is choose which hardware endpoint to put it on ... - * - * REVISIT what we really want here is a regular schedule tree - * like e.g. OHCI uses. - */ - best_diff = 4096; - best_end = -1; - - for (epnum = 1, hw_ep = musb->endpoints + 1; - epnum < musb->nr_endpoints; - epnum++, hw_ep++) { - int diff; - - if (musb_ep_get_qh(hw_ep, is_in) != NULL) - continue; - - if (hw_ep == musb->bulk_ep) - continue; - - if (is_in) - diff = hw_ep->max_packet_sz_rx; - else - diff = hw_ep->max_packet_sz_tx; - diff -= (qh->maxpacket * qh->hb_mult); - - if (diff >= 0 && best_diff > diff) { - - /* - * Mentor controller has a bug in that if we schedule - * a BULK Tx transfer on an endpoint that had earlier - * handled ISOC then the BULK transfer has to start on - * a zero toggle. If the BULK transfer starts on a 1 - * toggle then this transfer will fail as the mentor - * controller starts the Bulk transfer on a 0 toggle - * irrespective of the programming of the toggle bits - * in the TXCSR register. Check for this condition - * while allocating the EP for a Tx Bulk transfer. If - * so skip this EP. - */ - hw_ep = musb->endpoints + epnum; - toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in); - txtype = (musb_readb(hw_ep->regs, MUSB_TXTYPE) - >> 4) & 0x3; - if (!is_in && (qh->type == USB_ENDPOINT_XFER_BULK) && - toggle && (txtype == USB_ENDPOINT_XFER_ISOC)) - continue; - - best_diff = diff; - best_end = epnum; - } - } - /* use bulk reserved ep1 if no other ep is free */ - if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) { - hw_ep = musb->bulk_ep; - if (is_in) - head = &musb->in_bulk; - else - head = &musb->out_bulk; - - /* Enable bulk RX NAK timeout scheme when bulk requests are - * multiplexed. This scheme doen't work in high speed to full - * speed scenario as NAK interrupts are not coming from a - * full speed device connected to a high speed device. - * NAK timeout interval is 8 (128 uframe or 16ms) for HS and - * 4 (8 frame or 8ms) for FS device. - */ - if (is_in && qh->dev) - qh->intv_reg = - (USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4; - goto success; - } else if (best_end < 0) { - return -ENOSPC; - } - - idle = 1; - qh->mux = 0; - hw_ep = musb->endpoints + best_end; - dev_dbg(musb->controller, "qh %p periodic slot %d\n", qh, best_end); -success: - if (head) { - idle = list_empty(head); - list_add_tail(&qh->ring, head); - qh->mux = 1; - } - qh->hw_ep = hw_ep; - qh->hep->hcpriv = qh; - if (idle) - musb_start_urb(musb, is_in, qh); - return 0; -} - -#ifdef __UBOOT__ -/* check if transaction translator is needed for device */ -static int tt_needed(struct musb *musb, struct usb_device *dev) -{ - if ((musb_readb(musb->mregs, MUSB_POWER) & MUSB_POWER_HSMODE) && - (dev->speed < USB_SPEED_HIGH)) - return 1; - return 0; -} -#endif - -#ifndef __UBOOT__ -static int musb_urb_enqueue( -#else -int musb_urb_enqueue( -#endif - struct usb_hcd *hcd, - struct urb *urb, - gfp_t mem_flags) -{ - unsigned long flags; - struct musb *musb = hcd_to_musb(hcd); - struct usb_host_endpoint *hep = urb->ep; - struct musb_qh *qh; - struct usb_endpoint_descriptor *epd = &hep->desc; - int ret; - unsigned type_reg; - unsigned interval; - - /* host role must be active */ - if (!is_host_active(musb) || !musb->is_active) - return -ENODEV; - - spin_lock_irqsave(&musb->lock, flags); - ret = usb_hcd_link_urb_to_ep(hcd, urb); - qh = ret ? NULL : hep->hcpriv; - if (qh) - urb->hcpriv = qh; - spin_unlock_irqrestore(&musb->lock, flags); - - /* DMA mapping was already done, if needed, and this urb is on - * hep->urb_list now ... so we're done, unless hep wasn't yet - * scheduled onto a live qh. - * - * REVISIT best to keep hep->hcpriv valid until the endpoint gets - * disabled, testing for empty qh->ring and avoiding qh setup costs - * except for the first urb queued after a config change. - */ - if (qh || ret) - return ret; - - /* Allocate and initialize qh, minimizing the work done each time - * hw_ep gets reprogrammed, or with irqs blocked. Then schedule it. - * - * REVISIT consider a dedicated qh kmem_cache, so it's harder - * for bugs in other kernel code to break this driver... - */ - qh = kzalloc(sizeof *qh, mem_flags); - if (!qh) { - spin_lock_irqsave(&musb->lock, flags); - usb_hcd_unlink_urb_from_ep(hcd, urb); - spin_unlock_irqrestore(&musb->lock, flags); - return -ENOMEM; - } - - qh->hep = hep; - qh->dev = urb->dev; - INIT_LIST_HEAD(&qh->ring); - qh->is_ready = 1; - - qh->maxpacket = usb_endpoint_maxp(epd); - qh->type = usb_endpoint_type(epd); - - /* Bits 11 & 12 of wMaxPacketSize encode high bandwidth multiplier. - * Some musb cores don't support high bandwidth ISO transfers; and - * we don't (yet!) support high bandwidth interrupt transfers. - */ - qh->hb_mult = 1 + ((qh->maxpacket >> 11) & 0x03); - if (qh->hb_mult > 1) { - int ok = (qh->type == USB_ENDPOINT_XFER_ISOC); - - if (ok) - ok = (usb_pipein(urb->pipe) && musb->hb_iso_rx) - || (usb_pipeout(urb->pipe) && musb->hb_iso_tx); - if (!ok) { - ret = -EMSGSIZE; - goto done; - } - qh->maxpacket &= 0x7ff; - } - - qh->epnum = usb_endpoint_num(epd); - - /* NOTE: urb->dev->devnum is wrong during SET_ADDRESS */ - qh->addr_reg = (u8) usb_pipedevice(urb->pipe); - - /* precompute rxtype/txtype/type0 register */ - type_reg = (qh->type << 4) | qh->epnum; - switch (urb->dev->speed) { - case USB_SPEED_LOW: - type_reg |= 0xc0; - break; - case USB_SPEED_FULL: - type_reg |= 0x80; - break; - default: - type_reg |= 0x40; - } - qh->type_reg = type_reg; - - /* Precompute RXINTERVAL/TXINTERVAL register */ - switch (qh->type) { - case USB_ENDPOINT_XFER_INT: - /* - * Full/low speeds use the linear encoding, - * high speed uses the logarithmic encoding. - */ - if (urb->dev->speed <= USB_SPEED_FULL) { - interval = max_t(u8, epd->bInterval, 1); - break; - } - /* FALLTHROUGH */ - case USB_ENDPOINT_XFER_ISOC: - /* ISO always uses logarithmic encoding */ - interval = min_t(u8, epd->bInterval, 16); - break; - default: - /* REVISIT we actually want to use NAK limits, hinting to the - * transfer scheduling logic to try some other qh, e.g. try - * for 2 msec first: - * - * interval = (USB_SPEED_HIGH == urb->dev->speed) ? 16 : 2; - * - * The downside of disabling this is that transfer scheduling - * gets VERY unfair for nonperiodic transfers; a misbehaving - * peripheral could make that hurt. That's perfectly normal - * for reads from network or serial adapters ... so we have - * partial NAKlimit support for bulk RX. - * - * The upside of disabling it is simpler transfer scheduling. - */ - interval = 0; - } - qh->intv_reg = interval; - - /* precompute addressing for external hub/tt ports */ - if (musb->is_multipoint) { - struct usb_device *parent = urb->dev->parent; - -#ifndef __UBOOT__ - if (parent != hcd->self.root_hub) { -#else - if (parent) { -#endif - qh->h_addr_reg = (u8) parent->devnum; - -#ifndef __UBOOT__ - /* set up tt info if needed */ - if (urb->dev->tt) { - qh->h_port_reg = (u8) urb->dev->ttport; - if (urb->dev->tt->hub) - qh->h_addr_reg = - (u8) urb->dev->tt->hub->devnum; - if (urb->dev->tt->multi) - qh->h_addr_reg |= 0x80; - } -#else - if (tt_needed(musb, urb->dev)) { - u16 hub_port = find_tt(urb->dev); - qh->h_addr_reg = (u8) (hub_port >> 8); - qh->h_port_reg = (u8) (hub_port & 0xff); - } -#endif - } - } - - /* invariant: hep->hcpriv is null OR the qh that's already scheduled. - * until we get real dma queues (with an entry for each urb/buffer), - * we only have work to do in the former case. - */ - spin_lock_irqsave(&musb->lock, flags); - if (hep->hcpriv) { - /* some concurrent activity submitted another urb to hep... - * odd, rare, error prone, but legal. - */ - kfree(qh); - qh = NULL; - ret = 0; - } else - ret = musb_schedule(musb, qh, - epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK); - - if (ret == 0) { - urb->hcpriv = qh; - /* FIXME set urb->start_frame for iso/intr, it's tested in - * musb_start_urb(), but otherwise only konicawc cares ... - */ - } - spin_unlock_irqrestore(&musb->lock, flags); - -done: - if (ret != 0) { - spin_lock_irqsave(&musb->lock, flags); - usb_hcd_unlink_urb_from_ep(hcd, urb); - spin_unlock_irqrestore(&musb->lock, flags); - kfree(qh); - } - return ret; -} - - -#ifndef __UBOOT__ -/* - * abort a transfer that's at the head of a hardware queue. - * called with controller locked, irqs blocked - * that hardware queue advances to the next transfer, unless prevented - */ -static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh) -{ - struct musb_hw_ep *ep = qh->hw_ep; - struct musb *musb = ep->musb; - void __iomem *epio = ep->regs; - unsigned hw_end = ep->epnum; - void __iomem *regs = ep->musb->mregs; - int is_in = usb_pipein(urb->pipe); - int status = 0; - u16 csr; - - musb_ep_select(regs, hw_end); - - if (is_dma_capable()) { - struct dma_channel *dma; - - dma = is_in ? ep->rx_channel : ep->tx_channel; - if (dma) { - status = ep->musb->dma_controller->channel_abort(dma); - dev_dbg(musb->controller, - "abort %cX%d DMA for urb %p --> %d\n", - is_in ? 'R' : 'T', ep->epnum, - urb, status); - urb->actual_length += dma->actual_len; - } - } - - /* turn off DMA requests, discard state, stop polling ... */ - if (ep->epnum && is_in) { - /* giveback saves bulk toggle */ - csr = musb_h_flush_rxfifo(ep, 0); - - /* REVISIT we still get an irq; should likely clear the - * endpoint's irq status here to avoid bogus irqs. - * clearing that status is platform-specific... - */ - } else if (ep->epnum) { - musb_h_tx_flush_fifo(ep); - csr = musb_readw(epio, MUSB_TXCSR); - csr &= ~(MUSB_TXCSR_AUTOSET - | MUSB_TXCSR_DMAENAB - | MUSB_TXCSR_H_RXSTALL - | MUSB_TXCSR_H_NAKTIMEOUT - | MUSB_TXCSR_H_ERROR - | MUSB_TXCSR_TXPKTRDY); - musb_writew(epio, MUSB_TXCSR, csr); - /* REVISIT may need to clear FLUSHFIFO ... */ - musb_writew(epio, MUSB_TXCSR, csr); - /* flush cpu writebuffer */ - csr = musb_readw(epio, MUSB_TXCSR); - } else { - musb_h_ep0_flush_fifo(ep); - } - if (status == 0) - musb_advance_schedule(ep->musb, urb, ep, is_in); - return status; -} - -static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) -{ - struct musb *musb = hcd_to_musb(hcd); - struct musb_qh *qh; - unsigned long flags; - int is_in = usb_pipein(urb->pipe); - int ret; - - dev_dbg(musb->controller, "urb=%p, dev%d ep%d%s\n", urb, - usb_pipedevice(urb->pipe), - usb_pipeendpoint(urb->pipe), - is_in ? "in" : "out"); - - spin_lock_irqsave(&musb->lock, flags); - ret = usb_hcd_check_unlink_urb(hcd, urb, status); - if (ret) - goto done; - - qh = urb->hcpriv; - if (!qh) - goto done; - - /* - * Any URB not actively programmed into endpoint hardware can be - * immediately given back; that's any URB not at the head of an - * endpoint queue, unless someday we get real DMA queues. And even - * if it's at the head, it might not be known to the hardware... - * - * Otherwise abort current transfer, pending DMA, etc.; urb->status - * has already been updated. This is a synchronous abort; it'd be - * OK to hold off until after some IRQ, though. - * - * NOTE: qh is invalid unless !list_empty(&hep->urb_list) - */ - if (!qh->is_ready - || urb->urb_list.prev != &qh->hep->urb_list - || musb_ep_get_qh(qh->hw_ep, is_in) != qh) { - int ready = qh->is_ready; - - qh->is_ready = 0; - musb_giveback(musb, urb, 0); - qh->is_ready = ready; - - /* If nothing else (usually musb_giveback) is using it - * and its URB list has emptied, recycle this qh. - */ - if (ready && list_empty(&qh->hep->urb_list)) { - qh->hep->hcpriv = NULL; - list_del(&qh->ring); - kfree(qh); - } - } else - ret = musb_cleanup_urb(urb, qh); -done: - spin_unlock_irqrestore(&musb->lock, flags); - return ret; -} - -/* disable an endpoint */ -static void -musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) -{ - u8 is_in = hep->desc.bEndpointAddress & USB_DIR_IN; - unsigned long flags; - struct musb *musb = hcd_to_musb(hcd); - struct musb_qh *qh; - struct urb *urb; - - spin_lock_irqsave(&musb->lock, flags); - - qh = hep->hcpriv; - if (qh == NULL) - goto exit; - - /* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */ - - /* Kick the first URB off the hardware, if needed */ - qh->is_ready = 0; - if (musb_ep_get_qh(qh->hw_ep, is_in) == qh) { - urb = next_urb(qh); - - /* make software (then hardware) stop ASAP */ - if (!urb->unlinked) - urb->status = -ESHUTDOWN; - - /* cleanup */ - musb_cleanup_urb(urb, qh); - - /* Then nuke all the others ... and advance the - * queue on hw_ep (e.g. bulk ring) when we're done. - */ - while (!list_empty(&hep->urb_list)) { - urb = next_urb(qh); - urb->status = -ESHUTDOWN; - musb_advance_schedule(musb, urb, qh->hw_ep, is_in); - } - } else { - /* Just empty the queue; the hardware is busy with - * other transfers, and since !qh->is_ready nothing - * will activate any of these as it advances. - */ - while (!list_empty(&hep->urb_list)) - musb_giveback(musb, next_urb(qh), -ESHUTDOWN); - - hep->hcpriv = NULL; - list_del(&qh->ring); - kfree(qh); - } -exit: - spin_unlock_irqrestore(&musb->lock, flags); -} - -static int musb_h_get_frame_number(struct usb_hcd *hcd) -{ - struct musb *musb = hcd_to_musb(hcd); - - return musb_readw(musb->mregs, MUSB_FRAME); -} - -static int musb_h_start(struct usb_hcd *hcd) -{ - struct musb *musb = hcd_to_musb(hcd); - - /* NOTE: musb_start() is called when the hub driver turns - * on port power, or when (OTG) peripheral starts. - */ - hcd->state = HC_STATE_RUNNING; - musb->port1_status = 0; - return 0; -} - -static void musb_h_stop(struct usb_hcd *hcd) -{ - musb_stop(hcd_to_musb(hcd)); - hcd->state = HC_STATE_HALT; -} - -static int musb_bus_suspend(struct usb_hcd *hcd) -{ - struct musb *musb = hcd_to_musb(hcd); - u8 devctl; - - if (!is_host_active(musb)) - return 0; - - switch (musb->xceiv->state) { - case OTG_STATE_A_SUSPEND: - return 0; - case OTG_STATE_A_WAIT_VRISE: - /* ID could be grounded even if there's no device - * on the other end of the cable. NOTE that the - * A_WAIT_VRISE timers are messy with MUSB... - */ - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) - musb->xceiv->state = OTG_STATE_A_WAIT_BCON; - break; - default: - break; - } - - if (musb->is_active) { - WARNING("trying to suspend as %s while active\n", - otg_state_string(musb->xceiv->state)); - return -EBUSY; - } else - return 0; -} - -static int musb_bus_resume(struct usb_hcd *hcd) -{ - /* resuming child port does the work */ - return 0; -} - -const struct hc_driver musb_hc_driver = { - .description = "musb-hcd", - .product_desc = "MUSB HDRC host driver", - .hcd_priv_size = sizeof(struct musb), - .flags = HCD_USB2 | HCD_MEMORY, - - /* not using irq handler or reset hooks from usbcore, since - * those must be shared with peripheral code for OTG configs - */ - - .start = musb_h_start, - .stop = musb_h_stop, - - .get_frame_number = musb_h_get_frame_number, - - .urb_enqueue = musb_urb_enqueue, - .urb_dequeue = musb_urb_dequeue, - .endpoint_disable = musb_h_disable, - - .hub_status_data = musb_hub_status_data, - .hub_control = musb_hub_control, - .bus_suspend = musb_bus_suspend, - .bus_resume = musb_bus_resume, - /* .start_port_reset = NULL, */ - /* .hub_irq_enable = NULL, */ -}; -#endif diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_host.h b/qemu/roms/u-boot/drivers/usb/musb-new/musb_host.h deleted file mode 100644 index ebebe0c02..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_host.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * MUSB OTG driver host defines - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _MUSB_HOST_H -#define _MUSB_HOST_H -#ifdef __UBOOT__ -#include "usb-compat.h" -#endif - -static inline struct usb_hcd *musb_to_hcd(struct musb *musb) -{ - return container_of((void *) musb, struct usb_hcd, hcd_priv); -} - -static inline struct musb *hcd_to_musb(struct usb_hcd *hcd) -{ - return (struct musb *) (hcd->hcd_priv); -} - -/* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints */ -struct musb_qh { - struct usb_host_endpoint *hep; /* usbcore info */ - struct usb_device *dev; - struct musb_hw_ep *hw_ep; /* current binding */ - - struct list_head ring; /* of musb_qh */ - /* struct musb_qh *next; */ /* for periodic tree */ - u8 mux; /* qh multiplexed to hw_ep */ - - unsigned offset; /* in urb->transfer_buffer */ - unsigned segsize; /* current xfer fragment */ - - u8 type_reg; /* {rx,tx} type register */ - u8 intv_reg; /* {rx,tx} interval register */ - u8 addr_reg; /* device address register */ - u8 h_addr_reg; /* hub address register */ - u8 h_port_reg; /* hub port register */ - - u8 is_ready; /* safe to modify hw_ep */ - u8 type; /* XFERTYPE_* */ - u8 epnum; - u8 hb_mult; /* high bandwidth pkts per uf */ - u16 maxpacket; - u16 frame; /* for periodic schedule */ - unsigned iso_idx; /* in urb->iso_frame_desc[] */ -}; - -/* map from control or bulk queue head to the first qh on that ring */ -static inline struct musb_qh *first_qh(struct list_head *q) -{ - if (list_empty(q)) - return NULL; - return list_entry(q->next, struct musb_qh, ring); -} - - -extern void musb_root_disconnect(struct musb *musb); - -struct usb_hcd; - -extern int musb_hub_status_data(struct usb_hcd *hcd, char *buf); -extern int musb_hub_control(struct usb_hcd *hcd, - u16 typeReq, u16 wValue, u16 wIndex, - char *buf, u16 wLength); - -extern const struct hc_driver musb_hc_driver; - -static inline struct urb *next_urb(struct musb_qh *qh) -{ - struct list_head *queue; - - if (!qh) - return NULL; - queue = &qh->hep->urb_list; - if (list_empty(queue)) - return NULL; - return list_entry(queue->next, struct urb, urb_list); -} - -#ifdef __UBOOT__ -int musb_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags); -#endif -#endif /* _MUSB_HOST_H */ diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_io.h b/qemu/roms/u-boot/drivers/usb/musb-new/musb_io.h deleted file mode 100644 index 51730aee5..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_io.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * MUSB OTG driver register I/O - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __MUSB_LINUX_PLATFORM_ARCH_H__ -#define __MUSB_LINUX_PLATFORM_ARCH_H__ - -#ifndef __UBOOT__ -#include <linux/io.h> -#else -#include <asm/io.h> -#endif - -#if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \ - && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \ - && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) \ - && !defined(CONFIG_MIPS) && !defined(CONFIG_M68K) -static inline void readsl(const void __iomem *addr, void *buf, int len) - { insl((unsigned long)addr, buf, len); } -static inline void readsw(const void __iomem *addr, void *buf, int len) - { insw((unsigned long)addr, buf, len); } -static inline void readsb(const void __iomem *addr, void *buf, int len) - { insb((unsigned long)addr, buf, len); } - -static inline void writesl(const void __iomem *addr, const void *buf, int len) - { outsl((unsigned long)addr, buf, len); } -static inline void writesw(const void __iomem *addr, const void *buf, int len) - { outsw((unsigned long)addr, buf, len); } -static inline void writesb(const void __iomem *addr, const void *buf, int len) - { outsb((unsigned long)addr, buf, len); } - -#endif - -#ifndef CONFIG_BLACKFIN - -/* NOTE: these offsets are all in bytes */ - -static inline u16 musb_readw(const void __iomem *addr, unsigned offset) - { return __raw_readw(addr + offset); } - -static inline u32 musb_readl(const void __iomem *addr, unsigned offset) - { return __raw_readl(addr + offset); } - - -static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data) - { __raw_writew(data, addr + offset); } - -static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data) - { __raw_writel(data, addr + offset); } - - -#if defined(CONFIG_USB_MUSB_TUSB6010) || defined (CONFIG_USB_MUSB_TUSB6010_MODULE) - -/* - * TUSB6010 doesn't allow 8-bit access; 16-bit access is the minimum. - */ -static inline u8 musb_readb(const void __iomem *addr, unsigned offset) -{ - u16 tmp; - u8 val; - - tmp = __raw_readw(addr + (offset & ~1)); - if (offset & 1) - val = (tmp >> 8); - else - val = tmp & 0xff; - - return val; -} - -static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data) -{ - u16 tmp; - - tmp = __raw_readw(addr + (offset & ~1)); - if (offset & 1) - tmp = (data << 8) | (tmp & 0xff); - else - tmp = (tmp & 0xff00) | data; - - __raw_writew(tmp, addr + (offset & ~1)); -} - -#else - -static inline u8 musb_readb(const void __iomem *addr, unsigned offset) - { return __raw_readb(addr + offset); } - -static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data) - { __raw_writeb(data, addr + offset); } - -#endif /* CONFIG_USB_MUSB_TUSB6010 */ - -#else - -static inline u8 musb_readb(const void __iomem *addr, unsigned offset) - { return (u8) (bfin_read16(addr + offset)); } - -static inline u16 musb_readw(const void __iomem *addr, unsigned offset) - { return bfin_read16(addr + offset); } - -static inline u32 musb_readl(const void __iomem *addr, unsigned offset) - { return (u32) (bfin_read16(addr + offset)); } - -static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data) - { bfin_write16(addr + offset, (u16) data); } - -static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data) - { bfin_write16(addr + offset, data); } - -static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data) - { bfin_write16(addr + offset, (u16) data); } - -#endif /* CONFIG_BLACKFIN */ - -#endif diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_regs.h b/qemu/roms/u-boot/drivers/usb/musb-new/musb_regs.h deleted file mode 100644 index 03f2655af..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_regs.h +++ /dev/null @@ -1,645 +0,0 @@ -/* - * MUSB OTG driver register defines - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __MUSB_REGS_H__ -#define __MUSB_REGS_H__ - -#define MUSB_EP0_FIFOSIZE 64 /* This is non-configurable */ - -/* - * MUSB Register bits - */ - -/* POWER */ -#define MUSB_POWER_ISOUPDATE 0x80 -#define MUSB_POWER_SOFTCONN 0x40 -#define MUSB_POWER_HSENAB 0x20 -#define MUSB_POWER_HSMODE 0x10 -#define MUSB_POWER_RESET 0x08 -#define MUSB_POWER_RESUME 0x04 -#define MUSB_POWER_SUSPENDM 0x02 -#define MUSB_POWER_ENSUSPEND 0x01 - -/* INTRUSB */ -#define MUSB_INTR_SUSPEND 0x01 -#define MUSB_INTR_RESUME 0x02 -#define MUSB_INTR_RESET 0x04 -#define MUSB_INTR_BABBLE 0x04 -#define MUSB_INTR_SOF 0x08 -#define MUSB_INTR_CONNECT 0x10 -#define MUSB_INTR_DISCONNECT 0x20 -#define MUSB_INTR_SESSREQ 0x40 -#define MUSB_INTR_VBUSERROR 0x80 /* For SESSION end */ - -/* DEVCTL */ -#define MUSB_DEVCTL_BDEVICE 0x80 -#define MUSB_DEVCTL_FSDEV 0x40 -#define MUSB_DEVCTL_LSDEV 0x20 -#define MUSB_DEVCTL_VBUS 0x18 -#define MUSB_DEVCTL_VBUS_SHIFT 3 -#define MUSB_DEVCTL_HM 0x04 -#define MUSB_DEVCTL_HR 0x02 -#define MUSB_DEVCTL_SESSION 0x01 - -/* MUSB ULPI VBUSCONTROL */ -#define MUSB_ULPI_USE_EXTVBUS 0x01 -#define MUSB_ULPI_USE_EXTVBUSIND 0x02 -/* ULPI_REG_CONTROL */ -#define MUSB_ULPI_REG_REQ (1 << 0) -#define MUSB_ULPI_REG_CMPLT (1 << 1) -#define MUSB_ULPI_RDN_WR (1 << 2) - -/* TESTMODE */ -#define MUSB_TEST_FORCE_HOST 0x80 -#define MUSB_TEST_FIFO_ACCESS 0x40 -#define MUSB_TEST_FORCE_FS 0x20 -#define MUSB_TEST_FORCE_HS 0x10 -#define MUSB_TEST_PACKET 0x08 -#define MUSB_TEST_K 0x04 -#define MUSB_TEST_J 0x02 -#define MUSB_TEST_SE0_NAK 0x01 - -/* Allocate for double-packet buffering (effectively doubles assigned _SIZE) */ -#define MUSB_FIFOSZ_DPB 0x10 -/* Allocation size (8, 16, 32, ... 4096) */ -#define MUSB_FIFOSZ_SIZE 0x0f - -/* CSR0 */ -#define MUSB_CSR0_FLUSHFIFO 0x0100 -#define MUSB_CSR0_TXPKTRDY 0x0002 -#define MUSB_CSR0_RXPKTRDY 0x0001 - -/* CSR0 in Peripheral mode */ -#define MUSB_CSR0_P_SVDSETUPEND 0x0080 -#define MUSB_CSR0_P_SVDRXPKTRDY 0x0040 -#define MUSB_CSR0_P_SENDSTALL 0x0020 -#define MUSB_CSR0_P_SETUPEND 0x0010 -#define MUSB_CSR0_P_DATAEND 0x0008 -#define MUSB_CSR0_P_SENTSTALL 0x0004 - -/* CSR0 in Host mode */ -#define MUSB_CSR0_H_DIS_PING 0x0800 -#define MUSB_CSR0_H_WR_DATATOGGLE 0x0400 /* Set to allow setting: */ -#define MUSB_CSR0_H_DATATOGGLE 0x0200 /* Data toggle control */ -#define MUSB_CSR0_H_NAKTIMEOUT 0x0080 -#define MUSB_CSR0_H_STATUSPKT 0x0040 -#define MUSB_CSR0_H_REQPKT 0x0020 -#define MUSB_CSR0_H_ERROR 0x0010 -#define MUSB_CSR0_H_SETUPPKT 0x0008 -#define MUSB_CSR0_H_RXSTALL 0x0004 - -/* CSR0 bits to avoid zeroing (write zero clears, write 1 ignored) */ -#define MUSB_CSR0_P_WZC_BITS \ - (MUSB_CSR0_P_SENTSTALL) -#define MUSB_CSR0_H_WZC_BITS \ - (MUSB_CSR0_H_NAKTIMEOUT | MUSB_CSR0_H_RXSTALL \ - | MUSB_CSR0_RXPKTRDY) - -/* TxType/RxType */ -#define MUSB_TYPE_SPEED 0xc0 -#define MUSB_TYPE_SPEED_SHIFT 6 -#define MUSB_TYPE_PROTO 0x30 /* Implicitly zero for ep0 */ -#define MUSB_TYPE_PROTO_SHIFT 4 -#define MUSB_TYPE_REMOTE_END 0xf /* Implicitly zero for ep0 */ - -/* CONFIGDATA */ -#define MUSB_CONFIGDATA_MPRXE 0x80 /* Auto bulk pkt combining */ -#define MUSB_CONFIGDATA_MPTXE 0x40 /* Auto bulk pkt splitting */ -#define MUSB_CONFIGDATA_BIGENDIAN 0x20 -#define MUSB_CONFIGDATA_HBRXE 0x10 /* HB-ISO for RX */ -#define MUSB_CONFIGDATA_HBTXE 0x08 /* HB-ISO for TX */ -#define MUSB_CONFIGDATA_DYNFIFO 0x04 /* Dynamic FIFO sizing */ -#define MUSB_CONFIGDATA_SOFTCONE 0x02 /* SoftConnect */ -#define MUSB_CONFIGDATA_UTMIDW 0x01 /* Data width 0/1 => 8/16bits */ - -/* TXCSR in Peripheral and Host mode */ -#define MUSB_TXCSR_AUTOSET 0x8000 -#define MUSB_TXCSR_DMAENAB 0x1000 -#define MUSB_TXCSR_FRCDATATOG 0x0800 -#define MUSB_TXCSR_DMAMODE 0x0400 -#define MUSB_TXCSR_CLRDATATOG 0x0040 -#define MUSB_TXCSR_FLUSHFIFO 0x0008 -#define MUSB_TXCSR_FIFONOTEMPTY 0x0002 -#define MUSB_TXCSR_TXPKTRDY 0x0001 - -/* TXCSR in Peripheral mode */ -#define MUSB_TXCSR_P_ISO 0x4000 -#define MUSB_TXCSR_P_INCOMPTX 0x0080 -#define MUSB_TXCSR_P_SENTSTALL 0x0020 -#define MUSB_TXCSR_P_SENDSTALL 0x0010 -#define MUSB_TXCSR_P_UNDERRUN 0x0004 - -/* TXCSR in Host mode */ -#define MUSB_TXCSR_H_WR_DATATOGGLE 0x0200 -#define MUSB_TXCSR_H_DATATOGGLE 0x0100 -#define MUSB_TXCSR_H_NAKTIMEOUT 0x0080 -#define MUSB_TXCSR_H_RXSTALL 0x0020 -#define MUSB_TXCSR_H_ERROR 0x0004 - -/* TXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */ -#define MUSB_TXCSR_P_WZC_BITS \ - (MUSB_TXCSR_P_INCOMPTX | MUSB_TXCSR_P_SENTSTALL \ - | MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_FIFONOTEMPTY) -#define MUSB_TXCSR_H_WZC_BITS \ - (MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \ - | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY) - -/* RXCSR in Peripheral and Host mode */ -#define MUSB_RXCSR_AUTOCLEAR 0x8000 -#define MUSB_RXCSR_DMAENAB 0x2000 -#define MUSB_RXCSR_DISNYET 0x1000 -#define MUSB_RXCSR_PID_ERR 0x1000 -#define MUSB_RXCSR_DMAMODE 0x0800 -#define MUSB_RXCSR_INCOMPRX 0x0100 -#define MUSB_RXCSR_CLRDATATOG 0x0080 -#define MUSB_RXCSR_FLUSHFIFO 0x0010 -#define MUSB_RXCSR_DATAERROR 0x0008 -#define MUSB_RXCSR_FIFOFULL 0x0002 -#define MUSB_RXCSR_RXPKTRDY 0x0001 - -/* RXCSR in Peripheral mode */ -#define MUSB_RXCSR_P_ISO 0x4000 -#define MUSB_RXCSR_P_SENTSTALL 0x0040 -#define MUSB_RXCSR_P_SENDSTALL 0x0020 -#define MUSB_RXCSR_P_OVERRUN 0x0004 - -/* RXCSR in Host mode */ -#define MUSB_RXCSR_H_AUTOREQ 0x4000 -#define MUSB_RXCSR_H_WR_DATATOGGLE 0x0400 -#define MUSB_RXCSR_H_DATATOGGLE 0x0200 -#define MUSB_RXCSR_H_RXSTALL 0x0040 -#define MUSB_RXCSR_H_REQPKT 0x0020 -#define MUSB_RXCSR_H_ERROR 0x0004 - -/* RXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */ -#define MUSB_RXCSR_P_WZC_BITS \ - (MUSB_RXCSR_P_SENTSTALL | MUSB_RXCSR_P_OVERRUN \ - | MUSB_RXCSR_RXPKTRDY) -#define MUSB_RXCSR_H_WZC_BITS \ - (MUSB_RXCSR_H_RXSTALL | MUSB_RXCSR_H_ERROR \ - | MUSB_RXCSR_DATAERROR | MUSB_RXCSR_RXPKTRDY) - -/* HUBADDR */ -#define MUSB_HUBADDR_MULTI_TT 0x80 - - -#ifndef CONFIG_BLACKFIN - -/* - * Common USB registers - */ - -#define MUSB_FADDR 0x00 /* 8-bit */ -#define MUSB_POWER 0x01 /* 8-bit */ - -#define MUSB_INTRTX 0x02 /* 16-bit */ -#define MUSB_INTRRX 0x04 -#define MUSB_INTRTXE 0x06 -#define MUSB_INTRRXE 0x08 -#define MUSB_INTRUSB 0x0A /* 8 bit */ -#define MUSB_INTRUSBE 0x0B /* 8 bit */ -#define MUSB_FRAME 0x0C -#define MUSB_INDEX 0x0E /* 8 bit */ -#define MUSB_TESTMODE 0x0F /* 8 bit */ - -/* Get offset for a given FIFO from musb->mregs */ -#if defined(CONFIG_USB_MUSB_TUSB6010) || \ - defined(CONFIG_USB_MUSB_TUSB6010_MODULE) -#define MUSB_FIFO_OFFSET(epnum) (0x200 + ((epnum) * 0x20)) -#else -#define MUSB_FIFO_OFFSET(epnum) (0x20 + ((epnum) * 4)) -#endif - -/* - * Additional Control Registers - */ - -#define MUSB_DEVCTL 0x60 /* 8 bit */ - -/* These are always controlled through the INDEX register */ -#define MUSB_TXFIFOSZ 0x62 /* 8-bit (see masks) */ -#define MUSB_RXFIFOSZ 0x63 /* 8-bit (see masks) */ -#define MUSB_TXFIFOADD 0x64 /* 16-bit offset shifted right 3 */ -#define MUSB_RXFIFOADD 0x66 /* 16-bit offset shifted right 3 */ - -/* REVISIT: vctrl/vstatus: optional vendor utmi+phy register at 0x68 */ -#define MUSB_HWVERS 0x6C /* 8 bit */ -#define MUSB_ULPI_BUSCONTROL 0x70 /* 8 bit */ -#define MUSB_ULPI_INT_MASK 0x72 /* 8 bit */ -#define MUSB_ULPI_INT_SRC 0x73 /* 8 bit */ -#define MUSB_ULPI_REG_DATA 0x74 /* 8 bit */ -#define MUSB_ULPI_REG_ADDR 0x75 /* 8 bit */ -#define MUSB_ULPI_REG_CONTROL 0x76 /* 8 bit */ -#define MUSB_ULPI_RAW_DATA 0x77 /* 8 bit */ - -#define MUSB_EPINFO 0x78 /* 8 bit */ -#define MUSB_RAMINFO 0x79 /* 8 bit */ -#define MUSB_LINKINFO 0x7a /* 8 bit */ -#define MUSB_VPLEN 0x7b /* 8 bit */ -#define MUSB_HS_EOF1 0x7c /* 8 bit */ -#define MUSB_FS_EOF1 0x7d /* 8 bit */ -#define MUSB_LS_EOF1 0x7e /* 8 bit */ - -/* Offsets to endpoint registers */ -#define MUSB_TXMAXP 0x00 -#define MUSB_TXCSR 0x02 -#define MUSB_CSR0 MUSB_TXCSR /* Re-used for EP0 */ -#define MUSB_RXMAXP 0x04 -#define MUSB_RXCSR 0x06 -#define MUSB_RXCOUNT 0x08 -#define MUSB_COUNT0 MUSB_RXCOUNT /* Re-used for EP0 */ -#define MUSB_TXTYPE 0x0A -#define MUSB_TYPE0 MUSB_TXTYPE /* Re-used for EP0 */ -#define MUSB_TXINTERVAL 0x0B -#define MUSB_NAKLIMIT0 MUSB_TXINTERVAL /* Re-used for EP0 */ -#define MUSB_RXTYPE 0x0C -#define MUSB_RXINTERVAL 0x0D -#define MUSB_FIFOSIZE 0x0F -#define MUSB_CONFIGDATA MUSB_FIFOSIZE /* Re-used for EP0 */ - -/* Offsets to endpoint registers in indexed model (using INDEX register) */ -#define MUSB_INDEXED_OFFSET(_epnum, _offset) \ - (0x10 + (_offset)) - -/* Offsets to endpoint registers in flat models */ -#define MUSB_FLAT_OFFSET(_epnum, _offset) \ - (0x100 + (0x10*(_epnum)) + (_offset)) - -#if defined(CONFIG_USB_MUSB_TUSB6010) || \ - defined(CONFIG_USB_MUSB_TUSB6010_MODULE) -/* TUSB6010 EP0 configuration register is special */ -#define MUSB_TUSB_OFFSET(_epnum, _offset) \ - (0x10 + _offset) -#include "tusb6010.h" /* Needed "only" for TUSB_EP0_CONF */ -#endif - -#define MUSB_TXCSR_MODE 0x2000 - -/* "bus control"/target registers, for host side multipoint (external hubs) */ -#define MUSB_TXFUNCADDR 0x00 -#define MUSB_TXHUBADDR 0x02 -#define MUSB_TXHUBPORT 0x03 - -#define MUSB_RXFUNCADDR 0x04 -#define MUSB_RXHUBADDR 0x06 -#define MUSB_RXHUBPORT 0x07 - -#define MUSB_BUSCTL_OFFSET(_epnum, _offset) \ - (0x80 + (8*(_epnum)) + (_offset)) - -static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size) -{ - musb_writeb(mbase, MUSB_TXFIFOSZ, c_size); -} - -static inline void musb_write_txfifoadd(void __iomem *mbase, u16 c_off) -{ - musb_writew(mbase, MUSB_TXFIFOADD, c_off); -} - -static inline void musb_write_rxfifosz(void __iomem *mbase, u8 c_size) -{ - musb_writeb(mbase, MUSB_RXFIFOSZ, c_size); -} - -static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) -{ - musb_writew(mbase, MUSB_RXFIFOADD, c_off); -} - -static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val) -{ - musb_writeb(mbase, MUSB_ULPI_BUSCONTROL, val); -} - -static inline u8 musb_read_txfifosz(void __iomem *mbase) -{ - return musb_readb(mbase, MUSB_TXFIFOSZ); -} - -static inline u16 musb_read_txfifoadd(void __iomem *mbase) -{ - return musb_readw(mbase, MUSB_TXFIFOADD); -} - -static inline u8 musb_read_rxfifosz(void __iomem *mbase) -{ - return musb_readb(mbase, MUSB_RXFIFOSZ); -} - -static inline u16 musb_read_rxfifoadd(void __iomem *mbase) -{ - return musb_readw(mbase, MUSB_RXFIFOADD); -} - -static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase) -{ - return musb_readb(mbase, MUSB_ULPI_BUSCONTROL); -} - -static inline u8 musb_read_configdata(void __iomem *mbase) -{ - musb_writeb(mbase, MUSB_INDEX, 0); - return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA); -} - -static inline u16 musb_read_hwvers(void __iomem *mbase) -{ - return musb_readw(mbase, MUSB_HWVERS); -} - -static inline void __iomem *musb_read_target_reg_base(u8 i, void __iomem *mbase) -{ - return (MUSB_BUSCTL_OFFSET(i, 0) + mbase); -} - -static inline void musb_write_rxfunaddr(void __iomem *ep_target_regs, - u8 qh_addr_reg) -{ - musb_writeb(ep_target_regs, MUSB_RXFUNCADDR, qh_addr_reg); -} - -static inline void musb_write_rxhubaddr(void __iomem *ep_target_regs, - u8 qh_h_addr_reg) -{ - musb_writeb(ep_target_regs, MUSB_RXHUBADDR, qh_h_addr_reg); -} - -static inline void musb_write_rxhubport(void __iomem *ep_target_regs, - u8 qh_h_port_reg) -{ - musb_writeb(ep_target_regs, MUSB_RXHUBPORT, qh_h_port_reg); -} - -static inline void musb_write_txfunaddr(void __iomem *mbase, u8 epnum, - u8 qh_addr_reg) -{ - musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR), - qh_addr_reg); -} - -static inline void musb_write_txhubaddr(void __iomem *mbase, u8 epnum, - u8 qh_addr_reg) -{ - musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR), - qh_addr_reg); -} - -static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum, - u8 qh_h_port_reg) -{ - musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT), - qh_h_port_reg); -} - -static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum) -{ - return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXFUNCADDR)); -} - -static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum) -{ - return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBADDR)); -} - -static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum) -{ - return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBPORT)); -} - -static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum) -{ - return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR)); -} - -static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum) -{ - return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR)); -} - -static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum) -{ - return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT)); -} - -#else /* CONFIG_BLACKFIN */ - -#define USB_BASE USB_FADDR -#define USB_OFFSET(reg) (reg - USB_BASE) - -/* - * Common USB registers - */ -#define MUSB_FADDR USB_OFFSET(USB_FADDR) /* 8-bit */ -#define MUSB_POWER USB_OFFSET(USB_POWER) /* 8-bit */ -#define MUSB_INTRTX USB_OFFSET(USB_INTRTX) /* 16-bit */ -#define MUSB_INTRRX USB_OFFSET(USB_INTRRX) -#define MUSB_INTRTXE USB_OFFSET(USB_INTRTXE) -#define MUSB_INTRRXE USB_OFFSET(USB_INTRRXE) -#define MUSB_INTRUSB USB_OFFSET(USB_INTRUSB) /* 8 bit */ -#define MUSB_INTRUSBE USB_OFFSET(USB_INTRUSBE)/* 8 bit */ -#define MUSB_FRAME USB_OFFSET(USB_FRAME) -#define MUSB_INDEX USB_OFFSET(USB_INDEX) /* 8 bit */ -#define MUSB_TESTMODE USB_OFFSET(USB_TESTMODE)/* 8 bit */ - -/* Get offset for a given FIFO from musb->mregs */ -#define MUSB_FIFO_OFFSET(epnum) \ - (USB_OFFSET(USB_EP0_FIFO) + ((epnum) * 8)) - -/* - * Additional Control Registers - */ - -#define MUSB_DEVCTL USB_OFFSET(USB_OTG_DEV_CTL) /* 8 bit */ - -#define MUSB_LINKINFO USB_OFFSET(USB_LINKINFO)/* 8 bit */ -#define MUSB_VPLEN USB_OFFSET(USB_VPLEN) /* 8 bit */ -#define MUSB_HS_EOF1 USB_OFFSET(USB_HS_EOF1) /* 8 bit */ -#define MUSB_FS_EOF1 USB_OFFSET(USB_FS_EOF1) /* 8 bit */ -#define MUSB_LS_EOF1 USB_OFFSET(USB_LS_EOF1) /* 8 bit */ - -/* Offsets to endpoint registers */ -#define MUSB_TXMAXP 0x00 -#define MUSB_TXCSR 0x04 -#define MUSB_CSR0 MUSB_TXCSR /* Re-used for EP0 */ -#define MUSB_RXMAXP 0x08 -#define MUSB_RXCSR 0x0C -#define MUSB_RXCOUNT 0x10 -#define MUSB_COUNT0 MUSB_RXCOUNT /* Re-used for EP0 */ -#define MUSB_TXTYPE 0x14 -#define MUSB_TYPE0 MUSB_TXTYPE /* Re-used for EP0 */ -#define MUSB_TXINTERVAL 0x18 -#define MUSB_NAKLIMIT0 MUSB_TXINTERVAL /* Re-used for EP0 */ -#define MUSB_RXTYPE 0x1C -#define MUSB_RXINTERVAL 0x20 -#define MUSB_TXCOUNT 0x28 - -/* Offsets to endpoint registers in indexed model (using INDEX register) */ -#define MUSB_INDEXED_OFFSET(_epnum, _offset) \ - (0x40 + (_offset)) - -/* Offsets to endpoint registers in flat models */ -#define MUSB_FLAT_OFFSET(_epnum, _offset) \ - (USB_OFFSET(USB_EP_NI0_TXMAXP) + (0x40 * (_epnum)) + (_offset)) - -/* Not implemented - HW has separate Tx/Rx FIFO */ -#define MUSB_TXCSR_MODE 0x0000 - -static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size) -{ -} - -static inline void musb_write_txfifoadd(void __iomem *mbase, u16 c_off) -{ -} - -static inline void musb_write_rxfifosz(void __iomem *mbase, u8 c_size) -{ -} - -static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) -{ -} - -static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val) -{ -} - -static inline u8 musb_read_txfifosz(void __iomem *mbase) -{ - return 0; -} - -static inline u16 musb_read_txfifoadd(void __iomem *mbase) -{ - return 0; -} - -static inline u8 musb_read_rxfifosz(void __iomem *mbase) -{ - return 0; -} - -static inline u16 musb_read_rxfifoadd(void __iomem *mbase) -{ - return 0; -} - -static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase) -{ - return 0; -} - -static inline u8 musb_read_configdata(void __iomem *mbase) -{ - return 0; -} - -static inline u16 musb_read_hwvers(void __iomem *mbase) -{ - /* - * This register is invisible on Blackfin, actually the MUSB - * RTL version of Blackfin is 1.9, so just harcode its value. - */ - return MUSB_HWVERS_1900; -} - -static inline void __iomem *musb_read_target_reg_base(u8 i, void __iomem *mbase) -{ - return NULL; -} - -static inline void musb_write_rxfunaddr(void __iomem *ep_target_regs, - u8 qh_addr_req) -{ -} - -static inline void musb_write_rxhubaddr(void __iomem *ep_target_regs, - u8 qh_h_addr_reg) -{ -} - -static inline void musb_write_rxhubport(void __iomem *ep_target_regs, - u8 qh_h_port_reg) -{ -} - -static inline void musb_write_txfunaddr(void __iomem *mbase, u8 epnum, - u8 qh_addr_reg) -{ -} - -static inline void musb_write_txhubaddr(void __iomem *mbase, u8 epnum, - u8 qh_addr_reg) -{ -} - -static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum, - u8 qh_h_port_reg) -{ -} - -static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -#endif /* CONFIG_BLACKFIN */ - -#endif /* __MUSB_REGS_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/musb_uboot.c b/qemu/roms/u-boot/drivers/usb/musb-new/musb_uboot.c deleted file mode 100644 index 0d7b89fcf..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/musb_uboot.c +++ /dev/null @@ -1,242 +0,0 @@ -#include <common.h> -#include <watchdog.h> -#include <asm/errno.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> - -#define __UBOOT__ -#include <usb.h> -#include "linux-compat.h" -#include "usb-compat.h" -#include "musb_core.h" -#include "musb_host.h" -#include "musb_gadget.h" - -#ifdef CONFIG_MUSB_HOST -static struct musb *host; -static struct usb_hcd hcd; -static enum usb_device_speed host_speed; - -static void musb_host_complete_urb(struct urb *urb) -{ - urb->dev->status &= ~USB_ST_NOT_PROC; - urb->dev->act_len = urb->actual_length; -} - -static struct usb_host_endpoint hep; -static struct urb urb; - -static struct urb *construct_urb(struct usb_device *dev, int endpoint_type, - unsigned long pipe, void *buffer, int len, - struct devrequest *setup, int interval) -{ - int epnum = usb_pipeendpoint(pipe); - int is_in = usb_pipein(pipe); - - memset(&urb, 0, sizeof(struct urb)); - memset(&hep, 0, sizeof(struct usb_host_endpoint)); - INIT_LIST_HEAD(&hep.urb_list); - INIT_LIST_HEAD(&urb.urb_list); - urb.ep = &hep; - urb.complete = musb_host_complete_urb; - urb.status = -EINPROGRESS; - urb.dev = dev; - urb.pipe = pipe; - urb.transfer_buffer = buffer; - urb.transfer_dma = (unsigned long)buffer; - urb.transfer_buffer_length = len; - urb.setup_packet = (unsigned char *)setup; - - urb.ep->desc.wMaxPacketSize = - __cpu_to_le16(is_in ? dev->epmaxpacketin[epnum] : - dev->epmaxpacketout[epnum]); - urb.ep->desc.bmAttributes = endpoint_type; - urb.ep->desc.bEndpointAddress = - (is_in ? USB_DIR_IN : USB_DIR_OUT) | epnum; - urb.ep->desc.bInterval = interval; - - return &urb; -} - -#define MUSB_HOST_TIMEOUT 0x3ffffff - -static int submit_urb(struct usb_hcd *hcd, struct urb *urb) -{ - struct musb *host = hcd->hcd_priv; - int ret; - int timeout; - - ret = musb_urb_enqueue(hcd, urb, 0); - if (ret < 0) { - printf("Failed to enqueue URB to controller\n"); - return ret; - } - - timeout = MUSB_HOST_TIMEOUT; - do { - if (ctrlc()) - return -EIO; - host->isr(0, host); - } while ((urb->dev->status & USB_ST_NOT_PROC) && --timeout); - - return urb->status; -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int len, struct devrequest *setup) -{ - struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_CONTROL, pipe, - buffer, len, setup, 0); - - /* Fix speed for non hub-attached devices */ - if (!dev->parent) - dev->speed = host_speed; - - return submit_urb(&hcd, urb); -} - - -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int len) -{ - struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_BULK, pipe, - buffer, len, NULL, 0); - return submit_urb(&hcd, urb); -} - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int len, int interval) -{ - struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_INT, pipe, - buffer, len, NULL, interval); - return submit_urb(&hcd, urb); -} - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - u8 power; - void *mbase; - int timeout = MUSB_HOST_TIMEOUT; - - if (!host) { - printf("MUSB host is not registered\n"); - return -ENODEV; - } - - musb_start(host); - mbase = host->mregs; - do { - if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM) - break; - } while (--timeout); - if (!timeout) - return -ENODEV; - - power = musb_readb(mbase, MUSB_POWER); - musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power); - udelay(30000); - power = musb_readb(mbase, MUSB_POWER); - musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power); - host->isr(0, host); - host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ? - USB_SPEED_HIGH : - (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ? - USB_SPEED_FULL : USB_SPEED_LOW; - host->is_active = 1; - hcd.hcd_priv = host; - - return 0; -} - -int usb_lowlevel_stop(int index) -{ - if (!host) { - printf("MUSB host is not registered\n"); - return -ENODEV; - } - - musb_stop(host); - return 0; -} -#endif /* CONFIG_MUSB_HOST */ - -#ifdef CONFIG_MUSB_GADGET -static struct musb *gadget; - -int usb_gadget_handle_interrupts(void) -{ - WATCHDOG_RESET(); - if (!gadget || !gadget->isr) - return -EINVAL; - - return gadget->isr(0, gadget); -} - -int usb_gadget_register_driver(struct usb_gadget_driver *driver) -{ - int ret; - - if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind || - !driver->setup) { - printf("bad parameter.\n"); - return -EINVAL; - } - - if (!gadget) { - printf("Controller uninitialized\n"); - return -ENXIO; - } - - ret = musb_gadget_start(&gadget->g, driver); - if (ret < 0) { - printf("gadget_start failed with %d\n", ret); - return ret; - } - - ret = driver->bind(&gadget->g); - if (ret < 0) { - printf("bind failed with %d\n", ret); - return ret; - } - - return 0; -} - -int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -{ - if (driver->disconnect) - driver->disconnect(&gadget->g); - if (driver->unbind) - driver->unbind(&gadget->g); - return 0; -} -#endif /* CONFIG_MUSB_GADGET */ - -int musb_register(struct musb_hdrc_platform_data *plat, void *bdata, - void *ctl_regs) -{ - struct musb **musbp; - - switch (plat->mode) { -#ifdef CONFIG_MUSB_HOST - case MUSB_HOST: - musbp = &host; - break; -#endif -#ifdef CONFIG_MUSB_GADGET - case MUSB_PERIPHERAL: - musbp = &gadget; - break; -#endif - default: - return -EINVAL; - } - - *musbp = musb_init_controller(plat, (struct device *)bdata, ctl_regs); - if (!musbp) { - printf("Failed to init the controller\n"); - return -EIO; - } - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/omap2430.c b/qemu/roms/u-boot/drivers/usb/musb-new/omap2430.c deleted file mode 100644 index b1c4dc782..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/omap2430.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * Copyright (C) 2005-2007 by Texas Instruments - * Some code has been taken from tusb6010.c - * Copyrights for that are attributable to: - * Copyright (C) 2006 Nokia Corporation - * Tony Lindgren <tony@atomide.com> - * - * This file is part of the Inventra Controller Driver for Linux. - * - * The Inventra Controller Driver for Linux is free software; you - * can redistribute it and/or modify it under the terms of the GNU - * General Public License version 2 as published by the Free Software - * Foundation. - * - * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; if not, - * write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - */ -#define __UBOOT__ -#ifndef __UBOOT__ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/dma-mapping.h> -#include <linux/pm_runtime.h> -#include <linux/err.h> -#include <linux/usb/musb-omap.h> -#else -#include <common.h> -#include <asm/omap_musb.h> -#include <twl4030.h> -#include "linux-compat.h" -#endif - -#include "musb_core.h" -#include "omap2430.h" - -#ifndef __UBOOT__ -struct omap2430_glue { - struct device *dev; - struct platform_device *musb; - enum omap_musb_vbus_id_status status; - struct work_struct omap_musb_mailbox_work; -}; -#define glue_to_musb(g) platform_get_drvdata(g->musb) - -struct omap2430_glue *_glue; - -static struct timer_list musb_idle_timer; - -static void musb_do_idle(unsigned long _musb) -{ - struct musb *musb = (void *)_musb; - unsigned long flags; - u8 power; - u8 devctl; - - spin_lock_irqsave(&musb->lock, flags); - - switch (musb->xceiv->state) { - case OTG_STATE_A_WAIT_BCON: - - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - if (devctl & MUSB_DEVCTL_BDEVICE) { - musb->xceiv->state = OTG_STATE_B_IDLE; - MUSB_DEV_MODE(musb); - } else { - musb->xceiv->state = OTG_STATE_A_IDLE; - MUSB_HST_MODE(musb); - } - break; - case OTG_STATE_A_SUSPEND: - /* finish RESUME signaling? */ - if (musb->port1_status & MUSB_PORT_STAT_RESUME) { - power = musb_readb(musb->mregs, MUSB_POWER); - power &= ~MUSB_POWER_RESUME; - dev_dbg(musb->controller, "root port resume stopped, power %02x\n", power); - musb_writeb(musb->mregs, MUSB_POWER, power); - musb->is_active = 1; - musb->port1_status &= ~(USB_PORT_STAT_SUSPEND - | MUSB_PORT_STAT_RESUME); - musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; - usb_hcd_poll_rh_status(musb_to_hcd(musb)); - /* NOTE: it might really be A_WAIT_BCON ... */ - musb->xceiv->state = OTG_STATE_A_HOST; - } - break; - case OTG_STATE_A_HOST: - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - if (devctl & MUSB_DEVCTL_BDEVICE) - musb->xceiv->state = OTG_STATE_B_IDLE; - else - musb->xceiv->state = OTG_STATE_A_WAIT_BCON; - default: - break; - } - spin_unlock_irqrestore(&musb->lock, flags); -} - - -static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout) -{ - unsigned long default_timeout = jiffies + msecs_to_jiffies(3); - static unsigned long last_timer; - - if (timeout == 0) - timeout = default_timeout; - - /* Never idle if active, or when VBUS timeout is not set as host */ - if (musb->is_active || ((musb->a_wait_bcon == 0) - && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { - dev_dbg(musb->controller, "%s active, deleting timer\n", - otg_state_string(musb->xceiv->state)); - del_timer(&musb_idle_timer); - last_timer = jiffies; - return; - } - - if (time_after(last_timer, timeout)) { - if (!timer_pending(&musb_idle_timer)) - last_timer = timeout; - else { - dev_dbg(musb->controller, "Longer idle timer already pending, ignoring\n"); - return; - } - } - last_timer = timeout; - - dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n", - otg_state_string(musb->xceiv->state), - (unsigned long)jiffies_to_msecs(timeout - jiffies)); - mod_timer(&musb_idle_timer, timeout); -} - -static void omap2430_musb_set_vbus(struct musb *musb, int is_on) -{ - struct usb_otg *otg = musb->xceiv->otg; - u8 devctl; - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - int ret = 1; - /* HDRC controls CPEN, but beware current surges during device - * connect. They can trigger transient overcurrent conditions - * that must be ignored. - */ - - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - - if (is_on) { - if (musb->xceiv->state == OTG_STATE_A_IDLE) { - /* start the session */ - devctl |= MUSB_DEVCTL_SESSION; - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - /* - * Wait for the musb to set as A device to enable the - * VBUS - */ - while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) { - - cpu_relax(); - - if (time_after(jiffies, timeout)) { - dev_err(musb->controller, - "configured as A device timeout"); - ret = -EINVAL; - break; - } - } - - if (ret && otg->set_vbus) - otg_set_vbus(otg, 1); - } else { - musb->is_active = 1; - otg->default_a = 1; - musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; - devctl |= MUSB_DEVCTL_SESSION; - MUSB_HST_MODE(musb); - } - } else { - musb->is_active = 0; - - /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and - * jumping right to B_IDLE... - */ - - otg->default_a = 0; - musb->xceiv->state = OTG_STATE_B_IDLE; - devctl &= ~MUSB_DEVCTL_SESSION; - - MUSB_DEV_MODE(musb); - } - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - - dev_dbg(musb->controller, "VBUS %s, devctl %02x " - /* otg %3x conf %08x prcm %08x */ "\n", - otg_state_string(musb->xceiv->state), - musb_readb(musb->mregs, MUSB_DEVCTL)); -} - -static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode) -{ - u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - - devctl |= MUSB_DEVCTL_SESSION; - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - - return 0; -} -#endif - -static inline void omap2430_low_level_exit(struct musb *musb) -{ - u32 l; - - /* in any role */ - l = musb_readl(musb->mregs, OTG_FORCESTDBY); - l |= ENABLEFORCE; /* enable MSTANDBY */ - musb_writel(musb->mregs, OTG_FORCESTDBY, l); -} - -static inline void omap2430_low_level_init(struct musb *musb) -{ - u32 l; - - l = musb_readl(musb->mregs, OTG_FORCESTDBY); - l &= ~ENABLEFORCE; /* disable MSTANDBY */ - musb_writel(musb->mregs, OTG_FORCESTDBY, l); -} - -#ifndef __UBOOT__ -void omap_musb_mailbox(enum omap_musb_vbus_id_status status) -{ - struct omap2430_glue *glue = _glue; - struct musb *musb = glue_to_musb(glue); - - glue->status = status; - if (!musb) { - dev_err(glue->dev, "musb core is not yet ready\n"); - return; - } - - schedule_work(&glue->omap_musb_mailbox_work); -} -EXPORT_SYMBOL_GPL(omap_musb_mailbox); - -static void omap_musb_set_mailbox(struct omap2430_glue *glue) -{ - struct musb *musb = glue_to_musb(glue); - struct device *dev = musb->controller; - struct musb_hdrc_platform_data *pdata = dev->platform_data; - struct omap_musb_board_data *data = pdata->board_data; - struct usb_otg *otg = musb->xceiv->otg; - - switch (glue->status) { - case OMAP_MUSB_ID_GROUND: - dev_dbg(dev, "ID GND\n"); - - otg->default_a = true; - musb->xceiv->state = OTG_STATE_A_IDLE; - musb->xceiv->last_event = USB_EVENT_ID; - if (!is_otg_enabled(musb) || musb->gadget_driver) { - pm_runtime_get_sync(dev); - usb_phy_init(musb->xceiv); - omap2430_musb_set_vbus(musb, 1); - } - break; - - case OMAP_MUSB_VBUS_VALID: - dev_dbg(dev, "VBUS Connect\n"); - - otg->default_a = false; - musb->xceiv->state = OTG_STATE_B_IDLE; - musb->xceiv->last_event = USB_EVENT_VBUS; - if (musb->gadget_driver) - pm_runtime_get_sync(dev); - usb_phy_init(musb->xceiv); - break; - - case OMAP_MUSB_ID_FLOAT: - case OMAP_MUSB_VBUS_OFF: - dev_dbg(dev, "VBUS Disconnect\n"); - - musb->xceiv->last_event = USB_EVENT_NONE; - if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) - if (musb->gadget_driver) { - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - } - - if (data->interface_type == MUSB_INTERFACE_UTMI) { - if (musb->xceiv->otg->set_vbus) - otg_set_vbus(musb->xceiv->otg, 0); - } - usb_phy_shutdown(musb->xceiv); - break; - default: - dev_dbg(dev, "ID float\n"); - } -} - - -static void omap_musb_mailbox_work(struct work_struct *mailbox_work) -{ - struct omap2430_glue *glue = container_of(mailbox_work, - struct omap2430_glue, omap_musb_mailbox_work); - omap_musb_set_mailbox(glue); -} -#endif - -static int omap2430_musb_init(struct musb *musb) -{ - u32 l; - int status = 0; -#ifndef __UBOOT__ - struct device *dev = musb->controller; - struct omap2430_glue *glue = dev_get_drvdata(dev->parent); - struct musb_hdrc_platform_data *plat = dev->platform_data; - struct omap_musb_board_data *data = plat->board_data; -#else - struct omap_musb_board_data *data = - (struct omap_musb_board_data *)musb->controller; -#endif - - -#ifndef __UBOOT__ - /* We require some kind of external transceiver, hooked - * up through ULPI. TWL4030-family PMICs include one, - * which needs a driver, drivers aren't always needed. - */ - musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(musb->xceiv)) { - pr_err("HS USB OTG: no transceiver configured\n"); - return -ENODEV; - } - - status = pm_runtime_get_sync(dev); - if (status < 0) { - dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status); - goto err1; - } -#endif - - l = musb_readl(musb->mregs, OTG_INTERFSEL); - - if (data->interface_type == MUSB_INTERFACE_UTMI) { - /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */ - l &= ~ULPI_12PIN; /* Disable ULPI */ - l |= UTMI_8BIT; /* Enable UTMI */ - } else { - l |= ULPI_12PIN; - } - - musb_writel(musb->mregs, OTG_INTERFSEL, l); - - pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " - "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", - musb_readl(musb->mregs, OTG_REVISION), - musb_readl(musb->mregs, OTG_SYSCONFIG), - musb_readl(musb->mregs, OTG_SYSSTATUS), - musb_readl(musb->mregs, OTG_INTERFSEL), - musb_readl(musb->mregs, OTG_SIMENABLE)); - -#ifndef __UBOOT__ - setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); - - if (glue->status != OMAP_MUSB_UNKNOWN) - omap_musb_set_mailbox(glue); - - pm_runtime_put_noidle(musb->controller); -#endif - return 0; - -err1: - return status; -} - -static void omap2430_musb_enable(struct musb *musb) -{ -#ifndef __UBOOT__ - u8 devctl; - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - struct device *dev = musb->controller; - struct omap2430_glue *glue = dev_get_drvdata(dev->parent); - struct musb_hdrc_platform_data *pdata = dev->platform_data; - struct omap_musb_board_data *data = pdata->board_data; - - switch (glue->status) { - - case OMAP_MUSB_ID_GROUND: - usb_phy_init(musb->xceiv); - if (data->interface_type != MUSB_INTERFACE_UTMI) - break; - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - /* start the session */ - devctl |= MUSB_DEVCTL_SESSION; - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - while (musb_readb(musb->mregs, MUSB_DEVCTL) & - MUSB_DEVCTL_BDEVICE) { - cpu_relax(); - - if (time_after(jiffies, timeout)) { - dev_err(dev, "configured as A device timeout"); - break; - } - } - break; - - case OMAP_MUSB_VBUS_VALID: - usb_phy_init(musb->xceiv); - break; - - default: - break; - } -#else -#ifdef CONFIG_TWL4030_USB - if (twl4030_usb_ulpi_init()) { - serial_printf("ERROR: %s Could not initialize PHY\n", - __PRETTY_FUNCTION__); - } -#endif -#endif -} - -static void omap2430_musb_disable(struct musb *musb) -{ -#ifndef __UBOOT__ - struct device *dev = musb->controller; - struct omap2430_glue *glue = dev_get_drvdata(dev->parent); - - if (glue->status != OMAP_MUSB_UNKNOWN) - usb_phy_shutdown(musb->xceiv); -#endif -} - -static int omap2430_musb_exit(struct musb *musb) -{ - del_timer_sync(&musb_idle_timer); - - omap2430_low_level_exit(musb); - - return 0; -} - -#ifndef __UBOOT__ -static const struct musb_platform_ops omap2430_ops = { -#else -const struct musb_platform_ops omap2430_ops = { -#endif - .init = omap2430_musb_init, - .exit = omap2430_musb_exit, - -#ifndef __UBOOT__ - .set_mode = omap2430_musb_set_mode, - .try_idle = omap2430_musb_try_idle, - - .set_vbus = omap2430_musb_set_vbus, -#endif - - .enable = omap2430_musb_enable, - .disable = omap2430_musb_disable, -}; - -#ifndef __UBOOT__ -static u64 omap2430_dmamask = DMA_BIT_MASK(32); - -static int __devinit omap2430_probe(struct platform_device *pdev) -{ - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; - struct platform_device *musb; - struct omap2430_glue *glue; - int ret = -ENOMEM; - - glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); - if (!glue) { - dev_err(&pdev->dev, "failed to allocate glue context\n"); - goto err0; - } - - musb = platform_device_alloc("musb-hdrc", -1); - if (!musb) { - dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err0; - } - - musb->dev.parent = &pdev->dev; - musb->dev.dma_mask = &omap2430_dmamask; - musb->dev.coherent_dma_mask = omap2430_dmamask; - - glue->dev = &pdev->dev; - glue->musb = musb; - glue->status = OMAP_MUSB_UNKNOWN; - - pdata->platform_ops = &omap2430_ops; - - platform_set_drvdata(pdev, glue); - - /* - * REVISIT if we ever have two instances of the wrapper, we will be - * in big trouble - */ - _glue = glue; - - INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work); - - ret = platform_device_add_resources(musb, pdev->resource, - pdev->num_resources); - if (ret) { - dev_err(&pdev->dev, "failed to add resources\n"); - goto err1; - } - - ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); - if (ret) { - dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err1; - } - - pm_runtime_enable(&pdev->dev); - - ret = platform_device_add(musb); - if (ret) { - dev_err(&pdev->dev, "failed to register musb device\n"); - goto err1; - } - - return 0; - -err1: - platform_device_put(musb); - -err0: - return ret; -} - -static int __devexit omap2430_remove(struct platform_device *pdev) -{ - struct omap2430_glue *glue = platform_get_drvdata(pdev); - - cancel_work_sync(&glue->omap_musb_mailbox_work); - platform_device_del(glue->musb); - platform_device_put(glue->musb); - - return 0; -} - -#ifdef CONFIG_PM - -static int omap2430_runtime_suspend(struct device *dev) -{ - struct omap2430_glue *glue = dev_get_drvdata(dev); - struct musb *musb = glue_to_musb(glue); - - if (musb) { - musb->context.otg_interfsel = musb_readl(musb->mregs, - OTG_INTERFSEL); - - omap2430_low_level_exit(musb); - usb_phy_set_suspend(musb->xceiv, 1); - } - - return 0; -} - -static int omap2430_runtime_resume(struct device *dev) -{ - struct omap2430_glue *glue = dev_get_drvdata(dev); - struct musb *musb = glue_to_musb(glue); - - if (musb) { - omap2430_low_level_init(musb); - musb_writel(musb->mregs, OTG_INTERFSEL, - musb->context.otg_interfsel); - - usb_phy_set_suspend(musb->xceiv, 0); - } - - return 0; -} - -static struct dev_pm_ops omap2430_pm_ops = { - .runtime_suspend = omap2430_runtime_suspend, - .runtime_resume = omap2430_runtime_resume, -}; - -#define DEV_PM_OPS (&omap2430_pm_ops) -#else -#define DEV_PM_OPS NULL -#endif - -static struct platform_driver omap2430_driver = { - .probe = omap2430_probe, - .remove = __devexit_p(omap2430_remove), - .driver = { - .name = "musb-omap2430", - .pm = DEV_PM_OPS, - }, -}; - -MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer"); -MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); -MODULE_LICENSE("GPL v2"); - -static int __init omap2430_init(void) -{ - return platform_driver_register(&omap2430_driver); -} -subsys_initcall(omap2430_init); - -static void __exit omap2430_exit(void) -{ - platform_driver_unregister(&omap2430_driver); -} -module_exit(omap2430_exit); -#endif diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/omap2430.h b/qemu/roms/u-boot/drivers/usb/musb-new/omap2430.h deleted file mode 100644 index 3b795c248..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/omap2430.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2005-2006 by Texas Instruments - * - * The Inventra Controller Driver for Linux is free software; you - * can redistribute it and/or modify it under the terms of the GNU - * General Public License version 2 as published by the Free Software - * Foundation. - */ - -#ifndef __MUSB_OMAP243X_H__ -#define __MUSB_OMAP243X_H__ - -#ifndef __UBOOT__ -#include <plat/usb.h> -#else -#undef RESETDONE -#endif - -/* - * OMAP2430-specific definitions - */ - -#define OTG_REVISION 0x400 - -#define OTG_SYSCONFIG 0x404 -# define MIDLEMODE 12 /* bit position */ -# define FORCESTDBY (0 << MIDLEMODE) -# define NOSTDBY (1 << MIDLEMODE) -# define SMARTSTDBY (2 << MIDLEMODE) - -# define SIDLEMODE 3 /* bit position */ -# define FORCEIDLE (0 << SIDLEMODE) -# define NOIDLE (1 << SIDLEMODE) -# define SMARTIDLE (2 << SIDLEMODE) - -# define ENABLEWAKEUP (1 << 2) -# define SOFTRST (1 << 1) -# define AUTOIDLE (1 << 0) - -#define OTG_SYSSTATUS 0x408 -# define RESETDONE (1 << 0) - -#define OTG_INTERFSEL 0x40c -# define EXTCP (1 << 2) -# define PHYSEL 0 /* bit position */ -# define UTMI_8BIT (0 << PHYSEL) -# define ULPI_12PIN (1 << PHYSEL) -# define ULPI_8PIN (2 << PHYSEL) - -#define OTG_SIMENABLE 0x410 -# define TM1 (1 << 0) - -#define OTG_FORCESTDBY 0x414 -# define ENABLEFORCE (1 << 0) - -#endif /* __MUSB_OMAP243X_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb-new/usb-compat.h b/qemu/roms/u-boot/drivers/usb/musb-new/usb-compat.h deleted file mode 100644 index 27f656f0c..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb-new/usb-compat.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef __USB_COMPAT_H__ -#define __USB_COMPAT_H__ - -#include "usb.h" - -struct usb_hcd { - void *hcd_priv; -}; - -struct usb_host_endpoint { - struct usb_endpoint_descriptor desc; - struct list_head urb_list; - void *hcpriv; -}; - -/* - * urb->transfer_flags: - * - * Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb(). - */ -#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */ -#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */ - -struct urb; - -typedef void (*usb_complete_t)(struct urb *); - -struct urb { - void *hcpriv; /* private data for host controller */ - struct list_head urb_list; /* list head for use by the urb's - * current owner */ - struct usb_device *dev; /* (in) pointer to associated device */ - struct usb_host_endpoint *ep; /* (internal) pointer to endpoint */ - unsigned int pipe; /* (in) pipe information */ - int status; /* (return) non-ISO status */ - unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ - void *transfer_buffer; /* (in) associated data buffer */ - dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ - u32 transfer_buffer_length; /* (in) data buffer length */ - u32 actual_length; /* (return) actual transfer length */ - unsigned char *setup_packet; /* (in) setup packet (control only) */ - int start_frame; /* (modify) start frame (ISO) */ - usb_complete_t complete; /* (in) completion routine */ -}; - -#define usb_hcd_link_urb_to_ep(hcd, urb) ({ \ - int ret = 0; \ - list_add_tail(&urb->urb_list, &urb->ep->urb_list); \ - ret; }) -#define usb_hcd_unlink_urb_from_ep(hcd, urb) list_del_init(&urb->urb_list) - -static inline void usb_hcd_giveback_urb(struct usb_hcd *hcd, - struct urb *urb, - int status) -{ - urb->status = status; - if (urb->complete) - urb->complete(urb); -} - -static inline int usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, - struct urb *urb) -{ - /* TODO: add cache invalidation here */ - return 0; -} - -static inline u16 find_tt(struct usb_device *dev) -{ - u8 chid; - u8 hub; - - /* Find out the nearest parent which is high speed */ - while (dev->parent->parent != NULL) - if (dev->parent->speed != USB_SPEED_HIGH) - dev = dev->parent; - else - break; - - /* determine the port address at that hub */ - hub = dev->parent->devnum; - for (chid = 0; chid < USB_MAXCHILDREN; chid++) - if (dev->parent->children[chid] == dev) - break; - - return (hub << 8) | chid; -} -#endif /* __USB_COMPAT_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb/Makefile b/qemu/roms/u-boot/drivers/usb/musb/Makefile deleted file mode 100644 index 3c9ed98bc..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# (C) Copyright 2000-2007 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -obj-$(CONFIG_MUSB_HCD) += musb_hcd.o musb_core.o -obj-$(CONFIG_MUSB_UDC) += musb_udc.o musb_core.o -obj-$(CONFIG_USB_BLACKFIN) += blackfin_usb.o -obj-$(CONFIG_USB_DAVINCI) += davinci.o -obj-$(CONFIG_USB_OMAP3) += omap3.o -obj-$(CONFIG_USB_DA8XX) += da8xx.o -obj-$(CONFIG_USB_AM35X) += am35x.o diff --git a/qemu/roms/u-boot/drivers/usb/musb/am35x.c b/qemu/roms/u-boot/drivers/usb/musb/am35x.c deleted file mode 100644 index 62c3a6f60..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/am35x.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * am35x.c - TI's AM35x platform specific usb wrapper functions. - * - * Author: Ajay Kumar Gupta <ajay.gupta@ti.com> - * - * Based on drivers/usb/musb/da8xx.c - * - * Copyright (c) 2010 Texas Instruments Incorporated - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> - -#include "am35x.h" - -/* MUSB platform configuration */ -struct musb_config musb_cfg = { - .regs = (struct musb_regs *)AM35X_USB_OTG_CORE_BASE, - .timeout = AM35X_USB_OTG_TIMEOUT, - .musb_speed = 0, -}; - -/* - * Enable the USB phy - */ -static u8 phy_on(void) -{ - u32 devconf2; - u32 timeout; - - devconf2 = readl(&am35x_scm_general_regs->devconf2); - - devconf2 &= ~(DEVCONF2_RESET | DEVCONF2_PHYPWRDN | DEVCONF2_OTGPWRDN | - DEVCONF2_OTGMODE | DEVCONF2_REFFREQ | - DEVCONF2_PHY_GPIOMODE); - devconf2 |= DEVCONF2_SESENDEN | DEVCONF2_VBDTCTEN | DEVCONF2_PHY_PLLON | - DEVCONF2_REFFREQ_13MHZ | DEVCONF2_DATPOL; - - writel(devconf2, &am35x_scm_general_regs->devconf2); - - /* wait until the USB phy is turned on */ - timeout = musb_cfg.timeout; - while (timeout--) - if (readl(&am35x_scm_general_regs->devconf2) & DEVCONF2_PHYCKGD) - return 1; - - /* USB phy was not turned on */ - return 0; -} - -/* - * Disable the USB phy - */ -static void phy_off(void) -{ - u32 devconf2; - - /* - * Power down the on-chip PHY. - */ - devconf2 = readl(&am35x_scm_general_regs->devconf2); - - devconf2 &= ~DEVCONF2_PHY_PLLON; - devconf2 |= DEVCONF2_PHYPWRDN | DEVCONF2_OTGPWRDN; - writel(devconf2, &am35x_scm_general_regs->devconf2); -} - -/* - * This function performs platform specific initialization for usb0. - */ -int musb_platform_init(void) -{ - u32 revision; - u32 sw_reset; - - /* global usb reset */ - sw_reset = readl(&am35x_scm_general_regs->ip_sw_reset); - sw_reset |= (1 << 0); - writel(sw_reset, &am35x_scm_general_regs->ip_sw_reset); - sw_reset &= ~(1 << 0); - writel(sw_reset, &am35x_scm_general_regs->ip_sw_reset); - - /* reset the controller */ - writel(0x1, &am35x_usb_regs->control); - udelay(5000); - - /* start the on-chip usb phy and its pll */ - if (phy_on() == 0) - return -1; - - /* Returns zero if e.g. not clocked */ - revision = readl(&am35x_usb_regs->revision); - if (revision == 0) - return -1; - - return 0; -} - -/* - * This function performs platform specific deinitialization for usb0. - */ -void musb_platform_deinit(void) -{ - /* Turn off the phy */ - phy_off(); -} - -/* - * This function reads data from endpoint fifo for AM35x - * which supports only 32bit read operation. - * - * ep - endpoint number - * length - number of bytes to read from FIFO - * fifo_data - pointer to data buffer into which data is read - */ -__attribute__((weak)) -void read_fifo(u8 ep, u32 length, void *fifo_data) -{ - u8 *data = (u8 *)fifo_data; - u32 val; - int i; - - /* select the endpoint index */ - writeb(ep, &musbr->index); - - if (length > 4) { - for (i = 0; i < (length >> 2); i++) { - val = readl(&musbr->fifox[ep]); - memcpy(data, &val, 4); - data += 4; - } - length %= 4; - } - if (length > 0) { - val = readl(&musbr->fifox[ep]); - memcpy(data, &val, length); - } -} diff --git a/qemu/roms/u-boot/drivers/usb/musb/am35x.h b/qemu/roms/u-boot/drivers/usb/musb/am35x.h deleted file mode 100644 index bebe38d23..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/am35x.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * am35x.h - TI's AM35x platform specific usb wrapper definitions. - * - * Author: Ajay Kumar Gupta <ajay.gupta@ti.com> - * - * Based on drivers/usb/musb/da8xx.h - * - * Copyright (c) 2010 Texas Instruments Incorporated - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __AM35X_USB_H__ -#define __AM35X_USB_H__ - -#include <asm/arch/am35x_def.h> -#include "musb_core.h" - -/* Base address of musb wrapper */ -#define AM35X_USB_OTG_BASE 0x5C040000 - -/* Base address of musb core */ -#define AM35X_USB_OTG_CORE_BASE (AM35X_USB_OTG_BASE + 0x400) - -/* Timeout for AM35x usb module */ -#define AM35X_USB_OTG_TIMEOUT 0x3FFFFFF - -/* - * AM35x platform USB wrapper register overlay. - */ -struct am35x_usb_regs { - u32 revision; - u32 control; - u32 status; - u32 emulation; - u32 reserved0[1]; - u32 autoreq; - u32 srpfixtime; - u32 ep_intsrc; - u32 ep_intsrcset; - u32 ep_intsrcclr; - u32 ep_intmsk; - u32 ep_intmskset; - u32 ep_intmskclr; - u32 ep_intsrcmsked; - u32 reserved1[1]; - u32 core_intsrc; - u32 core_intsrcset; - u32 core_intsrcclr; - u32 core_intmsk; - u32 core_intmskset; - u32 core_intmskclr; - u32 core_intsrcmsked; - u32 reserved2[1]; - u32 eoi; - u32 mop_sop_en; - u32 reserved3[2]; - u32 txmode; - u32 rxmode; - u32 epcount_mode; -}; - -#define am35x_usb_regs ((struct am35x_usb_regs *)AM35X_USB_OTG_BASE) - -/* USB 2.0 PHY Control */ -#define DEVCONF2_PHY_GPIOMODE (1 << 23) -#define DEVCONF2_OTGMODE (3 << 14) -#define DEVCONF2_SESENDEN (1 << 13) /* Vsess_end comparator */ -#define DEVCONF2_VBDTCTEN (1 << 12) /* Vbus comparator */ -#define DEVCONF2_REFFREQ_24MHZ (2 << 8) -#define DEVCONF2_REFFREQ_26MHZ (7 << 8) -#define DEVCONF2_REFFREQ_13MHZ (6 << 8) -#define DEVCONF2_REFFREQ (0xf << 8) -#define DEVCONF2_PHYCKGD (1 << 7) -#define DEVCONF2_VBUSSENSE (1 << 6) -#define DEVCONF2_PHY_PLLON (1 << 5) /* override PLL suspend */ -#define DEVCONF2_RESET (1 << 4) -#define DEVCONF2_PHYPWRDN (1 << 3) -#define DEVCONF2_OTGPWRDN (1 << 2) -#define DEVCONF2_DATPOL (1 << 1) - -#endif /* __AM35X_USB_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb/blackfin_usb.c b/qemu/roms/u-boot/drivers/usb/musb/blackfin_usb.c deleted file mode 100644 index 65fff887d..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/blackfin_usb.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Blackfin MUSB HCD (Host Controller Driver) for u-boot - * - * Copyright (c) 2008-2009 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <common.h> - -#include <usb.h> - -#include <asm/blackfin.h> -#include <asm/clock.h> -#include <asm/mach-common/bits/usb.h> - -#include "musb_core.h" - -#ifndef CONFIG_USB_BLACKFIN_CLKIN -#define CONFIG_USB_BLACKFIN_CLKIN 24 -#endif - -/* MUSB platform configuration */ -struct musb_config musb_cfg = { - .regs = (struct musb_regs *)USB_FADDR, - .timeout = 0x3FFFFFF, - .musb_speed = 0, -}; - -/* - * This function read or write data to endpoint fifo - * Blackfin use DMA polling method to avoid buffer alignment issues - * - * ep - Endpoint number - * length - Number of bytes to write to FIFO - * fifo_data - Pointer to data buffer to be read/write - * is_write - Flag for read or write - */ -void rw_fifo(u8 ep, u32 length, void *fifo_data, int is_write) -{ - struct bfin_musb_dma_regs *regs; - u32 val = (u32)fifo_data; - - blackfin_dcache_flush_invalidate_range(fifo_data, fifo_data + length); - - regs = (void *)USB_DMA_INTERRUPT; - regs += ep; - - /* Setup DMA address register */ - bfin_write16(®s->addr_low, val); - SSYNC(); - - bfin_write16(®s->addr_high, val >> 16); - SSYNC(); - - /* Setup DMA count register */ - bfin_write16(®s->count_low, length); - bfin_write16(®s->count_high, 0); - SSYNC(); - - /* Enable the DMA */ - val = (ep << 4) | DMA_ENA | INT_ENA; - if (is_write) - val |= DIRECTION; - bfin_write16(®s->control, val); - SSYNC(); - - /* Wait for compelete */ - while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << ep))) - continue; - - /* acknowledge dma interrupt */ - bfin_write_USB_DMA_INTERRUPT(1 << ep); - SSYNC(); - - /* Reset DMA */ - bfin_write16(®s->control, 0); - SSYNC(); -} - -void write_fifo(u8 ep, u32 length, void *fifo_data) -{ - rw_fifo(ep, length, fifo_data, 1); -} - -void read_fifo(u8 ep, u32 length, void *fifo_data) -{ - rw_fifo(ep, length, fifo_data, 0); -} - - -/* - * CPU and board-specific MUSB initializations. Aliased function - * signals caller to move on. - */ -static void __def_musb_init(void) -{ -} -void board_musb_init(void) __attribute__((weak, alias("__def_musb_init"))); - -static void bfin_anomaly_init(void) -{ - u32 revid; - - if (!ANOMALY_05000346 && !ANOMALY_05000347) - return; - - revid = bfin_revid(); - -#ifdef __ADSPBF54x__ - if (revid > 0) - return; -#endif -#ifdef __ADSPBF52x__ - if (ANOMALY_BF526 && revid > 0) - return; - if (ANOMALY_BF527 && revid > 1) - return; -#endif - - if (ANOMALY_05000346) { - bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); - SSYNC(); - } - - if (ANOMALY_05000347) { - bfin_write_USB_APHY_CNTRL(0x0); - SSYNC(); - } -} - -int musb_platform_init(void) -{ - /* board specific initialization */ - board_musb_init(); - - bfin_anomaly_init(); - - /* Configure PLL oscillator register */ - bfin_write_USB_PLLOSC_CTRL(0x3080 | - ((480 / CONFIG_USB_BLACKFIN_CLKIN) << 1)); - SSYNC(); - - bfin_write_USB_SRP_CLKDIV((get_sclk()/1000) / 32 - 1); - SSYNC(); - - bfin_write_USB_EP_NI0_RXMAXP(64); - SSYNC(); - - bfin_write_USB_EP_NI0_TXMAXP(64); - SSYNC(); - - /* Route INTRUSB/INTR_RX/INTR_TX to USB_INT0*/ - bfin_write_USB_GLOBINTR(0x7); - SSYNC(); - - bfin_write_USB_GLOBAL_CTL(GLOBAL_ENA | EP1_TX_ENA | EP2_TX_ENA | - EP3_TX_ENA | EP4_TX_ENA | EP5_TX_ENA | - EP6_TX_ENA | EP7_TX_ENA | EP1_RX_ENA | - EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA | - EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA); - SSYNC(); - - return 0; -} - -/* - * This function performs Blackfin platform specific deinitialization for usb. -*/ -void musb_platform_deinit(void) -{ -} diff --git a/qemu/roms/u-boot/drivers/usb/musb/blackfin_usb.h b/qemu/roms/u-boot/drivers/usb/musb/blackfin_usb.h deleted file mode 100644 index de994bf33..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/blackfin_usb.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Blackfin MUSB HCD (Host Controller Driver) for u-boot - * - * Copyright (c) 2008-2009 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef __BLACKFIN_USB_H__ -#define __BLACKFIN_USB_H__ - -#include <linux/types.h> - -/* Every register is 32bit aligned, but only 16bits in size */ -#define ureg(name) u16 name; u16 __pad_##name; - -#define musb_regs musb_regs -struct musb_regs { - /* common registers */ - ureg(faddr) - ureg(power) - ureg(intrtx) - ureg(intrrx) - ureg(intrtxe) - ureg(intrrxe) - ureg(intrusb) - ureg(intrusbe) - ureg(frame) - ureg(index) - ureg(testmode) - ureg(globintr) - ureg(global_ctl) - u32 reserved0[3]; - /* indexed registers */ - ureg(txmaxp) - ureg(txcsr) - ureg(rxmaxp) - ureg(rxcsr) - ureg(rxcount) - ureg(txtype) - ureg(txinterval) - ureg(rxtype) - ureg(rxinterval) - u32 reserved1; - ureg(txcount) - u32 reserved2[5]; - /* fifo */ - u16 fifox[32]; - /* OTG, dynamic FIFO, version & vendor registers */ - u32 reserved3[16]; - ureg(devctl) - ureg(vbus_irq) - ureg(vbus_mask) - u32 reserved4[15]; - ureg(linkinfo) - ureg(vplen) - ureg(hseof1) - ureg(fseof1) - ureg(lseof1) - u32 reserved5[41]; - /* target address registers */ - struct musb_tar_regs { - ureg(txmaxp) - ureg(txcsr) - ureg(rxmaxp) - ureg(rxcsr) - ureg(rxcount) - ureg(txtype) - ureg(txinternal) - ureg(rxtype) - ureg(rxinternal) - u32 reserved6; - ureg(txcount) - u32 reserved7[5]; - } tar[8]; -} __attribute__((packed)); - -struct bfin_musb_dma_regs { - ureg(interrupt); - ureg(control); - ureg(addr_low); - ureg(addr_high); - ureg(count_low); - ureg(count_high); - u32 reserved0[2]; -}; - -#undef ureg - -/* EP5-EP7 are the only ones with 1024 byte FIFOs which BULK really needs */ -#define MUSB_BULK_EP 5 - -/* Blackfin FIFO's are static */ -#define MUSB_NO_DYNAMIC_FIFO - -/* No HUB support :( */ -#define MUSB_NO_MULTIPOINT - -#endif diff --git a/qemu/roms/u-boot/drivers/usb/musb/da8xx.c b/qemu/roms/u-boot/drivers/usb/musb/da8xx.c deleted file mode 100644 index 97d4ddb57..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/da8xx.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * da8xx.c - TI's DA8xx platform specific usb wrapper functions. - * - * Author: Ajay Kumar Gupta <ajay.gupta@ti.com> - * - * Based on drivers/usb/musb/davinci.c - * - * Copyright (C) 2009 Texas Instruments Incorporated - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include <common.h> - -#include "musb_core.h" -#include <asm/arch/da8xx-usb.h> - -/* MUSB platform configuration */ -struct musb_config musb_cfg = { - .regs = (struct musb_regs *)DA8XX_USB_OTG_CORE_BASE, - .timeout = DA8XX_USB_OTG_TIMEOUT, - .musb_speed = 0, -}; - -/* - * This function enables VBUS by driving the GPIO Bank4 Pin 15 high. - */ -static void enable_vbus(void) -{ - u32 value; - - /* configure GPIO bank4 pin 15 in output direction */ - value = readl(&davinci_gpio_bank45->dir); - writel((value & (~DA8XX_USB_VBUS_GPIO)), &davinci_gpio_bank45->dir); - - /* set GPIO bank4 pin 15 high to drive VBUS */ - value = readl(&davinci_gpio_bank45->set_data); - writel((value | DA8XX_USB_VBUS_GPIO), &davinci_gpio_bank45->set_data); -} - -/* - * Enable the usb0 phy. This initialization procedure is explained in - * the DA8xx USB user guide document. - */ -static u8 phy_on(void) -{ - u32 timeout; - u32 cfgchip2; - - cfgchip2 = readl(&davinci_syscfg_regs->cfgchip2); - - cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN | - CFGCHIP2_OTGMODE | CFGCHIP2_REFFREQ); - cfgchip2 |= CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN | CFGCHIP2_PHY_PLLON | - CFGCHIP2_REFFREQ_24MHZ; - - writel(cfgchip2, &davinci_syscfg_regs->cfgchip2); - - /* wait until the usb phy pll locks */ - timeout = musb_cfg.timeout; - while (timeout--) - if (readl(&davinci_syscfg_regs->cfgchip2) & CFGCHIP2_PHYCLKGD) - return 1; - - /* USB phy was not turned on */ - return 0; -} - -/* - * Disable the usb phy - */ -static void phy_off(void) -{ - u32 cfgchip2; - - /* - * Power down the on-chip PHY. - */ - cfgchip2 = readl(&davinci_syscfg_regs->cfgchip2); - cfgchip2 &= ~CFGCHIP2_PHY_PLLON; - cfgchip2 |= CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN; - writel(cfgchip2, &davinci_syscfg_regs->cfgchip2); -} - -/* - * This function performs DA8xx platform specific initialization for usb0. - */ -int musb_platform_init(void) -{ - u32 revision; - - /* enable psc for usb2.0 */ - lpsc_on(33); - - /* enable usb vbus */ - enable_vbus(); - - /* reset the controller */ - writel(0x1, &da8xx_usb_regs->control); - udelay(5000); - - /* start the on-chip usb phy and its pll */ - if (phy_on() == 0) - return -1; - - /* Returns zero if e.g. not clocked */ - revision = readl(&da8xx_usb_regs->revision); - if (revision == 0) - return -1; - - /* Disable all interrupts */ - writel((DA8XX_USB_USBINT_MASK | DA8XX_USB_TXINT_MASK | - DA8XX_USB_RXINT_MASK), &da8xx_usb_regs->intmsk_set); - return 0; -} - -/* - * This function performs DA8xx platform specific deinitialization for usb0. - */ -void musb_platform_deinit(void) -{ - /* Turn of the phy */ - phy_off(); - - /* flush any interrupts */ - writel((DA8XX_USB_USBINT_MASK | DA8XX_USB_TXINT_MASK | - DA8XX_USB_RXINT_MASK), &da8xx_usb_regs->intmsk_clr); - writel(0, &da8xx_usb_regs->eoi); -} diff --git a/qemu/roms/u-boot/drivers/usb/musb/davinci.c b/qemu/roms/u-boot/drivers/usb/musb/davinci.c deleted file mode 100644 index a9707a898..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/davinci.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * TI's Davinci platform specific USB wrapper functions. - * - * Copyright (c) 2008 Texas Instruments - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments - */ - -#include <common.h> -#include <asm/io.h> -#include "davinci.h" -#include <asm/arch/hardware.h> - -#if !defined(CONFIG_DV_USBPHY_CTL) -#define CONFIG_DV_USBPHY_CTL (USBPHY_SESNDEN | USBPHY_VBDTCTEN) -#endif - -/* MUSB platform configuration */ -struct musb_config musb_cfg = { - .regs = (struct musb_regs *)MENTOR_USB0_BASE, - .timeout = DAVINCI_USB_TIMEOUT, - .musb_speed = 0, -}; - -/* MUSB module register overlay */ -struct davinci_usb_regs *dregs; - -/* - * Enable the USB phy - */ -static u8 phy_on(void) -{ - u32 timeout; -#ifdef DAVINCI_DM365EVM - u32 val; -#endif - /* Wait until the USB phy is turned on */ -#ifdef DAVINCI_DM365EVM - writel(USBPHY_PHY24MHZ | USBPHY_SESNDEN | - USBPHY_VBDTCTEN, USBPHY_CTL_PADDR); -#else - writel(CONFIG_DV_USBPHY_CTL, USBPHY_CTL_PADDR); -#endif - timeout = musb_cfg.timeout; - -#ifdef DAVINCI_DM365EVM - /* Set the ownership of GIO33 to USB */ - val = readl(PINMUX4); - val &= ~(PINMUX4_USBDRVBUS_BITCLEAR); - val |= PINMUX4_USBDRVBUS_BITSET; - writel(val, PINMUX4); -#endif - while (timeout--) - if (readl(USBPHY_CTL_PADDR) & USBPHY_PHYCLKGD) - return 1; - - /* USB phy was not turned on */ - return 0; -} - -/* - * Disable the USB phy - */ -static void phy_off(void) -{ - /* powerdown the on-chip PHY and its oscillator */ - writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, USBPHY_CTL_PADDR); -} - -void __enable_vbus(void) -{ - /* - * nothing to do, vbus is handled through the cpu. - * Define this function in board code, if it is - * different on your board. - */ -} -void enable_vbus(void) - __attribute__((weak, alias("__enable_vbus"))); - -/* - * This function performs Davinci platform specific initialization for usb0. - */ -int musb_platform_init(void) -{ - u32 revision; - - /* enable USB VBUS */ - enable_vbus(); - - /* start the on-chip USB phy and its pll */ - if (!phy_on()) - return -1; - - /* reset the controller */ - dregs = (struct davinci_usb_regs *)DAVINCI_USB0_BASE; - writel(1, &dregs->ctrlr); - udelay(5000); - - /* Returns zero if e.g. not clocked */ - revision = readl(&dregs->version); - if (!revision) - return -1; - - /* Disable all interrupts */ - writel(DAVINCI_USB_USBINT_MASK | DAVINCI_USB_RXINT_MASK | - DAVINCI_USB_TXINT_MASK , &dregs->intmsksetr); - return 0; -} - -/* - * This function performs Davinci platform specific deinitialization for usb0. - */ -void musb_platform_deinit(void) -{ - /* Turn of the phy */ - phy_off(); - - /* flush any interrupts */ - writel(DAVINCI_USB_USBINT_MASK | DAVINCI_USB_TXINT_MASK | - DAVINCI_USB_RXINT_MASK , &dregs->intclrr); -} diff --git a/qemu/roms/u-boot/drivers/usb/musb/davinci.h b/qemu/roms/u-boot/drivers/usb/musb/davinci.h deleted file mode 100644 index 9efefe81d..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/davinci.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * TI's Davinci platform specific USB wrapper functions. - * - * Copyright (c) 2008 Texas Instruments - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments - */ - -#ifndef __DAVINCI_USB_H__ -#define __DAVINCI_USB_H__ - -#include <asm/arch/hardware.h> -#include "musb_core.h" - -/* Base address of DAVINCI usb0 wrapper */ -#define DAVINCI_USB0_BASE 0x01C64000 - -/* Base address of DAVINCI musb core */ -#define MENTOR_USB0_BASE (DAVINCI_USB0_BASE+0x400) - -/* - * Davinci platform USB wrapper register overlay. Note: Only the required - * registers are included in this structure. It can be expanded as required. - */ -struct davinci_usb_regs { - u32 version; - u32 ctrlr; - u32 reserved[0x20]; - u32 intclrr; - u32 intmskr; - u32 intmsksetr; -}; - -#define DAVINCI_USB_TX_ENDPTS_MASK 0x1f /* ep0 + 4 tx */ -#define DAVINCI_USB_RX_ENDPTS_MASK 0x1e /* 4 rx */ -#define DAVINCI_USB_USBINT_SHIFT 16 -#define DAVINCI_USB_TXINT_SHIFT 0 -#define DAVINCI_USB_RXINT_SHIFT 8 -#define DAVINCI_INTR_DRVVBUS 0x0100 - -#define DAVINCI_USB_USBINT_MASK 0x01ff0000 /* 8 Mentor, DRVVBUS */ -#define DAVINCI_USB_TXINT_MASK \ - (DAVINCI_USB_TX_ENDPTS_MASK << DAVINCI_USB_TXINT_SHIFT) -#define DAVINCI_USB_RXINT_MASK \ - (DAVINCI_USB_RX_ENDPTS_MASK << DAVINCI_USB_RXINT_SHIFT) -#define MGC_BUSCTL_OFFSET(_bEnd, _bOffset) \ - (0x80 + (8*(_bEnd)) + (_bOffset)) - -/* Integrated highspeed/otg PHY */ -#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) -#define USBPHY_PHY24MHZ (1 << 13) -#define USBPHY_PHYCLKGD (1 << 8) -#define USBPHY_SESNDEN (1 << 7) /* v(sess_end) comparator */ -#define USBPHY_VBDTCTEN (1 << 6) /* v(bus) comparator */ -#define USBPHY_PHYPLLON (1 << 4) /* override pll suspend */ -#define USBPHY_CLKO1SEL (1 << 3) -#define USBPHY_OSCPDWN (1 << 2) -#define USBPHY_PHYPDWN (1 << 0) - -/* Timeout for Davinci USB module */ -#define DAVINCI_USB_TIMEOUT 0x3FFFFFF - -/* IO Expander I2C address and VBUS enable mask */ -#define IOEXP_I2C_ADDR 0x3A -#define IOEXP_VBUSEN_MASK 1 - -/* extern functions */ -extern void lpsc_on(unsigned int id); -extern int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len); -extern int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len); -extern void enable_vbus(void); -#endif /* __DAVINCI_USB_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb/musb_core.c b/qemu/roms/u-boot/drivers/usb/musb/musb_core.c deleted file mode 100644 index 786909fb6..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/musb_core.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Mentor USB OTG Core functionality common for both Host and Device - * functionality. - * - * Copyright (c) 2008 Texas Instruments - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments - */ - -#include <common.h> - -#include "musb_core.h" -struct musb_regs *musbr; - -/* - * program the mentor core to start (enable interrupts, dma, etc.) - */ -void musb_start(void) -{ -#if defined(CONFIG_MUSB_HCD) - u8 devctl; - u8 busctl; -#endif - - /* disable all interrupts */ - writew(0, &musbr->intrtxe); - writew(0, &musbr->intrrxe); - writeb(0, &musbr->intrusbe); - writeb(0, &musbr->testmode); - - /* put into basic highspeed mode and start session */ - writeb(MUSB_POWER_HSENAB, &musbr->power); -#if defined(CONFIG_MUSB_HCD) - /* Program PHY to use EXT VBUS if required */ - if (musb_cfg.extvbus == 1) { - busctl = musb_read_ulpi_buscontrol(musbr); - musb_write_ulpi_buscontrol(musbr, busctl | ULPI_USE_EXTVBUS); - } - - devctl = readb(&musbr->devctl); - writeb(devctl | MUSB_DEVCTL_SESSION, &musbr->devctl); -#endif -} - -#ifdef MUSB_NO_DYNAMIC_FIFO -# define config_fifo(dir, idx, addr) -#else -# define config_fifo(dir, idx, addr) \ - do { \ - writeb(idx, &musbr->dir##fifosz); \ - writew(fifoaddr >> 3, &musbr->dir##fifoadd); \ - } while (0) -#endif - -/* - * This function configures the endpoint configuration. The musb hcd or musb - * device implementation can use this function to configure the endpoints - * and set the FIFO sizes. Note: The summation of FIFO sizes of all endpoints - * should not be more than the available FIFO size. - * - * epinfo - Pointer to EP configuration table - * cnt - Number of entries in the EP conf table. - */ -void musb_configure_ep(const struct musb_epinfo *epinfo, u8 cnt) -{ - u16 csr; - u16 fifoaddr = 64; /* First 64 bytes of FIFO reserved for EP0 */ - u32 fifosize; - u8 idx; - - while (cnt--) { - /* prepare fifosize to write to register */ - fifosize = epinfo->epsize >> 3; - idx = ffs(fifosize) - 1; - - writeb(epinfo->epnum, &musbr->index); - if (epinfo->epdir) { - /* Configure fifo size and fifo base address */ - config_fifo(tx, idx, fifoaddr); - - csr = readw(&musbr->txcsr); -#if defined(CONFIG_MUSB_HCD) - /* clear the data toggle bit */ - writew(csr | MUSB_TXCSR_CLRDATATOG, &musbr->txcsr); -#endif - /* Flush fifo if required */ - if (csr & MUSB_TXCSR_TXPKTRDY) - writew(csr | MUSB_TXCSR_FLUSHFIFO, - &musbr->txcsr); - } else { - /* Configure fifo size and fifo base address */ - config_fifo(rx, idx, fifoaddr); - - csr = readw(&musbr->rxcsr); -#if defined(CONFIG_MUSB_HCD) - /* clear the data toggle bit */ - writew(csr | MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr); -#endif - /* Flush fifo if required */ - if (csr & MUSB_RXCSR_RXPKTRDY) - writew(csr | MUSB_RXCSR_FLUSHFIFO, - &musbr->rxcsr); - } - fifoaddr += epinfo->epsize; - epinfo++; - } -} - -/* - * This function writes data to endpoint fifo - * - * ep - endpoint number - * length - number of bytes to write to FIFO - * fifo_data - Pointer to data buffer that contains the data to write - */ -__attribute__((weak)) -void write_fifo(u8 ep, u32 length, void *fifo_data) -{ - u8 *data = (u8 *)fifo_data; - - /* select the endpoint index */ - writeb(ep, &musbr->index); - - /* write the data to the fifo */ - while (length--) - writeb(*data++, &musbr->fifox[ep]); -} - -/* - * AM35x supports only 32bit read operations so - * use seperate read_fifo() function for it. - */ -#ifndef CONFIG_USB_AM35X -/* - * This function reads data from endpoint fifo - * - * ep - endpoint number - * length - number of bytes to read from FIFO - * fifo_data - pointer to data buffer into which data is read - */ -__attribute__((weak)) -void read_fifo(u8 ep, u32 length, void *fifo_data) -{ - u8 *data = (u8 *)fifo_data; - - /* select the endpoint index */ - writeb(ep, &musbr->index); - - /* read the data to the fifo */ - while (length--) - *data++ = readb(&musbr->fifox[ep]); -} -#endif /* CONFIG_USB_AM35X */ diff --git a/qemu/roms/u-boot/drivers/usb/musb/musb_core.h b/qemu/roms/u-boot/drivers/usb/musb/musb_core.h deleted file mode 100644 index ec8a038c7..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/musb_core.h +++ /dev/null @@ -1,395 +0,0 @@ -/****************************************************************** - * Copyright 2008 Mentor Graphics Corporation - * Copyright (C) 2008 by Texas Instruments - * - * This file is part of the Inventra Controller Driver for Linux. - * - * The Inventra Controller Driver for Linux is free software; you - * can redistribute it and/or modify it under the terms of the GNU - * General Public License version 2 as published by the Free Software - * Foundation. - * - * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; if not, - * write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * ANY DOWNLOAD, USE, REPRODUCTION, MODIFICATION OR DISTRIBUTION - * OF THIS DRIVER INDICATES YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE - * OF THOSE TERMS.THIS DRIVER IS PROVIDED "AS IS" AND MENTOR GRAPHICS - * MAKES NO WARRANTIES, EXPRESS OR IMPLIED, RELATED TO THIS DRIVER. - * MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY; FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. MENTOR GRAPHICS DOES NOT PROVIDE SUPPORT - * SERVICES OR UPDATES FOR THIS DRIVER, EVEN IF YOU ARE A MENTOR - * GRAPHICS SUPPORT CUSTOMER. - ******************************************************************/ - -#ifndef __MUSB_HDRC_DEFS_H__ -#define __MUSB_HDRC_DEFS_H__ - -#include <usb_defs.h> -#include <asm/io.h> - -#ifdef CONFIG_USB_BLACKFIN -# include "blackfin_usb.h" -#endif - -#define MUSB_EP0_FIFOSIZE 64 /* This is non-configurable */ - -/* EP0 */ -struct musb_ep0_regs { - u16 reserved4; - u16 csr0; - u16 reserved5; - u16 reserved6; - u16 count0; - u8 host_type0; - u8 host_naklimit0; - u8 reserved7; - u8 reserved8; - u8 reserved9; - u8 configdata; -}; - -/* EP 1-15 */ -struct musb_epN_regs { - u16 txmaxp; - u16 txcsr; - u16 rxmaxp; - u16 rxcsr; - u16 rxcount; - u8 txtype; - u8 txinterval; - u8 rxtype; - u8 rxinterval; - u8 reserved0; - u8 fifosize; -}; - -/* Mentor USB core register overlay structure */ -#ifndef musb_regs -struct musb_regs { - /* common registers */ - u8 faddr; - u8 power; - u16 intrtx; - u16 intrrx; - u16 intrtxe; - u16 intrrxe; - u8 intrusb; - u8 intrusbe; - u16 frame; - u8 index; - u8 testmode; - /* indexed registers */ - u16 txmaxp; - u16 txcsr; - u16 rxmaxp; - u16 rxcsr; - u16 rxcount; - u8 txtype; - u8 txinterval; - u8 rxtype; - u8 rxinterval; - u8 reserved0; - u8 fifosize; - /* fifo */ - u32 fifox[16]; - /* OTG, dynamic FIFO, version & vendor registers */ - u8 devctl; - u8 reserved1; - u8 txfifosz; - u8 rxfifosz; - u16 txfifoadd; - u16 rxfifoadd; - u32 vcontrol; - u16 hwvers; - u16 reserved2a[1]; - u8 ulpi_busctl; - u8 reserved2b[1]; - u16 reserved2[3]; - u8 epinfo; - u8 raminfo; - u8 linkinfo; - u8 vplen; - u8 hseof1; - u8 fseof1; - u8 lseof1; - u8 reserved3; - /* target address registers */ - struct musb_tar_regs { - u8 txfuncaddr; - u8 reserved0; - u8 txhubaddr; - u8 txhubport; - u8 rxfuncaddr; - u8 reserved1; - u8 rxhubaddr; - u8 rxhubport; - } tar[16]; - /* - * endpoint registers - * ep0 elements are valid when array index is 0 - * otherwise epN is valid - */ - union musb_ep_regs { - struct musb_ep0_regs ep0; - struct musb_epN_regs epN; - } ep[16]; - -} __attribute__((packed)); -#endif - -/* - * MUSB Register bits - */ - -/* POWER */ -#define MUSB_POWER_ISOUPDATE 0x80 -#define MUSB_POWER_SOFTCONN 0x40 -#define MUSB_POWER_HSENAB 0x20 -#define MUSB_POWER_HSMODE 0x10 -#define MUSB_POWER_RESET 0x08 -#define MUSB_POWER_RESUME 0x04 -#define MUSB_POWER_SUSPENDM 0x02 -#define MUSB_POWER_ENSUSPEND 0x01 -#define MUSB_POWER_HSMODE_SHIFT 4 - -/* INTRUSB */ -#define MUSB_INTR_SUSPEND 0x01 -#define MUSB_INTR_RESUME 0x02 -#define MUSB_INTR_RESET 0x04 -#define MUSB_INTR_BABBLE 0x04 -#define MUSB_INTR_SOF 0x08 -#define MUSB_INTR_CONNECT 0x10 -#define MUSB_INTR_DISCONNECT 0x20 -#define MUSB_INTR_SESSREQ 0x40 -#define MUSB_INTR_VBUSERROR 0x80 /* For SESSION end */ - -/* DEVCTL */ -#define MUSB_DEVCTL_BDEVICE 0x80 -#define MUSB_DEVCTL_FSDEV 0x40 -#define MUSB_DEVCTL_LSDEV 0x20 -#define MUSB_DEVCTL_VBUS 0x18 -#define MUSB_DEVCTL_VBUS_SHIFT 3 -#define MUSB_DEVCTL_HM 0x04 -#define MUSB_DEVCTL_HR 0x02 -#define MUSB_DEVCTL_SESSION 0x01 - -/* ULPI VBUSCONTROL */ -#define ULPI_USE_EXTVBUS 0x01 -#define ULPI_USE_EXTVBUSIND 0x02 - -/* TESTMODE */ -#define MUSB_TEST_FORCE_HOST 0x80 -#define MUSB_TEST_FIFO_ACCESS 0x40 -#define MUSB_TEST_FORCE_FS 0x20 -#define MUSB_TEST_FORCE_HS 0x10 -#define MUSB_TEST_PACKET 0x08 -#define MUSB_TEST_K 0x04 -#define MUSB_TEST_J 0x02 -#define MUSB_TEST_SE0_NAK 0x01 - -/* Allocate for double-packet buffering (effectively doubles assigned _SIZE) */ -#define MUSB_FIFOSZ_DPB 0x10 -/* Allocation size (8, 16, 32, ... 4096) */ -#define MUSB_FIFOSZ_SIZE 0x0f - -/* CSR0 */ -#define MUSB_CSR0_FLUSHFIFO 0x0100 -#define MUSB_CSR0_TXPKTRDY 0x0002 -#define MUSB_CSR0_RXPKTRDY 0x0001 - -/* CSR0 in Peripheral mode */ -#define MUSB_CSR0_P_SVDSETUPEND 0x0080 -#define MUSB_CSR0_P_SVDRXPKTRDY 0x0040 -#define MUSB_CSR0_P_SENDSTALL 0x0020 -#define MUSB_CSR0_P_SETUPEND 0x0010 -#define MUSB_CSR0_P_DATAEND 0x0008 -#define MUSB_CSR0_P_SENTSTALL 0x0004 - -/* CSR0 in Host mode */ -#define MUSB_CSR0_H_DIS_PING 0x0800 -#define MUSB_CSR0_H_WR_DATATOGGLE 0x0400 /* Set to allow setting: */ -#define MUSB_CSR0_H_DATATOGGLE 0x0200 /* Data toggle control */ -#define MUSB_CSR0_H_NAKTIMEOUT 0x0080 -#define MUSB_CSR0_H_STATUSPKT 0x0040 -#define MUSB_CSR0_H_REQPKT 0x0020 -#define MUSB_CSR0_H_ERROR 0x0010 -#define MUSB_CSR0_H_SETUPPKT 0x0008 -#define MUSB_CSR0_H_RXSTALL 0x0004 - -/* CSR0 bits to avoid zeroing (write zero clears, write 1 ignored) */ -#define MUSB_CSR0_P_WZC_BITS \ - (MUSB_CSR0_P_SENTSTALL) -#define MUSB_CSR0_H_WZC_BITS \ - (MUSB_CSR0_H_NAKTIMEOUT | MUSB_CSR0_H_RXSTALL \ - | MUSB_CSR0_RXPKTRDY) - -/* TxType/RxType */ -#define MUSB_TYPE_SPEED 0xc0 -#define MUSB_TYPE_SPEED_SHIFT 6 -#define MUSB_TYPE_SPEED_HIGH 1 -#define MUSB_TYPE_SPEED_FULL 2 -#define MUSB_TYPE_SPEED_LOW 3 -#define MUSB_TYPE_PROTO 0x30 /* Implicitly zero for ep0 */ -#define MUSB_TYPE_PROTO_SHIFT 4 -#define MUSB_TYPE_REMOTE_END 0xf /* Implicitly zero for ep0 */ -#define MUSB_TYPE_PROTO_BULK 2 -#define MUSB_TYPE_PROTO_INTR 3 - -/* CONFIGDATA */ -#define MUSB_CONFIGDATA_MPRXE 0x80 /* Auto bulk pkt combining */ -#define MUSB_CONFIGDATA_MPTXE 0x40 /* Auto bulk pkt splitting */ -#define MUSB_CONFIGDATA_BIGENDIAN 0x20 -#define MUSB_CONFIGDATA_HBRXE 0x10 /* HB-ISO for RX */ -#define MUSB_CONFIGDATA_HBTXE 0x08 /* HB-ISO for TX */ -#define MUSB_CONFIGDATA_DYNFIFO 0x04 /* Dynamic FIFO sizing */ -#define MUSB_CONFIGDATA_SOFTCONE 0x02 /* SoftConnect */ -#define MUSB_CONFIGDATA_UTMIDW 0x01 /* Data width 0/1 => 8/16bits */ - -/* TXCSR in Peripheral and Host mode */ -#define MUSB_TXCSR_AUTOSET 0x8000 -#define MUSB_TXCSR_MODE 0x2000 -#define MUSB_TXCSR_DMAENAB 0x1000 -#define MUSB_TXCSR_FRCDATATOG 0x0800 -#define MUSB_TXCSR_DMAMODE 0x0400 -#define MUSB_TXCSR_CLRDATATOG 0x0040 -#define MUSB_TXCSR_FLUSHFIFO 0x0008 -#define MUSB_TXCSR_FIFONOTEMPTY 0x0002 -#define MUSB_TXCSR_TXPKTRDY 0x0001 - -/* TXCSR in Peripheral mode */ -#define MUSB_TXCSR_P_ISO 0x4000 -#define MUSB_TXCSR_P_INCOMPTX 0x0080 -#define MUSB_TXCSR_P_SENTSTALL 0x0020 -#define MUSB_TXCSR_P_SENDSTALL 0x0010 -#define MUSB_TXCSR_P_UNDERRUN 0x0004 - -/* TXCSR in Host mode */ -#define MUSB_TXCSR_H_WR_DATATOGGLE 0x0200 -#define MUSB_TXCSR_H_DATATOGGLE 0x0100 -#define MUSB_TXCSR_H_NAKTIMEOUT 0x0080 -#define MUSB_TXCSR_H_RXSTALL 0x0020 -#define MUSB_TXCSR_H_ERROR 0x0004 -#define MUSB_TXCSR_H_DATATOGGLE_SHIFT 8 - -/* TXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */ -#define MUSB_TXCSR_P_WZC_BITS \ - (MUSB_TXCSR_P_INCOMPTX | MUSB_TXCSR_P_SENTSTALL \ - | MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_FIFONOTEMPTY) -#define MUSB_TXCSR_H_WZC_BITS \ - (MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \ - | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY) - -/* RXCSR in Peripheral and Host mode */ -#define MUSB_RXCSR_AUTOCLEAR 0x8000 -#define MUSB_RXCSR_DMAENAB 0x2000 -#define MUSB_RXCSR_DISNYET 0x1000 -#define MUSB_RXCSR_PID_ERR 0x1000 -#define MUSB_RXCSR_DMAMODE 0x0800 -#define MUSB_RXCSR_INCOMPRX 0x0100 -#define MUSB_RXCSR_CLRDATATOG 0x0080 -#define MUSB_RXCSR_FLUSHFIFO 0x0010 -#define MUSB_RXCSR_DATAERROR 0x0008 -#define MUSB_RXCSR_FIFOFULL 0x0002 -#define MUSB_RXCSR_RXPKTRDY 0x0001 - -/* RXCSR in Peripheral mode */ -#define MUSB_RXCSR_P_ISO 0x4000 -#define MUSB_RXCSR_P_SENTSTALL 0x0040 -#define MUSB_RXCSR_P_SENDSTALL 0x0020 -#define MUSB_RXCSR_P_OVERRUN 0x0004 - -/* RXCSR in Host mode */ -#define MUSB_RXCSR_H_AUTOREQ 0x4000 -#define MUSB_RXCSR_H_WR_DATATOGGLE 0x0400 -#define MUSB_RXCSR_H_DATATOGGLE 0x0200 -#define MUSB_RXCSR_H_RXSTALL 0x0040 -#define MUSB_RXCSR_H_REQPKT 0x0020 -#define MUSB_RXCSR_H_ERROR 0x0004 -#define MUSB_S_RXCSR_H_DATATOGGLE 9 - -/* RXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */ -#define MUSB_RXCSR_P_WZC_BITS \ - (MUSB_RXCSR_P_SENTSTALL | MUSB_RXCSR_P_OVERRUN \ - | MUSB_RXCSR_RXPKTRDY) -#define MUSB_RXCSR_H_WZC_BITS \ - (MUSB_RXCSR_H_RXSTALL | MUSB_RXCSR_H_ERROR \ - | MUSB_RXCSR_DATAERROR | MUSB_RXCSR_RXPKTRDY) - -/* HUBADDR */ -#define MUSB_HUBADDR_MULTI_TT 0x80 - -/* Endpoint configuration information. Note: The value of endpoint fifo size - * element should be either 8,16,32,64,128,256,512,1024,2048 or 4096. Other - * values are not supported - */ -struct musb_epinfo { - u8 epnum; /* endpoint number */ - u8 epdir; /* endpoint direction */ - u16 epsize; /* endpoint FIFO size */ -}; - -/* - * Platform specific MUSB configuration. Any platform using the musb - * functionality should create one instance of this structure in the - * platform specific file. - */ -struct musb_config { - struct musb_regs *regs; - u32 timeout; - u8 musb_speed; - u8 extvbus; -}; - -/* externally defined data */ -extern struct musb_config musb_cfg; -extern struct musb_regs *musbr; - -/* exported functions */ -extern void musb_start(void); -extern void musb_configure_ep(const struct musb_epinfo *epinfo, u8 cnt); -extern void write_fifo(u8 ep, u32 length, void *fifo_data); -extern void read_fifo(u8 ep, u32 length, void *fifo_data); - -#if defined(CONFIG_USB_BLACKFIN) -/* Every USB register is accessed as a 16-bit even if the value itself - * is only 8-bits in size. Fun stuff. - */ -# undef readb -# define readb(addr) (u8)bfin_read16(addr) -# undef writeb -# define writeb(b, addr) bfin_write16(addr, b) -# undef MUSB_TXCSR_MODE /* not supported */ -# define MUSB_TXCSR_MODE 0 -/* - * The USB PHY on current Blackfin processors is a UTMI+ level 2 PHY. - * However, it has no ULPI support - so there are no registers at all. - * That means accesses to ULPI_BUSCONTROL have to be abstracted away. - */ -static inline u8 musb_read_ulpi_buscontrol(struct musb_regs *musbr) -{ - return 0; -} -static inline void musb_write_ulpi_buscontrol(struct musb_regs *musbr, u8 val) -{} -#else -static inline u8 musb_read_ulpi_buscontrol(struct musb_regs *musbr) -{ - return readb(&musbr->ulpi_busctl); -} -static inline void musb_write_ulpi_buscontrol(struct musb_regs *musbr, u8 val) -{ - writeb(val, &musbr->ulpi_busctl); -} -#endif - -#endif /* __MUSB_HDRC_DEFS_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb/musb_debug.h b/qemu/roms/u-boot/drivers/usb/musb/musb_debug.h deleted file mode 100644 index b387fc36e..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/musb_debug.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2009 Wind River Systems, Inc. - * Tom Rix <Tom.Rix@windriver.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* Define MUSB_DEBUG before including this file to get debug macros */ -#ifdef MUSB_DEBUG - -#define MUSB_FLAGS_PRINT(v, x, y) \ - if (((v) & MUSB_##x##_##y)) \ - serial_printf("\t\t"#y"\n") - -static inline void musb_print_pwr(u8 b) -{ - serial_printf("\tpower 0x%2.2x\n", b); - MUSB_FLAGS_PRINT(b, POWER, ISOUPDATE); - MUSB_FLAGS_PRINT(b, POWER, SOFTCONN); - MUSB_FLAGS_PRINT(b, POWER, HSENAB); - MUSB_FLAGS_PRINT(b, POWER, HSMODE); - MUSB_FLAGS_PRINT(b, POWER, RESET); - MUSB_FLAGS_PRINT(b, POWER, RESUME); - MUSB_FLAGS_PRINT(b, POWER, SUSPENDM); - MUSB_FLAGS_PRINT(b, POWER, ENSUSPEND); -} - -static inline void musb_print_csr0(u16 w) -{ - serial_printf("\tcsr0 0x%4.4x\n", w); - MUSB_FLAGS_PRINT(w, CSR0, FLUSHFIFO); - MUSB_FLAGS_PRINT(w, CSR0_P, SVDSETUPEND); - MUSB_FLAGS_PRINT(w, CSR0_P, SVDRXPKTRDY); - MUSB_FLAGS_PRINT(w, CSR0_P, SENDSTALL); - MUSB_FLAGS_PRINT(w, CSR0_P, SETUPEND); - MUSB_FLAGS_PRINT(w, CSR0_P, DATAEND); - MUSB_FLAGS_PRINT(w, CSR0_P, SENTSTALL); - MUSB_FLAGS_PRINT(w, CSR0, TXPKTRDY); - MUSB_FLAGS_PRINT(w, CSR0, RXPKTRDY); -} - -static inline void musb_print_intrusb(u8 b) -{ - serial_printf("\tintrusb 0x%2.2x\n", b); - MUSB_FLAGS_PRINT(b, INTR, VBUSERROR); - MUSB_FLAGS_PRINT(b, INTR, SESSREQ); - MUSB_FLAGS_PRINT(b, INTR, DISCONNECT); - MUSB_FLAGS_PRINT(b, INTR, CONNECT); - MUSB_FLAGS_PRINT(b, INTR, SOF); - MUSB_FLAGS_PRINT(b, INTR, RESUME); - MUSB_FLAGS_PRINT(b, INTR, SUSPEND); - - if (b & MUSB_INTR_BABBLE) - serial_printf("\t\tMUSB_INTR_RESET or MUSB_INTR_BABBLE\n"); - -} - -static inline void musb_print_intrtx(u16 w) -{ - serial_printf("\tintrtx 0x%4.4x\n", w); -} - -static inline void musb_print_intrrx(u16 w) -{ - serial_printf("\tintrx 0x%4.4x\n", w); -} - -static inline void musb_print_devctl(u8 b) -{ - serial_printf("\tdevctl 0x%2.2x\n", b); - if (b & MUSB_DEVCTL_BDEVICE) - serial_printf("\t\tB device\n"); - else - serial_printf("\t\tA device\n"); - if (b & MUSB_DEVCTL_FSDEV) - serial_printf("\t\tFast Device -(host mode)\n"); - if (b & MUSB_DEVCTL_LSDEV) - serial_printf("\t\tSlow Device -(host mode)\n"); - if (b & MUSB_DEVCTL_HM) - serial_printf("\t\tHost mode\n"); - else - serial_printf("\t\tPeripherial mode\n"); - if (b & MUSB_DEVCTL_HR) - serial_printf("\t\tHost request started(B device)\n"); - else - serial_printf("\t\tHost request finished(B device)\n"); - if (b & MUSB_DEVCTL_BDEVICE) { - if (b & MUSB_DEVCTL_SESSION) - serial_printf("\t\tStart of session(B device)\n"); - else - serial_printf("\t\tEnd of session(B device)\n"); - } else { - if (b & MUSB_DEVCTL_SESSION) - serial_printf("\t\tStart of session(A device)\n"); - else - serial_printf("\t\tEnd of session(A device)\n"); - } -} - -static inline void musb_print_config(u8 b) -{ - serial_printf("\tconfig 0x%2.2x\n", b); - if (b & MUSB_CONFIGDATA_MPRXE) - serial_printf("\t\tAuto combine rx bulk packets\n"); - if (b & MUSB_CONFIGDATA_MPTXE) - serial_printf("\t\tAuto split tx bulk packets\n"); - if (b & MUSB_CONFIGDATA_BIGENDIAN) - serial_printf("\t\tBig Endian ordering\n"); - else - serial_printf("\t\tLittle Endian ordering\n"); - if (b & MUSB_CONFIGDATA_HBRXE) - serial_printf("\t\tHigh speed rx iso endpoint\n"); - if (b & MUSB_CONFIGDATA_HBTXE) - serial_printf("\t\tHigh speed tx iso endpoint\n"); - if (b & MUSB_CONFIGDATA_DYNFIFO) - serial_printf("\t\tDynamic fifo sizing\n"); - if (b & MUSB_CONFIGDATA_SOFTCONE) - serial_printf("\t\tSoft Connect\n"); - if (b & MUSB_CONFIGDATA_UTMIDW) - serial_printf("\t\t16 bit data width\n"); - else - serial_printf("\t\t8 bit data width\n"); -} - -static inline void musb_print_rxmaxp(u16 w) -{ - serial_printf("\trxmaxp 0x%4.4x\n", w); -} - -static inline void musb_print_rxcsr(u16 w) -{ - serial_printf("\trxcsr 0x%4.4x\n", w); - MUSB_FLAGS_PRINT(w, RXCSR, AUTOCLEAR); - MUSB_FLAGS_PRINT(w, RXCSR, DMAENAB); - MUSB_FLAGS_PRINT(w, RXCSR, DISNYET); - MUSB_FLAGS_PRINT(w, RXCSR, PID_ERR); - MUSB_FLAGS_PRINT(w, RXCSR, DMAMODE); - MUSB_FLAGS_PRINT(w, RXCSR, CLRDATATOG); - MUSB_FLAGS_PRINT(w, RXCSR, FLUSHFIFO); - MUSB_FLAGS_PRINT(w, RXCSR, DATAERROR); - MUSB_FLAGS_PRINT(w, RXCSR, FIFOFULL); - MUSB_FLAGS_PRINT(w, RXCSR, RXPKTRDY); - MUSB_FLAGS_PRINT(w, RXCSR_P, SENTSTALL); - MUSB_FLAGS_PRINT(w, RXCSR_P, SENDSTALL); - MUSB_FLAGS_PRINT(w, RXCSR_P, OVERRUN); - - if (w & MUSB_RXCSR_P_ISO) - serial_printf("\t\tiso mode\n"); - else - serial_printf("\t\tbulk mode\n"); - -} - -static inline void musb_print_txmaxp(u16 w) -{ - serial_printf("\ttxmaxp 0x%4.4x\n", w); -} - -static inline void musb_print_txcsr(u16 w) -{ - serial_printf("\ttxcsr 0x%4.4x\n", w); - MUSB_FLAGS_PRINT(w, TXCSR, TXPKTRDY); - MUSB_FLAGS_PRINT(w, TXCSR, FIFONOTEMPTY); - MUSB_FLAGS_PRINT(w, TXCSR, FLUSHFIFO); - MUSB_FLAGS_PRINT(w, TXCSR, CLRDATATOG); - MUSB_FLAGS_PRINT(w, TXCSR_P, UNDERRUN); - MUSB_FLAGS_PRINT(w, TXCSR_P, SENTSTALL); - MUSB_FLAGS_PRINT(w, TXCSR_P, SENDSTALL); - - if (w & MUSB_TXCSR_MODE) - serial_printf("\t\tTX mode\n"); - else - serial_printf("\t\tRX mode\n"); -} - -#else - -/* stubs */ - -#define musb_print_pwr(b) -#define musb_print_csr0(w) -#define musb_print_intrusb(b) -#define musb_print_intrtx(w) -#define musb_print_intrrx(w) -#define musb_print_devctl(b) -#define musb_print_config(b) -#define musb_print_rxmaxp(w) -#define musb_print_rxcsr(w) -#define musb_print_txmaxp(w) -#define musb_print_txcsr(w) - -#endif /* MUSB_DEBUG */ diff --git a/qemu/roms/u-boot/drivers/usb/musb/musb_hcd.c b/qemu/roms/u-boot/drivers/usb/musb/musb_hcd.c deleted file mode 100644 index f0ba8aaaa..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/musb_hcd.c +++ /dev/null @@ -1,1172 +0,0 @@ -/* - * Mentor USB OTG Core host controller driver. - * - * Copyright (c) 2008 Texas Instruments - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments - */ - -#include <common.h> -#include <usb.h> -#include "musb_hcd.h" - -/* MSC control transfers */ -#define USB_MSC_BBB_RESET 0xFF -#define USB_MSC_BBB_GET_MAX_LUN 0xFE - -/* Endpoint configuration information */ -static const struct musb_epinfo epinfo[3] = { - {MUSB_BULK_EP, 1, 512}, /* EP1 - Bluk Out - 512 Bytes */ - {MUSB_BULK_EP, 0, 512}, /* EP1 - Bluk In - 512 Bytes */ - {MUSB_INTR_EP, 0, 64} /* EP2 - Interrupt IN - 64 Bytes */ -}; - -/* --- Virtual Root Hub ---------------------------------------------------- */ -#ifdef MUSB_NO_MULTIPOINT -static int rh_devnum; -static u32 port_status; - -#include <usbroothubdes.h> - -#endif - -/* - * This function writes the data toggle value. - */ -static void write_toggle(struct usb_device *dev, u8 ep, u8 dir_out) -{ - u16 toggle = usb_gettoggle(dev, ep, dir_out); - u16 csr; - - if (dir_out) { - csr = readw(&musbr->txcsr); - if (!toggle) { - if (csr & MUSB_TXCSR_MODE) - csr = MUSB_TXCSR_CLRDATATOG; - else - csr = 0; - writew(csr, &musbr->txcsr); - } else { - csr |= MUSB_TXCSR_H_WR_DATATOGGLE; - writew(csr, &musbr->txcsr); - csr |= (toggle << MUSB_TXCSR_H_DATATOGGLE_SHIFT); - writew(csr, &musbr->txcsr); - } - } else { - if (!toggle) { - csr = readw(&musbr->txcsr); - if (csr & MUSB_TXCSR_MODE) - csr = MUSB_RXCSR_CLRDATATOG; - else - csr = 0; - writew(csr, &musbr->rxcsr); - } else { - csr = readw(&musbr->rxcsr); - csr |= MUSB_RXCSR_H_WR_DATATOGGLE; - writew(csr, &musbr->rxcsr); - csr |= (toggle << MUSB_S_RXCSR_H_DATATOGGLE); - writew(csr, &musbr->rxcsr); - } - } -} - -/* - * This function checks if RxStall has occured on the endpoint. If a RxStall - * has occured, the RxStall is cleared and 1 is returned. If RxStall has - * not occured, 0 is returned. - */ -static u8 check_stall(u8 ep, u8 dir_out) -{ - u16 csr; - - /* For endpoint 0 */ - if (!ep) { - csr = readw(&musbr->txcsr); - if (csr & MUSB_CSR0_H_RXSTALL) { - csr &= ~MUSB_CSR0_H_RXSTALL; - writew(csr, &musbr->txcsr); - return 1; - } - } else { /* For non-ep0 */ - if (dir_out) { /* is it tx ep */ - csr = readw(&musbr->txcsr); - if (csr & MUSB_TXCSR_H_RXSTALL) { - csr &= ~MUSB_TXCSR_H_RXSTALL; - writew(csr, &musbr->txcsr); - return 1; - } - } else { /* is it rx ep */ - csr = readw(&musbr->rxcsr); - if (csr & MUSB_RXCSR_H_RXSTALL) { - csr &= ~MUSB_RXCSR_H_RXSTALL; - writew(csr, &musbr->rxcsr); - return 1; - } - } - } - return 0; -} - -/* - * waits until ep0 is ready. Returns 0 if ep is ready, -1 for timeout - * error and -2 for stall. - */ -static int wait_until_ep0_ready(struct usb_device *dev, u32 bit_mask) -{ - u16 csr; - int result = 1; - int timeout = CONFIG_MUSB_TIMEOUT; - - while (result > 0) { - csr = readw(&musbr->txcsr); - if (csr & MUSB_CSR0_H_ERROR) { - csr &= ~MUSB_CSR0_H_ERROR; - writew(csr, &musbr->txcsr); - dev->status = USB_ST_CRC_ERR; - result = -1; - break; - } - - switch (bit_mask) { - case MUSB_CSR0_TXPKTRDY: - if (!(csr & MUSB_CSR0_TXPKTRDY)) { - if (check_stall(MUSB_CONTROL_EP, 0)) { - dev->status = USB_ST_STALLED; - result = -2; - } else - result = 0; - } - break; - - case MUSB_CSR0_RXPKTRDY: - if (check_stall(MUSB_CONTROL_EP, 0)) { - dev->status = USB_ST_STALLED; - result = -2; - } else - if (csr & MUSB_CSR0_RXPKTRDY) - result = 0; - break; - - case MUSB_CSR0_H_REQPKT: - if (!(csr & MUSB_CSR0_H_REQPKT)) { - if (check_stall(MUSB_CONTROL_EP, 0)) { - dev->status = USB_ST_STALLED; - result = -2; - } else - result = 0; - } - break; - } - - /* Check the timeout */ - if (--timeout) - udelay(1); - else { - dev->status = USB_ST_CRC_ERR; - result = -1; - break; - } - } - - return result; -} - -/* - * waits until tx ep is ready. Returns 1 when ep is ready and 0 on error. - */ -static int wait_until_txep_ready(struct usb_device *dev, u8 ep) -{ - u16 csr; - int timeout = CONFIG_MUSB_TIMEOUT; - - do { - if (check_stall(ep, 1)) { - dev->status = USB_ST_STALLED; - return 0; - } - - csr = readw(&musbr->txcsr); - if (csr & MUSB_TXCSR_H_ERROR) { - dev->status = USB_ST_CRC_ERR; - return 0; - } - - /* Check the timeout */ - if (--timeout) - udelay(1); - else { - dev->status = USB_ST_CRC_ERR; - return -1; - } - - } while (csr & MUSB_TXCSR_TXPKTRDY); - return 1; -} - -/* - * waits until rx ep is ready. Returns 1 when ep is ready and 0 on error. - */ -static int wait_until_rxep_ready(struct usb_device *dev, u8 ep) -{ - u16 csr; - int timeout = CONFIG_MUSB_TIMEOUT; - - do { - if (check_stall(ep, 0)) { - dev->status = USB_ST_STALLED; - return 0; - } - - csr = readw(&musbr->rxcsr); - if (csr & MUSB_RXCSR_H_ERROR) { - dev->status = USB_ST_CRC_ERR; - return 0; - } - - /* Check the timeout */ - if (--timeout) - udelay(1); - else { - dev->status = USB_ST_CRC_ERR; - return -1; - } - - } while (!(csr & MUSB_RXCSR_RXPKTRDY)); - return 1; -} - -/* - * This function performs the setup phase of the control transfer - */ -static int ctrlreq_setup_phase(struct usb_device *dev, struct devrequest *setup) -{ - int result; - u16 csr; - - /* write the control request to ep0 fifo */ - write_fifo(MUSB_CONTROL_EP, sizeof(struct devrequest), (void *)setup); - - /* enable transfer of setup packet */ - csr = readw(&musbr->txcsr); - csr |= (MUSB_CSR0_TXPKTRDY|MUSB_CSR0_H_SETUPPKT); - writew(csr, &musbr->txcsr); - - /* wait until the setup packet is transmitted */ - result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY); - dev->act_len = 0; - return result; -} - -/* - * This function handles the control transfer in data phase - */ -static int ctrlreq_in_data_phase(struct usb_device *dev, u32 len, void *buffer) -{ - u16 csr; - u32 rxlen = 0; - u32 nextlen = 0; - u8 maxpktsize = (1 << dev->maxpacketsize) * 8; - u8 *rxbuff = (u8 *)buffer; - u8 rxedlength; - int result; - - while (rxlen < len) { - /* Determine the next read length */ - nextlen = ((len-rxlen) > maxpktsize) ? maxpktsize : (len-rxlen); - - /* Set the ReqPkt bit */ - csr = readw(&musbr->txcsr); - writew(csr | MUSB_CSR0_H_REQPKT, &musbr->txcsr); - result = wait_until_ep0_ready(dev, MUSB_CSR0_RXPKTRDY); - if (result < 0) - return result; - - /* Actual number of bytes received by usb */ - rxedlength = readb(&musbr->rxcount); - - /* Read the data from the RxFIFO */ - read_fifo(MUSB_CONTROL_EP, rxedlength, &rxbuff[rxlen]); - - /* Clear the RxPktRdy Bit */ - csr = readw(&musbr->txcsr); - csr &= ~MUSB_CSR0_RXPKTRDY; - writew(csr, &musbr->txcsr); - - /* short packet? */ - if (rxedlength != nextlen) { - dev->act_len += rxedlength; - break; - } - rxlen += nextlen; - dev->act_len = rxlen; - } - return 0; -} - -/* - * This function handles the control transfer out data phase - */ -static int ctrlreq_out_data_phase(struct usb_device *dev, u32 len, void *buffer) -{ - u16 csr; - u32 txlen = 0; - u32 nextlen = 0; - u8 maxpktsize = (1 << dev->maxpacketsize) * 8; - u8 *txbuff = (u8 *)buffer; - int result = 0; - - while (txlen < len) { - /* Determine the next write length */ - nextlen = ((len-txlen) > maxpktsize) ? maxpktsize : (len-txlen); - - /* Load the data to send in FIFO */ - write_fifo(MUSB_CONTROL_EP, txlen, &txbuff[txlen]); - - /* Set TXPKTRDY bit */ - csr = readw(&musbr->txcsr); - - csr |= MUSB_CSR0_TXPKTRDY; -#if !defined(CONFIG_SOC_DM365) - csr |= MUSB_CSR0_H_DIS_PING; -#endif - writew(csr, &musbr->txcsr); - result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY); - if (result < 0) - break; - - txlen += nextlen; - dev->act_len = txlen; - } - return result; -} - -/* - * This function handles the control transfer out status phase - */ -static int ctrlreq_out_status_phase(struct usb_device *dev) -{ - u16 csr; - int result; - - /* Set the StatusPkt bit */ - csr = readw(&musbr->txcsr); - csr |= (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_H_STATUSPKT); -#if !defined(CONFIG_SOC_DM365) - csr |= MUSB_CSR0_H_DIS_PING; -#endif - writew(csr, &musbr->txcsr); - - /* Wait until TXPKTRDY bit is cleared */ - result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY); - return result; -} - -/* - * This function handles the control transfer in status phase - */ -static int ctrlreq_in_status_phase(struct usb_device *dev) -{ - u16 csr; - int result; - - /* Set the StatusPkt bit and ReqPkt bit */ - csr = MUSB_CSR0_H_REQPKT | MUSB_CSR0_H_STATUSPKT; -#if !defined(CONFIG_SOC_DM365) - csr |= MUSB_CSR0_H_DIS_PING; -#endif - writew(csr, &musbr->txcsr); - result = wait_until_ep0_ready(dev, MUSB_CSR0_H_REQPKT); - - /* clear StatusPkt bit and RxPktRdy bit */ - csr = readw(&musbr->txcsr); - csr &= ~(MUSB_CSR0_RXPKTRDY | MUSB_CSR0_H_STATUSPKT); - writew(csr, &musbr->txcsr); - return result; -} - -/* - * determines the speed of the device (High/Full/Slow) - */ -static u8 get_dev_speed(struct usb_device *dev) -{ - return (dev->speed == USB_SPEED_HIGH) ? MUSB_TYPE_SPEED_HIGH : - ((dev->speed == USB_SPEED_LOW) ? MUSB_TYPE_SPEED_LOW : - MUSB_TYPE_SPEED_FULL); -} - -/* - * configure the hub address and the port address. - */ -static void config_hub_port(struct usb_device *dev, u8 ep) -{ - u8 chid; - u8 hub; - - /* Find out the nearest parent which is high speed */ - while (dev->parent->parent != NULL) - if (get_dev_speed(dev->parent) != MUSB_TYPE_SPEED_HIGH) - dev = dev->parent; - else - break; - - /* determine the port address at that hub */ - hub = dev->parent->devnum; - for (chid = 0; chid < USB_MAXCHILDREN; chid++) - if (dev->parent->children[chid] == dev) - break; - -#ifndef MUSB_NO_MULTIPOINT - /* configure the hub address and the port address */ - writeb(hub, &musbr->tar[ep].txhubaddr); - writeb((chid + 1), &musbr->tar[ep].txhubport); - writeb(hub, &musbr->tar[ep].rxhubaddr); - writeb((chid + 1), &musbr->tar[ep].rxhubport); -#endif -} - -#ifdef MUSB_NO_MULTIPOINT - -static void musb_port_reset(int do_reset) -{ - u8 power = readb(&musbr->power); - - if (do_reset) { - power &= 0xf0; - writeb(power | MUSB_POWER_RESET, &musbr->power); - port_status |= USB_PORT_STAT_RESET; - port_status &= ~USB_PORT_STAT_ENABLE; - udelay(30000); - } else { - writeb(power & ~MUSB_POWER_RESET, &musbr->power); - - power = readb(&musbr->power); - if (power & MUSB_POWER_HSMODE) - port_status |= USB_PORT_STAT_HIGH_SPEED; - - port_status &= ~(USB_PORT_STAT_RESET | (USB_PORT_STAT_C_CONNECTION << 16)); - port_status |= USB_PORT_STAT_ENABLE - | (USB_PORT_STAT_C_RESET << 16) - | (USB_PORT_STAT_C_ENABLE << 16); - } -} - -/* - * root hub control - */ -static int musb_submit_rh_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *cmd) -{ - int leni = transfer_len; - int len = 0; - int stat = 0; - u32 datab[4]; - const u8 *data_buf = (u8 *) datab; - u16 bmRType_bReq; - u16 wValue; - u16 wIndex; - u16 wLength; - u16 int_usb; - - if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { - debug("Root-Hub submit IRQ: NOT implemented\n"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = swap_16(cmd->value); - wIndex = swap_16(cmd->index); - wLength = swap_16(cmd->length); - - debug("--- HUB ----------------------------------------\n"); - debug("submit rh urb, req=%x val=%#x index=%#x len=%d\n", - bmRType_bReq, wValue, wIndex, wLength); - debug("------------------------------------------------\n"); - - switch (bmRType_bReq) { - case RH_GET_STATUS: - debug("RH_GET_STATUS\n"); - - *(__u16 *) data_buf = swap_16(1); - len = 2; - break; - - case RH_GET_STATUS | RH_INTERFACE: - debug("RH_GET_STATUS | RH_INTERFACE\n"); - - *(__u16 *) data_buf = swap_16(0); - len = 2; - break; - - case RH_GET_STATUS | RH_ENDPOINT: - debug("RH_GET_STATUS | RH_ENDPOINT\n"); - - *(__u16 *) data_buf = swap_16(0); - len = 2; - break; - - case RH_GET_STATUS | RH_CLASS: - debug("RH_GET_STATUS | RH_CLASS\n"); - - *(__u32 *) data_buf = swap_32(0); - len = 4; - break; - - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - debug("RH_GET_STATUS | RH_OTHER | RH_CLASS\n"); - - int_usb = readw(&musbr->intrusb); - if (int_usb & MUSB_INTR_CONNECT) { - port_status |= USB_PORT_STAT_CONNECTION - | (USB_PORT_STAT_C_CONNECTION << 16); - port_status |= USB_PORT_STAT_HIGH_SPEED - | USB_PORT_STAT_ENABLE; - } - - if (port_status & USB_PORT_STAT_RESET) - musb_port_reset(0); - - *(__u32 *) data_buf = swap_32(port_status); - len = 4; - break; - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - debug("RH_CLEAR_FEATURE | RH_ENDPOINT\n"); - - switch (wValue) { - case RH_ENDPOINT_STALL: - debug("C_HUB_ENDPOINT_STALL\n"); - len = 0; - break; - } - port_status &= ~(1 << wValue); - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - debug("RH_CLEAR_FEATURE | RH_CLASS\n"); - - switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - debug("C_HUB_LOCAL_POWER\n"); - len = 0; - break; - - case RH_C_HUB_OVER_CURRENT: - debug("C_HUB_OVER_CURRENT\n"); - len = 0; - break; - } - port_status &= ~(1 << wValue); - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - debug("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS\n"); - - switch (wValue) { - case RH_PORT_ENABLE: - len = 0; - break; - - case RH_PORT_SUSPEND: - len = 0; - break; - - case RH_PORT_POWER: - len = 0; - break; - - case RH_C_PORT_CONNECTION: - len = 0; - break; - - case RH_C_PORT_ENABLE: - len = 0; - break; - - case RH_C_PORT_SUSPEND: - len = 0; - break; - - case RH_C_PORT_OVER_CURRENT: - len = 0; - break; - - case RH_C_PORT_RESET: - len = 0; - break; - - default: - debug("invalid wValue\n"); - stat = USB_ST_STALLED; - } - - port_status &= ~(1 << wValue); - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - debug("RH_SET_FEATURE | RH_OTHER | RH_CLASS\n"); - - switch (wValue) { - case RH_PORT_SUSPEND: - len = 0; - break; - - case RH_PORT_RESET: - musb_port_reset(1); - len = 0; - break; - - case RH_PORT_POWER: - len = 0; - break; - - case RH_PORT_ENABLE: - len = 0; - break; - - default: - debug("invalid wValue\n"); - stat = USB_ST_STALLED; - } - - port_status |= 1 << wValue; - break; - - case RH_SET_ADDRESS: - debug("RH_SET_ADDRESS\n"); - - rh_devnum = wValue; - len = 0; - break; - - case RH_GET_DESCRIPTOR: - debug("RH_GET_DESCRIPTOR: %x, %d\n", wValue, wLength); - - switch (wValue) { - case (USB_DT_DEVICE << 8): /* device descriptor */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_dev_des), - wLength)); - data_buf = root_hub_dev_des; - break; - - case (USB_DT_CONFIG << 8): /* configuration descriptor */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_config_des), - wLength)); - data_buf = root_hub_config_des; - break; - - case ((USB_DT_STRING << 8) | 0x00): /* string 0 descriptors */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_str_index0), - wLength)); - data_buf = root_hub_str_index0; - break; - - case ((USB_DT_STRING << 8) | 0x01): /* string 1 descriptors */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_str_index1), - wLength)); - data_buf = root_hub_str_index1; - break; - - default: - debug("invalid wValue\n"); - stat = USB_ST_STALLED; - } - - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: { - u8 *_data_buf = (u8 *) datab; - debug("RH_GET_DESCRIPTOR | RH_CLASS\n"); - - _data_buf[0] = 0x09; /* min length; */ - _data_buf[1] = 0x29; - _data_buf[2] = 0x1; /* 1 port */ - _data_buf[3] = 0x01; /* per-port power switching */ - _data_buf[3] |= 0x10; /* no overcurrent reporting */ - - /* Corresponds to data_buf[4-7] */ - _data_buf[4] = 0; - _data_buf[5] = 5; - _data_buf[6] = 0; - _data_buf[7] = 0x02; - _data_buf[8] = 0xff; - - len = min_t(unsigned int, leni, - min_t(unsigned int, data_buf[0], wLength)); - break; - } - - case RH_GET_CONFIGURATION: - debug("RH_GET_CONFIGURATION\n"); - - *(__u8 *) data_buf = 0x01; - len = 1; - break; - - case RH_SET_CONFIGURATION: - debug("RH_SET_CONFIGURATION\n"); - - len = 0; - break; - - default: - debug("*** *** *** unsupported root hub command *** *** ***\n"); - stat = USB_ST_STALLED; - } - - len = min_t(int, len, leni); - if (buffer != data_buf) - memcpy(buffer, data_buf, len); - - dev->act_len = len; - dev->status = stat; - debug("dev act_len %d, status %lu\n", dev->act_len, dev->status); - - return stat; -} - -static void musb_rh_init(void) -{ - rh_devnum = 0; - port_status = 0; -} - -#else - -static void musb_rh_init(void) {} - -#endif - -/* - * do a control transfer - */ -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, struct devrequest *setup) -{ - int devnum = usb_pipedevice(pipe); - u8 devspeed; - -#ifdef MUSB_NO_MULTIPOINT - /* Control message is for the HUB? */ - if (devnum == rh_devnum) { - int stat = musb_submit_rh_msg(dev, pipe, buffer, len, setup); - if (stat) - return stat; - } -#endif - - /* select control endpoint */ - writeb(MUSB_CONTROL_EP, &musbr->index); - readw(&musbr->txcsr); - -#ifndef MUSB_NO_MULTIPOINT - /* target addr and (for multipoint) hub addr/port */ - writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].txfuncaddr); - writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].rxfuncaddr); -#endif - - /* configure the hub address and the port number as required */ - devspeed = get_dev_speed(dev); - if ((musb_ishighspeed()) && (dev->parent != NULL) && - (devspeed != MUSB_TYPE_SPEED_HIGH)) { - config_hub_port(dev, MUSB_CONTROL_EP); - writeb(devspeed << 6, &musbr->txtype); - } else { - writeb(musb_cfg.musb_speed << 6, &musbr->txtype); -#ifndef MUSB_NO_MULTIPOINT - writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubaddr); - writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubport); - writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubaddr); - writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubport); -#endif - } - - /* Control transfer setup phase */ - if (ctrlreq_setup_phase(dev, setup) < 0) - return 0; - - switch (setup->request) { - case USB_REQ_GET_DESCRIPTOR: - case USB_REQ_GET_CONFIGURATION: - case USB_REQ_GET_INTERFACE: - case USB_REQ_GET_STATUS: - case USB_MSC_BBB_GET_MAX_LUN: - /* control transfer in-data-phase */ - if (ctrlreq_in_data_phase(dev, len, buffer) < 0) - return 0; - /* control transfer out-status-phase */ - if (ctrlreq_out_status_phase(dev) < 0) - return 0; - break; - - case USB_REQ_SET_ADDRESS: - case USB_REQ_SET_CONFIGURATION: - case USB_REQ_SET_FEATURE: - case USB_REQ_SET_INTERFACE: - case USB_REQ_CLEAR_FEATURE: - case USB_MSC_BBB_RESET: - /* control transfer in status phase */ - if (ctrlreq_in_status_phase(dev) < 0) - return 0; - break; - - case USB_REQ_SET_DESCRIPTOR: - /* control transfer out data phase */ - if (ctrlreq_out_data_phase(dev, len, buffer) < 0) - return 0; - /* control transfer in status phase */ - if (ctrlreq_in_status_phase(dev) < 0) - return 0; - break; - - default: - /* unhandled control transfer */ - return -1; - } - - dev->status = 0; - dev->act_len = len; - -#ifdef MUSB_NO_MULTIPOINT - /* Set device address to USB_FADDR register */ - if (setup->request == USB_REQ_SET_ADDRESS) - writeb(dev->devnum, &musbr->faddr); -#endif - - return len; -} - -/* - * do a bulk transfer - */ -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int len) -{ - int dir_out = usb_pipeout(pipe); - int ep = usb_pipeendpoint(pipe); -#ifndef MUSB_NO_MULTIPOINT - int devnum = usb_pipedevice(pipe); -#endif - u8 type; - u16 csr; - u32 txlen = 0; - u32 nextlen = 0; - u8 devspeed; - - /* select bulk endpoint */ - writeb(MUSB_BULK_EP, &musbr->index); - -#ifndef MUSB_NO_MULTIPOINT - /* write the address of the device */ - if (dir_out) - writeb(devnum, &musbr->tar[MUSB_BULK_EP].txfuncaddr); - else - writeb(devnum, &musbr->tar[MUSB_BULK_EP].rxfuncaddr); -#endif - - /* configure the hub address and the port number as required */ - devspeed = get_dev_speed(dev); - if ((musb_ishighspeed()) && (dev->parent != NULL) && - (devspeed != MUSB_TYPE_SPEED_HIGH)) { - /* - * MUSB is in high speed and the destination device is full - * speed device. So configure the hub address and port - * address registers. - */ - config_hub_port(dev, MUSB_BULK_EP); - } else { -#ifndef MUSB_NO_MULTIPOINT - if (dir_out) { - writeb(0, &musbr->tar[MUSB_BULK_EP].txhubaddr); - writeb(0, &musbr->tar[MUSB_BULK_EP].txhubport); - } else { - writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubaddr); - writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubport); - } -#endif - devspeed = musb_cfg.musb_speed; - } - - /* Write the saved toggle bit value */ - write_toggle(dev, ep, dir_out); - - if (dir_out) { /* bulk-out transfer */ - /* Program the TxType register */ - type = (devspeed << MUSB_TYPE_SPEED_SHIFT) | - (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) | - (ep & MUSB_TYPE_REMOTE_END); - writeb(type, &musbr->txtype); - - /* Write maximum packet size to the TxMaxp register */ - writew(dev->epmaxpacketout[ep], &musbr->txmaxp); - while (txlen < len) { - nextlen = ((len-txlen) < dev->epmaxpacketout[ep]) ? - (len-txlen) : dev->epmaxpacketout[ep]; - -#ifdef CONFIG_USB_BLACKFIN - /* Set the transfer data size */ - writew(nextlen, &musbr->txcount); -#endif - - /* Write the data to the FIFO */ - write_fifo(MUSB_BULK_EP, nextlen, - (void *)(((u8 *)buffer) + txlen)); - - /* Set the TxPktRdy bit */ - csr = readw(&musbr->txcsr); - writew(csr | MUSB_TXCSR_TXPKTRDY, &musbr->txcsr); - - /* Wait until the TxPktRdy bit is cleared */ - if (wait_until_txep_ready(dev, MUSB_BULK_EP) != 1) { - readw(&musbr->txcsr); - usb_settoggle(dev, ep, dir_out, - (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1); - dev->act_len = txlen; - return 0; - } - txlen += nextlen; - } - - /* Keep a copy of the data toggle bit */ - csr = readw(&musbr->txcsr); - usb_settoggle(dev, ep, dir_out, - (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1); - } else { /* bulk-in transfer */ - /* Write the saved toggle bit value */ - write_toggle(dev, ep, dir_out); - - /* Program the RxType register */ - type = (devspeed << MUSB_TYPE_SPEED_SHIFT) | - (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) | - (ep & MUSB_TYPE_REMOTE_END); - writeb(type, &musbr->rxtype); - - /* Write the maximum packet size to the RxMaxp register */ - writew(dev->epmaxpacketin[ep], &musbr->rxmaxp); - while (txlen < len) { - nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ? - (len-txlen) : dev->epmaxpacketin[ep]; - - /* Set the ReqPkt bit */ - csr = readw(&musbr->rxcsr); - writew(csr | MUSB_RXCSR_H_REQPKT, &musbr->rxcsr); - - /* Wait until the RxPktRdy bit is set */ - if (wait_until_rxep_ready(dev, MUSB_BULK_EP) != 1) { - csr = readw(&musbr->rxcsr); - usb_settoggle(dev, ep, dir_out, - (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1); - csr &= ~MUSB_RXCSR_RXPKTRDY; - writew(csr, &musbr->rxcsr); - dev->act_len = txlen; - return 0; - } - - /* Read the data from the FIFO */ - read_fifo(MUSB_BULK_EP, nextlen, - (void *)(((u8 *)buffer) + txlen)); - - /* Clear the RxPktRdy bit */ - csr = readw(&musbr->rxcsr); - csr &= ~MUSB_RXCSR_RXPKTRDY; - writew(csr, &musbr->rxcsr); - txlen += nextlen; - } - - /* Keep a copy of the data toggle bit */ - csr = readw(&musbr->rxcsr); - usb_settoggle(dev, ep, dir_out, - (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1); - } - - /* bulk transfer is complete */ - dev->status = 0; - dev->act_len = len; - return 0; -} - -/* - * This function initializes the usb controller module. - */ -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - u8 power; - u32 timeout; - - musb_rh_init(); - - if (musb_platform_init() == -1) - return -1; - - /* Configure all the endpoint FIFO's and start usb controller */ - musbr = musb_cfg.regs; - musb_configure_ep(&epinfo[0], ARRAY_SIZE(epinfo)); - musb_start(); - - /* - * Wait until musb is enabled in host mode with a timeout. There - * should be a usb device connected. - */ - timeout = musb_cfg.timeout; - while (--timeout) - if (readb(&musbr->devctl) & MUSB_DEVCTL_HM) - break; - - /* if musb core is not in host mode, then return */ - if (!timeout) - return -1; - - /* start usb bus reset */ - power = readb(&musbr->power); - writeb(power | MUSB_POWER_RESET, &musbr->power); - - /* After initiating a usb reset, wait for about 20ms to 30ms */ - udelay(30000); - - /* stop usb bus reset */ - power = readb(&musbr->power); - power &= ~MUSB_POWER_RESET; - writeb(power, &musbr->power); - - /* Determine if the connected device is a high/full/low speed device */ - musb_cfg.musb_speed = (readb(&musbr->power) & MUSB_POWER_HSMODE) ? - MUSB_TYPE_SPEED_HIGH : - ((readb(&musbr->devctl) & MUSB_DEVCTL_FSDEV) ? - MUSB_TYPE_SPEED_FULL : MUSB_TYPE_SPEED_LOW); - return 0; -} - -/* - * This function stops the operation of the davinci usb module. - */ -int usb_lowlevel_stop(int index) -{ - /* Reset the USB module */ - musb_platform_deinit(); - writeb(0, &musbr->devctl); - return 0; -} - -/* - * This function supports usb interrupt transfers. Currently, usb interrupt - * transfers are not supported. - */ -int submit_int_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int len, int interval) -{ - int dir_out = usb_pipeout(pipe); - int ep = usb_pipeendpoint(pipe); -#ifndef MUSB_NO_MULTIPOINT - int devnum = usb_pipedevice(pipe); -#endif - u8 type; - u16 csr; - u32 txlen = 0; - u32 nextlen = 0; - u8 devspeed; - - /* select interrupt endpoint */ - writeb(MUSB_INTR_EP, &musbr->index); - -#ifndef MUSB_NO_MULTIPOINT - /* write the address of the device */ - if (dir_out) - writeb(devnum, &musbr->tar[MUSB_INTR_EP].txfuncaddr); - else - writeb(devnum, &musbr->tar[MUSB_INTR_EP].rxfuncaddr); -#endif - - /* configure the hub address and the port number as required */ - devspeed = get_dev_speed(dev); - if ((musb_ishighspeed()) && (dev->parent != NULL) && - (devspeed != MUSB_TYPE_SPEED_HIGH)) { - /* - * MUSB is in high speed and the destination device is full - * speed device. So configure the hub address and port - * address registers. - */ - config_hub_port(dev, MUSB_INTR_EP); - } else { -#ifndef MUSB_NO_MULTIPOINT - if (dir_out) { - writeb(0, &musbr->tar[MUSB_INTR_EP].txhubaddr); - writeb(0, &musbr->tar[MUSB_INTR_EP].txhubport); - } else { - writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubaddr); - writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubport); - } -#endif - devspeed = musb_cfg.musb_speed; - } - - /* Write the saved toggle bit value */ - write_toggle(dev, ep, dir_out); - - if (!dir_out) { /* intrrupt-in transfer */ - /* Write the saved toggle bit value */ - write_toggle(dev, ep, dir_out); - writeb(interval, &musbr->rxinterval); - - /* Program the RxType register */ - type = (devspeed << MUSB_TYPE_SPEED_SHIFT) | - (MUSB_TYPE_PROTO_INTR << MUSB_TYPE_PROTO_SHIFT) | - (ep & MUSB_TYPE_REMOTE_END); - writeb(type, &musbr->rxtype); - - /* Write the maximum packet size to the RxMaxp register */ - writew(dev->epmaxpacketin[ep], &musbr->rxmaxp); - - while (txlen < len) { - nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ? - (len-txlen) : dev->epmaxpacketin[ep]; - - /* Set the ReqPkt bit */ - csr = readw(&musbr->rxcsr); - writew(csr | MUSB_RXCSR_H_REQPKT, &musbr->rxcsr); - - /* Wait until the RxPktRdy bit is set */ - if (wait_until_rxep_ready(dev, MUSB_INTR_EP) != 1) { - csr = readw(&musbr->rxcsr); - usb_settoggle(dev, ep, dir_out, - (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1); - csr &= ~MUSB_RXCSR_RXPKTRDY; - writew(csr, &musbr->rxcsr); - dev->act_len = txlen; - return 0; - } - - /* Read the data from the FIFO */ - read_fifo(MUSB_INTR_EP, nextlen, - (void *)(((u8 *)buffer) + txlen)); - - /* Clear the RxPktRdy bit */ - csr = readw(&musbr->rxcsr); - csr &= ~MUSB_RXCSR_RXPKTRDY; - writew(csr, &musbr->rxcsr); - txlen += nextlen; - } - - /* Keep a copy of the data toggle bit */ - csr = readw(&musbr->rxcsr); - usb_settoggle(dev, ep, dir_out, - (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1); - } - - /* interrupt transfer is complete */ - dev->irq_status = 0; - dev->irq_act_len = len; - dev->irq_handle(dev); - dev->status = 0; - dev->act_len = len; - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/musb/musb_hcd.h b/qemu/roms/u-boot/drivers/usb/musb/musb_hcd.h deleted file mode 100644 index 02b9adcbe..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/musb_hcd.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Mentor USB OTG Core host controller driver. - * - * Copyright (c) 2008 Texas Instruments - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments - */ - -#ifndef __MUSB_HCD_H__ -#define __MUSB_HCD_H__ - -#include "musb_core.h" -#ifdef CONFIG_USB_KEYBOARD -#include <stdio_dev.h> -extern unsigned char new[]; -#endif - -#ifndef CONFIG_MUSB_TIMEOUT -# define CONFIG_MUSB_TIMEOUT 100000 -#endif - -/* This defines the endpoint number used for control transfers */ -#define MUSB_CONTROL_EP 0 - -/* This defines the endpoint number used for bulk transfer */ -#ifndef MUSB_BULK_EP -# define MUSB_BULK_EP 1 -#endif - -/* This defines the endpoint number used for interrupt transfer */ -#define MUSB_INTR_EP 2 - -/* Determine the operating speed of MUSB core */ -#define musb_ishighspeed() \ - ((readb(&musbr->power) & MUSB_POWER_HSMODE) \ - >> MUSB_POWER_HSMODE_SHIFT) - -#define min_t(type, x, y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; }) - -/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 - -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - -/* extern functions */ -extern int musb_platform_init(void); -extern void musb_platform_deinit(void); - -#endif /* __MUSB_HCD_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/musb/musb_udc.c b/qemu/roms/u-boot/drivers/usb/musb/musb_udc.c deleted file mode 100644 index 87640f4e3..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/musb_udc.c +++ /dev/null @@ -1,959 +0,0 @@ -/* - * Copyright (c) 2009 Wind River Systems, Inc. - * Tom Rix <Tom.Rix@windriver.com> - * - * This file is a rewrite of the usb device part of - * repository git.omapzoom.org/repo/u-boot.git, branch master, - * file cpu/omap3/fastboot.c - * - * This is the unique part of its copyright : - * - * ------------------------------------------------------------------------- - * - * (C) Copyright 2008 - 2009 - * Windriver, <www.windriver.com> - * Tom Rix <Tom.Rix@windriver.com> - * - * ------------------------------------------------------------------------- - * - * The details of connecting the device to the uboot usb device subsystem - * came from the old omap3 repository www.sakoman.net/u-boot-omap3.git, - * branch omap3-dev-usb, file drivers/usb/usbdcore_musb.c - * - * This is the unique part of its copyright : - * - * ------------------------------------------------------------------------- - * - * (C) Copyright 2008 Texas Instruments Incorporated. - * - * Based on - * u-boot OMAP1510 USB drivers (drivers/usbdcore_omap1510.c) - * twl4030 init based on linux (drivers/i2c/chips/twl4030_usb.c) - * - * Author: Diego Dompe (diego.dompe@ridgerun.com) - * Atin Malaviya (atin.malaviya@gmail.com) - * - * ------------------------------------------------------------------------- - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usbdevice.h> -#include <usb/udc.h> -#include "../gadget/ep0.h" -#include "musb_core.h" -#if defined(CONFIG_USB_OMAP3) -#include "omap3.h" -#elif defined(CONFIG_USB_AM35X) -#include "am35x.h" -#elif defined(CONFIG_USB_DAVINCI) -#include "davinci.h" -#endif - -/* Define MUSB_DEBUG for debugging */ -/* #define MUSB_DEBUG */ -#include "musb_debug.h" - -#define MAX_ENDPOINT 15 - -#define GET_ENDPOINT(dev,ep) \ -(((struct usb_device_instance *)(dev))->bus->endpoint_array + ep) - -#define SET_EP0_STATE(s) \ -do { \ - if ((0 <= (s)) && (SET_ADDRESS >= (s))) { \ - if ((s) != ep0_state) { \ - if ((debug_setup) && (debug_level > 1)) \ - serial_printf("INFO : Changing state " \ - "from %s to %s in %s at " \ - "line %d\n", \ - ep0_state_strings[ep0_state],\ - ep0_state_strings[s], \ - __PRETTY_FUNCTION__, \ - __LINE__); \ - ep0_state = s; \ - } \ - } else { \ - if (debug_level > 0) \ - serial_printf("Error at %s %d with setting " \ - "state %d is invalid\n", \ - __PRETTY_FUNCTION__, __LINE__, s); \ - } \ -} while (0) - -/* static implies these initialized to 0 or NULL */ -static int debug_setup; -static int debug_level; -static struct musb_epinfo epinfo[MAX_ENDPOINT * 2]; -static enum ep0_state_enum { - IDLE = 0, - TX, - RX, - SET_ADDRESS -} ep0_state = IDLE; -static char *ep0_state_strings[4] = { - "IDLE", - "TX", - "RX", - "SET_ADDRESS", -}; - -static struct urb *ep0_urb; -struct usb_endpoint_instance *ep0_endpoint; -static struct usb_device_instance *udc_device; -static int enabled; - -#ifdef MUSB_DEBUG -static void musb_db_regs(void) -{ - u8 b; - u16 w; - - b = readb(&musbr->faddr); - serial_printf("\tfaddr 0x%2.2x\n", b); - - b = readb(&musbr->power); - musb_print_pwr(b); - - w = readw(&musbr->ep[0].ep0.csr0); - musb_print_csr0(w); - - b = readb(&musbr->devctl); - musb_print_devctl(b); - - b = readb(&musbr->ep[0].ep0.configdata); - musb_print_config(b); - - w = readw(&musbr->frame); - serial_printf("\tframe 0x%4.4x\n", w); - - b = readb(&musbr->index); - serial_printf("\tindex 0x%2.2x\n", b); - - w = readw(&musbr->ep[1].epN.rxmaxp); - musb_print_rxmaxp(w); - - w = readw(&musbr->ep[1].epN.rxcsr); - musb_print_rxcsr(w); - - w = readw(&musbr->ep[1].epN.txmaxp); - musb_print_txmaxp(w); - - w = readw(&musbr->ep[1].epN.txcsr); - musb_print_txcsr(w); -} -#else -#define musb_db_regs() -#endif /* DEBUG_MUSB */ - -static void musb_peri_softconnect(void) -{ - u8 power, devctl; - - /* Power off MUSB */ - power = readb(&musbr->power); - power &= ~MUSB_POWER_SOFTCONN; - writeb(power, &musbr->power); - - /* Read intr to clear */ - readb(&musbr->intrusb); - readw(&musbr->intrrx); - readw(&musbr->intrtx); - - udelay(1000 * 1000); /* 1 sec */ - - /* Power on MUSB */ - power = readb(&musbr->power); - power |= MUSB_POWER_SOFTCONN; - /* - * The usb device interface is usb 1.1 - * Disable 2.0 high speed by clearring the hsenable bit. - */ - power &= ~MUSB_POWER_HSENAB; - writeb(power, &musbr->power); - - /* Check if device is in b-peripheral mode */ - devctl = readb(&musbr->devctl); - if (!(devctl & MUSB_DEVCTL_BDEVICE) || - (devctl & MUSB_DEVCTL_HM)) { - serial_printf("ERROR : Unsupport USB mode\n"); - serial_printf("Check that mini-B USB cable is attached " - "to the device\n"); - } - - if (debug_setup && (debug_level > 1)) - musb_db_regs(); -} - -static void musb_peri_reset(void) -{ - if ((debug_setup) && (debug_level > 1)) - serial_printf("INFO : %s reset\n", __PRETTY_FUNCTION__); - - if (ep0_endpoint) - ep0_endpoint->endpoint_address = 0xff; - - /* Sync sw and hw addresses */ - writeb(udc_device->address, &musbr->faddr); - - SET_EP0_STATE(IDLE); -} - -static void musb_peri_resume(void) -{ - /* noop */ -} - -static void musb_peri_ep0_stall(void) -{ - u16 csr0; - - csr0 = readw(&musbr->ep[0].ep0.csr0); - csr0 |= MUSB_CSR0_P_SENDSTALL; - writew(csr0, &musbr->ep[0].ep0.csr0); - if ((debug_setup) && (debug_level > 1)) - serial_printf("INFO : %s stall\n", __PRETTY_FUNCTION__); -} - -static void musb_peri_ep0_ack_req(void) -{ - u16 csr0; - - csr0 = readw(&musbr->ep[0].ep0.csr0); - csr0 |= MUSB_CSR0_P_SVDRXPKTRDY; - writew(csr0, &musbr->ep[0].ep0.csr0); -} - -static void musb_ep0_tx_ready(void) -{ - u16 csr0; - - csr0 = readw(&musbr->ep[0].ep0.csr0); - csr0 |= MUSB_CSR0_TXPKTRDY; - writew(csr0, &musbr->ep[0].ep0.csr0); -} - -static void musb_ep0_tx_ready_and_last(void) -{ - u16 csr0; - - csr0 = readw(&musbr->ep[0].ep0.csr0); - csr0 |= (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_P_DATAEND); - writew(csr0, &musbr->ep[0].ep0.csr0); -} - -static void musb_peri_ep0_last(void) -{ - u16 csr0; - - csr0 = readw(&musbr->ep[0].ep0.csr0); - csr0 |= MUSB_CSR0_P_DATAEND; - writew(csr0, &musbr->ep[0].ep0.csr0); -} - -static void musb_peri_ep0_set_address(void) -{ - u8 faddr; - writeb(udc_device->address, &musbr->faddr); - - /* Verify */ - faddr = readb(&musbr->faddr); - if (udc_device->address == faddr) { - SET_EP0_STATE(IDLE); - usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0); - if ((debug_setup) && (debug_level > 1)) - serial_printf("INFO : %s Address set to %d\n", - __PRETTY_FUNCTION__, udc_device->address); - } else { - if (debug_level > 0) - serial_printf("ERROR : %s Address missmatch " - "sw %d vs hw %d\n", - __PRETTY_FUNCTION__, - udc_device->address, faddr); - } -} - -static void musb_peri_rx_ack(unsigned int ep) -{ - u16 peri_rxcsr; - - peri_rxcsr = readw(&musbr->ep[ep].epN.rxcsr); - peri_rxcsr &= ~MUSB_RXCSR_RXPKTRDY; - writew(peri_rxcsr, &musbr->ep[ep].epN.rxcsr); -} - -static void musb_peri_tx_ready(unsigned int ep) -{ - u16 peri_txcsr; - - peri_txcsr = readw(&musbr->ep[ep].epN.txcsr); - peri_txcsr |= MUSB_TXCSR_TXPKTRDY; - writew(peri_txcsr, &musbr->ep[ep].epN.txcsr); -} - -static void musb_peri_ep0_zero_data_request(int err) -{ - musb_peri_ep0_ack_req(); - - if (err) { - musb_peri_ep0_stall(); - SET_EP0_STATE(IDLE); - } else { - - musb_peri_ep0_last(); - - /* USBD state */ - switch (ep0_urb->device_request.bRequest) { - case USB_REQ_SET_ADDRESS: - if ((debug_setup) && (debug_level > 1)) - serial_printf("INFO : %s received set " - "address\n", __PRETTY_FUNCTION__); - break; - - case USB_REQ_SET_CONFIGURATION: - if ((debug_setup) && (debug_level > 1)) - serial_printf("INFO : %s Configured\n", - __PRETTY_FUNCTION__); - usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0); - break; - } - - /* EP0 state */ - if (USB_REQ_SET_ADDRESS == ep0_urb->device_request.bRequest) { - SET_EP0_STATE(SET_ADDRESS); - } else { - SET_EP0_STATE(IDLE); - } - } -} - -static void musb_peri_ep0_rx_data_request(void) -{ - /* - * This is the completion of the data OUT / RX - * - * Host is sending data to ep0 that is not - * part of setup. This comes from the cdc_recv_setup - * op that is device specific. - * - */ - musb_peri_ep0_ack_req(); - - ep0_endpoint->rcv_urb = ep0_urb; - ep0_urb->actual_length = 0; - SET_EP0_STATE(RX); -} - -static void musb_peri_ep0_tx_data_request(int err) -{ - if (err) { - musb_peri_ep0_stall(); - SET_EP0_STATE(IDLE); - } else { - musb_peri_ep0_ack_req(); - - ep0_endpoint->tx_urb = ep0_urb; - ep0_endpoint->sent = 0; - SET_EP0_STATE(TX); - } -} - -static void musb_peri_ep0_idle(void) -{ - u16 count0; - int err; - u16 csr0; - - /* - * Verify addresses - * A lot of confusion can be caused if the address - * in software, udc layer, does not agree with the - * hardware. Since the setting of the hardware address - * must be set after the set address request, the - * usb state machine is out of sync for a few frame. - * It is a good idea to run this check when changes - * are made to the state machine. - */ - if ((debug_level > 0) && - (ep0_state != SET_ADDRESS)) { - u8 faddr; - - faddr = readb(&musbr->faddr); - if (udc_device->address != faddr) { - serial_printf("ERROR : %s addresses do not" - "match sw %d vs hw %d\n", - __PRETTY_FUNCTION__, - udc_device->address, faddr); - udelay(1000 * 1000); - hang(); - } - } - - csr0 = readw(&musbr->ep[0].ep0.csr0); - - if (!(MUSB_CSR0_RXPKTRDY & csr0)) - goto end; - - count0 = readw(&musbr->ep[0].ep0.count0); - if (count0 == 0) - goto end; - - if (count0 != 8) { - if ((debug_setup) && (debug_level > 1)) - serial_printf("WARN : %s SETUP incorrect size %d\n", - __PRETTY_FUNCTION__, count0); - musb_peri_ep0_stall(); - goto end; - } - - read_fifo(0, count0, &ep0_urb->device_request); - - if (debug_level > 2) - print_usb_device_request(&ep0_urb->device_request); - - if (ep0_urb->device_request.wLength == 0) { - err = ep0_recv_setup(ep0_urb); - - /* Zero data request */ - musb_peri_ep0_zero_data_request(err); - } else { - /* Is data coming or going ? */ - u8 reqType = ep0_urb->device_request.bmRequestType; - - if (USB_REQ_DEVICE2HOST == (reqType & USB_REQ_DIRECTION_MASK)) { - err = ep0_recv_setup(ep0_urb); - /* Device to host */ - musb_peri_ep0_tx_data_request(err); - } else { - /* - * Host to device - * - * The RX routine will call ep0_recv_setup - * when the data packet has arrived. - */ - musb_peri_ep0_rx_data_request(); - } - } - -end: - return; -} - -static void musb_peri_ep0_rx(void) -{ - /* - * This is the completion of the data OUT / RX - * - * Host is sending data to ep0 that is not - * part of setup. This comes from the cdc_recv_setup - * op that is device specific. - * - * Pass the data back to driver ep0_recv_setup which - * should give the cdc_recv_setup the chance to handle - * the rx - */ - u16 csr0; - u16 count0; - - if (debug_level > 3) { - if (0 != ep0_urb->actual_length) { - serial_printf("%s finished ? %d of %d\n", - __PRETTY_FUNCTION__, - ep0_urb->actual_length, - ep0_urb->device_request.wLength); - } - } - - if (ep0_urb->device_request.wLength == ep0_urb->actual_length) { - musb_peri_ep0_last(); - SET_EP0_STATE(IDLE); - ep0_recv_setup(ep0_urb); - return; - } - - csr0 = readw(&musbr->ep[0].ep0.csr0); - if (!(MUSB_CSR0_RXPKTRDY & csr0)) - return; - - count0 = readw(&musbr->ep[0].ep0.count0); - - if (count0) { - struct usb_endpoint_instance *endpoint; - u32 length; - u8 *data; - - endpoint = ep0_endpoint; - if (endpoint && endpoint->rcv_urb) { - struct urb *urb = endpoint->rcv_urb; - unsigned int remaining_space = urb->buffer_length - - urb->actual_length; - - if (remaining_space) { - int urb_bad = 0; /* urb is good */ - - if (count0 > remaining_space) - length = remaining_space; - else - length = count0; - - data = (u8 *) urb->buffer_data; - data += urb->actual_length; - - /* The common musb fifo reader */ - read_fifo(0, length, data); - - musb_peri_ep0_ack_req(); - - /* - * urb's actual_length is updated in - * usbd_rcv_complete - */ - usbd_rcv_complete(endpoint, length, urb_bad); - - } else { - if (debug_level > 0) - serial_printf("ERROR : %s no space in " - "rcv buffer\n", - __PRETTY_FUNCTION__); - } - } else { - if (debug_level > 0) - serial_printf("ERROR : %s problem with " - "endpoint\n", - __PRETTY_FUNCTION__); - } - } else { - if (debug_level > 0) - serial_printf("ERROR : %s with nothing to do\n", - __PRETTY_FUNCTION__); - } -} - -static void musb_peri_ep0_tx(void) -{ - u16 csr0; - int transfer_size = 0; - unsigned int p, pm; - - csr0 = readw(&musbr->ep[0].ep0.csr0); - - /* Check for pending tx */ - if (csr0 & MUSB_CSR0_TXPKTRDY) - goto end; - - /* Check if this is the last packet sent */ - if (ep0_endpoint->sent >= ep0_urb->actual_length) { - SET_EP0_STATE(IDLE); - goto end; - } - - transfer_size = ep0_urb->actual_length - ep0_endpoint->sent; - /* Is the transfer size negative ? */ - if (transfer_size <= 0) { - if (debug_level > 0) - serial_printf("ERROR : %s problem with the" - " transfer size %d\n", - __PRETTY_FUNCTION__, - transfer_size); - SET_EP0_STATE(IDLE); - goto end; - } - - /* Truncate large transfers to the fifo size */ - if (transfer_size > ep0_endpoint->tx_packetSize) - transfer_size = ep0_endpoint->tx_packetSize; - - write_fifo(0, transfer_size, &ep0_urb->buffer[ep0_endpoint->sent]); - ep0_endpoint->sent += transfer_size; - - /* Done or more to send ? */ - if (ep0_endpoint->sent >= ep0_urb->actual_length) - musb_ep0_tx_ready_and_last(); - else - musb_ep0_tx_ready(); - - /* Wait a bit */ - pm = 10; - for (p = 0; p < pm; p++) { - csr0 = readw(&musbr->ep[0].ep0.csr0); - if (!(csr0 & MUSB_CSR0_TXPKTRDY)) - break; - - /* Double the delay. */ - udelay(1 << pm); - } - - if ((ep0_endpoint->sent >= ep0_urb->actual_length) && (p < pm)) - SET_EP0_STATE(IDLE); - -end: - return; -} - -static void musb_peri_ep0(void) -{ - u16 csr0; - - if (SET_ADDRESS == ep0_state) - return; - - csr0 = readw(&musbr->ep[0].ep0.csr0); - - /* Error conditions */ - if (MUSB_CSR0_P_SENTSTALL & csr0) { - csr0 &= ~MUSB_CSR0_P_SENTSTALL; - writew(csr0, &musbr->ep[0].ep0.csr0); - SET_EP0_STATE(IDLE); - } - if (MUSB_CSR0_P_SETUPEND & csr0) { - csr0 |= MUSB_CSR0_P_SVDSETUPEND; - writew(csr0, &musbr->ep[0].ep0.csr0); - SET_EP0_STATE(IDLE); - if ((debug_setup) && (debug_level > 1)) - serial_printf("WARN: %s SETUPEND\n", - __PRETTY_FUNCTION__); - } - - /* Normal states */ - if (IDLE == ep0_state) - musb_peri_ep0_idle(); - - if (TX == ep0_state) - musb_peri_ep0_tx(); - - if (RX == ep0_state) - musb_peri_ep0_rx(); -} - -static void musb_peri_rx_ep(unsigned int ep) -{ - u16 peri_rxcount; - u8 peri_rxcsr = readw(&musbr->ep[ep].epN.rxcsr); - - if (!(peri_rxcsr & MUSB_RXCSR_RXPKTRDY)) { - if (debug_level > 0) - serial_printf("ERROR : %s %d without MUSB_RXCSR_RXPKTRDY set\n", - __PRETTY_FUNCTION__, ep); - return; - } - - peri_rxcount = readw(&musbr->ep[ep].epN.rxcount); - if (peri_rxcount) { - struct usb_endpoint_instance *endpoint; - u32 length; - u8 *data; - - endpoint = GET_ENDPOINT(udc_device, ep); - if (endpoint && endpoint->rcv_urb) { - struct urb *urb = endpoint->rcv_urb; - unsigned int remaining_space = urb->buffer_length - - urb->actual_length; - - if (remaining_space) { - int urb_bad = 0; /* urb is good */ - - if (peri_rxcount > remaining_space) - length = remaining_space; - else - length = peri_rxcount; - - data = (u8 *) urb->buffer_data; - data += urb->actual_length; - - /* The common musb fifo reader */ - read_fifo(ep, length, data); - - musb_peri_rx_ack(ep); - - /* - * urb's actual_length is updated in - * usbd_rcv_complete - */ - usbd_rcv_complete(endpoint, length, urb_bad); - - } else { - if (debug_level > 0) - serial_printf("ERROR : %s %d no space " - "in rcv buffer\n", - __PRETTY_FUNCTION__, ep); - } - } else { - if (debug_level > 0) - serial_printf("ERROR : %s %d problem with " - "endpoint\n", - __PRETTY_FUNCTION__, ep); - } - - } else { - if (debug_level > 0) - serial_printf("ERROR : %s %d with nothing to do\n", - __PRETTY_FUNCTION__, ep); - } -} - -static void musb_peri_rx(u16 intr) -{ - unsigned int ep; - - /* Check for EP0 */ - if (0x01 & intr) - musb_peri_ep0(); - - for (ep = 1; ep < 16; ep++) { - if ((1 << ep) & intr) - musb_peri_rx_ep(ep); - } -} - -static void musb_peri_tx(u16 intr) -{ - /* Check for EP0 */ - if (0x01 & intr) - musb_peri_ep0_tx(); - - /* - * Use this in the future when handling epN tx - * - * u8 ep; - * - * for (ep = 1; ep < 16; ep++) { - * if ((1 << ep) & intr) { - * / * handle tx for this endpoint * / - * } - * } - */ -} - -void udc_irq(void) -{ - /* This is a high freq called function */ - if (enabled) { - u8 intrusb; - - intrusb = readb(&musbr->intrusb); - - /* - * See drivers/usb/gadget/mpc8xx_udc.c for - * state diagram going from detached through - * configuration. - */ - if (MUSB_INTR_RESUME & intrusb) { - usbd_device_event_irq(udc_device, - DEVICE_BUS_ACTIVITY, 0); - musb_peri_resume(); - } - - musb_peri_ep0(); - - if (MUSB_INTR_RESET & intrusb) { - usbd_device_event_irq(udc_device, DEVICE_RESET, 0); - musb_peri_reset(); - } - - if (MUSB_INTR_DISCONNECT & intrusb) { - /* cable unplugged from hub/host */ - usbd_device_event_irq(udc_device, DEVICE_RESET, 0); - musb_peri_reset(); - usbd_device_event_irq(udc_device, DEVICE_HUB_RESET, 0); - } - - if (MUSB_INTR_SOF & intrusb) { - usbd_device_event_irq(udc_device, - DEVICE_BUS_ACTIVITY, 0); - musb_peri_resume(); - } - - if (MUSB_INTR_SUSPEND & intrusb) { - usbd_device_event_irq(udc_device, - DEVICE_BUS_INACTIVE, 0); - } - - if (ep0_state != SET_ADDRESS) { - u16 intrrx, intrtx; - - intrrx = readw(&musbr->intrrx); - intrtx = readw(&musbr->intrtx); - - if (intrrx) - musb_peri_rx(intrrx); - - if (intrtx) - musb_peri_tx(intrtx); - } else { - if (MUSB_INTR_SOF & intrusb) { - u8 faddr; - faddr = readb(&musbr->faddr); - /* - * Setting of the address can fail. - * Normally it succeeds the second time. - */ - if (udc_device->address != faddr) - musb_peri_ep0_set_address(); - } - } - } -} - -void udc_set_nak(int ep_num) -{ - /* noop */ -} - -void udc_unset_nak(int ep_num) -{ - /* noop */ -} - -int udc_endpoint_write(struct usb_endpoint_instance *endpoint) -{ - int ret = 0; - - /* Transmit only if the hardware is available */ - if (endpoint->tx_urb && endpoint->state == 0) { - unsigned int ep = endpoint->endpoint_address & - USB_ENDPOINT_NUMBER_MASK; - - u16 peri_txcsr = readw(&musbr->ep[ep].epN.txcsr); - - /* Error conditions */ - if (peri_txcsr & MUSB_TXCSR_P_UNDERRUN) { - peri_txcsr &= ~MUSB_TXCSR_P_UNDERRUN; - writew(peri_txcsr, &musbr->ep[ep].epN.txcsr); - } - - if (debug_level > 1) - musb_print_txcsr(peri_txcsr); - - /* Check if a packet is waiting to be sent */ - if (!(peri_txcsr & MUSB_TXCSR_TXPKTRDY)) { - u32 length; - u8 *data; - struct urb *urb = endpoint->tx_urb; - unsigned int remaining_packet = urb->actual_length - - endpoint->sent; - - if (endpoint->tx_packetSize < remaining_packet) - length = endpoint->tx_packetSize; - else - length = remaining_packet; - - data = (u8 *) urb->buffer; - data += endpoint->sent; - - /* common musb fifo function */ - write_fifo(ep, length, data); - - musb_peri_tx_ready(ep); - - endpoint->last = length; - /* usbd_tx_complete will take care of updating 'sent' */ - usbd_tx_complete(endpoint); - } - } else { - if (debug_level > 0) - serial_printf("ERROR : %s Problem with urb %p " - "or ep state %d\n", - __PRETTY_FUNCTION__, - endpoint->tx_urb, endpoint->state); - } - - return ret; -} - -void udc_setup_ep(struct usb_device_instance *device, unsigned int id, - struct usb_endpoint_instance *endpoint) -{ - if (0 == id) { - /* EP0 */ - ep0_endpoint = endpoint; - ep0_endpoint->endpoint_address = 0xff; - ep0_urb = usbd_alloc_urb(device, endpoint); - } else if (MAX_ENDPOINT >= id) { - int ep_addr; - - /* Check the direction */ - ep_addr = endpoint->endpoint_address; - if (USB_DIR_IN == (ep_addr & USB_ENDPOINT_DIR_MASK)) { - /* IN */ - epinfo[(id * 2) + 1].epsize = endpoint->tx_packetSize; - } else { - /* OUT */ - epinfo[id * 2].epsize = endpoint->rcv_packetSize; - } - - musb_configure_ep(&epinfo[0], ARRAY_SIZE(epinfo)); - } else { - if (debug_level > 0) - serial_printf("ERROR : %s endpoint request %d " - "exceeds maximum %d\n", - __PRETTY_FUNCTION__, id, MAX_ENDPOINT); - } -} - -void udc_connect(void) -{ - /* noop */ -} - -void udc_disconnect(void) -{ - /* noop */ -} - -void udc_enable(struct usb_device_instance *device) -{ - /* Save the device structure pointer */ - udc_device = device; - - enabled = 1; -} - -void udc_disable(void) -{ - enabled = 0; -} - -void udc_startup_events(struct usb_device_instance *device) -{ - /* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */ - usbd_device_event_irq(device, DEVICE_INIT, 0); - - /* - * The DEVICE_CREATE event puts the USB device in the state - * STATE_ATTACHED. - */ - usbd_device_event_irq(device, DEVICE_CREATE, 0); - - /* Resets the address to 0 */ - usbd_device_event_irq(device, DEVICE_RESET, 0); - - udc_enable(device); -} - -int udc_init(void) -{ - int ret; - int ep_loop; - - ret = musb_platform_init(); - if (ret < 0) - goto end; - - /* Configure all the endpoint FIFO's and start usb controller */ - musbr = musb_cfg.regs; - - /* Initialize the endpoints */ - for (ep_loop = 0; ep_loop < MAX_ENDPOINT * 2; ep_loop++) { - epinfo[ep_loop].epnum = (ep_loop / 2) + 1; - epinfo[ep_loop].epdir = ep_loop % 2; /* OUT, IN */ - epinfo[ep_loop].epsize = 0; - } - - musb_peri_softconnect(); - - ret = 0; -end: - - return ret; -} diff --git a/qemu/roms/u-boot/drivers/usb/musb/omap3.c b/qemu/roms/u-boot/drivers/usb/musb/omap3.c deleted file mode 100644 index 97da529b4..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/omap3.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2009 Wind River Systems, Inc. - * Tom Rix <Tom.Rix@windriver.com> - * - * This is file is based on - * repository git.gitorious.org/u-boot-omap3/mainline.git, - * branch omap3-dev-usb, file drivers/usb/host/omap3530_usb.c - * - * This is the unique part of its copyright : - * - * ------------------------------------------------------------------------ - * - * Copyright (c) 2009 Texas Instruments - * - * ------------------------------------------------------------------------ - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <asm/omap_common.h> -#include <twl4030.h> -#include <twl6030.h> -#include "omap3.h" - -static int platform_needs_initialization = 1; - -struct musb_config musb_cfg = { - .regs = (struct musb_regs *)MENTOR_USB0_BASE, - .timeout = OMAP3_USB_TIMEOUT, - .musb_speed = 0, -}; - -/* - * OMAP3 USB OTG registers. - */ -struct omap3_otg_regs { - u32 revision; - u32 sysconfig; - u32 sysstatus; - u32 interfsel; - u32 simenable; - u32 forcestdby; -}; - -static struct omap3_otg_regs *otg; - -#define OMAP3_OTG_SYSCONFIG_SMART_STANDBY_MODE 0x2000 -#define OMAP3_OTG_SYSCONFIG_NO_STANDBY_MODE 0x1000 -#define OMAP3_OTG_SYSCONFIG_SMART_IDLE_MODE 0x0010 -#define OMAP3_OTG_SYSCONFIG_NO_IDLE_MODE 0x0008 -#define OMAP3_OTG_SYSCONFIG_ENABLEWAKEUP 0x0004 -#define OMAP3_OTG_SYSCONFIG_SOFTRESET 0x0002 -#define OMAP3_OTG_SYSCONFIG_AUTOIDLE 0x0001 - -#define OMAP3_OTG_SYSSTATUS_RESETDONE 0x0001 - -/* OMAP4430 has an internal PHY, use it */ -#ifdef CONFIG_OMAP4430 -#define OMAP3_OTG_INTERFSEL_OMAP 0x0000 -#else -#define OMAP3_OTG_INTERFSEL_OMAP 0x0001 -#endif - -#define OMAP3_OTG_FORCESTDBY_STANDBY 0x0001 - - -#ifdef DEBUG_MUSB_OMAP3 -static void musb_db_otg_regs(void) -{ - u32 l; - l = readl(&otg->revision); - serial_printf("OTG_REVISION 0x%x\n", l); - l = readl(&otg->sysconfig); - serial_printf("OTG_SYSCONFIG 0x%x\n", l); - l = readl(&otg->sysstatus); - serial_printf("OTG_SYSSTATUS 0x%x\n", l); - l = readl(&otg->interfsel); - serial_printf("OTG_INTERFSEL 0x%x\n", l); - l = readl(&otg->forcestdby); - serial_printf("OTG_FORCESTDBY 0x%x\n", l); -} -#endif - -int musb_platform_init(void) -{ - int ret = -1; - - if (platform_needs_initialization) { - u32 stdby; - - /* - * OMAP3EVM uses ISP1504 phy and so - * twl4030 related init is not required. - */ -#ifdef CONFIG_TWL4030_USB - if (twl4030_usb_ulpi_init()) { - serial_printf("ERROR: %s Could not initialize PHY\n", - __PRETTY_FUNCTION__); - goto end; - } -#endif - -#ifdef CONFIG_TWL6030_POWER - twl6030_usb_device_settings(); -#endif - - otg = (struct omap3_otg_regs *)OMAP3_OTG_BASE; - - /* Set OTG to always be on */ - writel(OMAP3_OTG_SYSCONFIG_NO_STANDBY_MODE | - OMAP3_OTG_SYSCONFIG_NO_IDLE_MODE, &otg->sysconfig); - - /* Set the interface */ - writel(OMAP3_OTG_INTERFSEL_OMAP, &otg->interfsel); - - /* Clear force standby */ - stdby = readl(&otg->forcestdby); - stdby &= ~OMAP3_OTG_FORCESTDBY_STANDBY; - writel(stdby, &otg->forcestdby); - -#ifdef CONFIG_OMAP3_EVM - musb_cfg.extvbus = omap3_evm_need_extvbus(); -#endif - -#ifdef CONFIG_OMAP4430 - u32 *usbotghs_control = - (u32 *)((*ctrl)->control_usbotghs_ctrl); - *usbotghs_control = 0x15; -#endif - platform_needs_initialization = 0; - } - - ret = platform_needs_initialization; - -#ifdef CONFIG_TWL4030_USB -end: -#endif - return ret; - -} - -void musb_platform_deinit(void) -{ - /* noop */ -} diff --git a/qemu/roms/u-boot/drivers/usb/musb/omap3.h b/qemu/roms/u-boot/drivers/usb/musb/omap3.h deleted file mode 100644 index ae645c72d..000000000 --- a/qemu/roms/u-boot/drivers/usb/musb/omap3.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2009 Wind River Systems, Inc. - * Tom Rix <Tom.Rix@windriver.com> - * - * This file is based on the file drivers/usb/musb/davinci.h - * - * This is the unique part of its copyright: - * - * -------------------------------------------------------------------- - * - * Copyright (c) 2008 Texas Instruments - * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments - * - * -------------------------------------------------------------------- - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#ifndef _MUSB_OMAP3_H_ -#define _MUSB_OMAP3_H_ - -#include <asm/arch/cpu.h> -#include "musb_core.h" - -/* Base address of MUSB registers */ -#define MENTOR_USB0_BASE MUSB_BASE - -/* Base address of OTG registers */ -#define OMAP3_OTG_BASE (MENTOR_USB0_BASE + 0x400) - -/* Timeout for USB module */ -#define OMAP3_USB_TIMEOUT 0x3FFFFFF - -int musb_platform_init(void); - -#ifdef CONFIG_OMAP3_EVM -extern u8 omap3_evm_need_extvbus(void); -#endif - -#endif /* _MUSB_OMAP3_H */ diff --git a/qemu/roms/u-boot/drivers/usb/phy/Makefile b/qemu/roms/u-boot/drivers/usb/phy/Makefile deleted file mode 100644 index 93d147e26..000000000 --- a/qemu/roms/u-boot/drivers/usb/phy/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Copyright (c) 2009 Wind River Systems, Inc. -# Tom Rix <Tom.Rix@windriver.com> -# -# SPDX-License-Identifier: GPL-2.0+ -# - -obj-$(CONFIG_TWL4030_USB) += twl4030.o -obj-$(CONFIG_OMAP_USB_PHY) += omap_usb_phy.o diff --git a/qemu/roms/u-boot/drivers/usb/phy/omap_usb_phy.c b/qemu/roms/u-boot/drivers/usb/phy/omap_usb_phy.c deleted file mode 100644 index af46db2ed..000000000 --- a/qemu/roms/u-boot/drivers/usb/phy/omap_usb_phy.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * OMAP USB PHY Support - * - * (C) Copyright 2013 - * Texas Instruments, <www.ti.com> - * - * Author: Dan Murphy <dmurphy@ti.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> -#include <asm-generic/errno.h> -#include <asm/omap_common.h> -#include <asm/arch/cpu.h> -#include <asm/arch/sys_proto.h> - -#include <linux/compat.h> -#include <linux/usb/dwc3.h> -#include <linux/usb/xhci-omap.h> - -#include "../host/xhci.h" - -#ifdef CONFIG_OMAP_USB3PHY1_HOST -struct usb_dpll_params { - u16 m; - u8 n; - u8 freq:3; - u8 sd; - u32 mf; -}; - -#define NUM_USB_CLKS 6 - -static struct usb_dpll_params omap_usb3_dpll_params[NUM_USB_CLKS] = { - {1250, 5, 4, 20, 0}, /* 12 MHz */ - {3125, 20, 4, 20, 0}, /* 16.8 MHz */ - {1172, 8, 4, 20, 65537}, /* 19.2 MHz */ - {1250, 12, 4, 20, 0}, /* 26 MHz */ - {3125, 47, 4, 20, 92843}, /* 38.4 MHz */ - {1000, 7, 4, 10, 0}, /* 20 MHz */ -}; - -static void omap_usb_dpll_relock(struct omap_usb3_phy *phy_regs) -{ - u32 val; - - writel(SET_PLL_GO, &phy_regs->pll_go); - do { - val = readl(&phy_regs->pll_status); - if (val & PLL_LOCK) - break; - } while (1); -} - -static void omap_usb_dpll_lock(struct omap_usb3_phy *phy_regs) -{ - u32 clk_index = get_sys_clk_index(); - u32 val; - - val = readl(&phy_regs->pll_config_1); - val &= ~PLL_REGN_MASK; - val |= omap_usb3_dpll_params[clk_index].n << PLL_REGN_SHIFT; - writel(val, &phy_regs->pll_config_1); - - val = readl(&phy_regs->pll_config_2); - val &= ~PLL_SELFREQDCO_MASK; - val |= omap_usb3_dpll_params[clk_index].freq << PLL_SELFREQDCO_SHIFT; - writel(val, &phy_regs->pll_config_2); - - val = readl(&phy_regs->pll_config_1); - val &= ~PLL_REGM_MASK; - val |= omap_usb3_dpll_params[clk_index].m << PLL_REGM_SHIFT; - writel(val, &phy_regs->pll_config_1); - - val = readl(&phy_regs->pll_config_4); - val &= ~PLL_REGM_F_MASK; - val |= omap_usb3_dpll_params[clk_index].mf << PLL_REGM_F_SHIFT; - writel(val, &phy_regs->pll_config_4); - - val = readl(&phy_regs->pll_config_3); - val &= ~PLL_SD_MASK; - val |= omap_usb3_dpll_params[clk_index].sd << PLL_SD_SHIFT; - writel(val, &phy_regs->pll_config_3); - - omap_usb_dpll_relock(phy_regs); -} - -static void usb3_phy_partial_powerup(struct omap_usb3_phy *phy_regs) -{ - u32 rate = get_sys_clk_freq()/1000000; - u32 val; - - val = readl((*ctrl)->control_phy_power_usb); - val &= ~(USB3_PWRCTL_CLK_CMD_MASK | USB3_PWRCTL_CLK_FREQ_MASK); - val |= (USB3_PHY_PARTIAL_RX_POWERON | USB3_PHY_TX_RX_POWERON); - val |= rate << USB3_PWRCTL_CLK_FREQ_SHIFT; - - writel(val, (*ctrl)->control_phy_power_usb); -} - -void usb_phy_power(int on) -{ - u32 val; - - val = readl((*ctrl)->control_phy_power_usb); - if (on) { - val &= ~USB3_PWRCTL_CLK_CMD_MASK; - val |= USB3_PHY_TX_RX_POWERON; - } else { - val &= (~USB3_PWRCTL_CLK_CMD_MASK & ~USB3_PHY_TX_RX_POWERON); - } - - writel(val, (*ctrl)->control_phy_power_usb); -} - -void omap_usb3_phy_init(struct omap_usb3_phy *phy_regs) -{ - omap_usb_dpll_lock(phy_regs); - - usb3_phy_partial_powerup(phy_regs); - /* - * Give enough time for the PHY to partially power-up before - * powering it up completely. delay value suggested by the HW - * team. - */ - mdelay(100); - usb3_phy_power(1); -} - -static void omap_enable_usb3_phy(struct omap_xhci *omap) -{ - u32 val; - - /* Setting OCP2SCP1 register */ - setbits_le32((*prcm)->cm_l3init_ocp2scp1_clkctrl, - OCP2SCP1_CLKCTRL_MODULEMODE_HW); - - /* Turn on 32K AON clk */ - setbits_le32((*prcm)->cm_coreaon_usb_phy_core_clkctrl, - USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K); - - /* Setting CM_L3INIT_CLKSTCTRL to 0x0 i.e NO sleep */ - writel(0x0, (*prcm)->cm_l3init_clkstctrl); - - val = (USBOTGSS_DMADISABLE | - USBOTGSS_STANDBYMODE_SMRT_WKUP | - USBOTGSS_IDLEMODE_NOIDLE); - writel(val, &omap->otg_wrapper->sysconfig); - - /* Clear the utmi OTG status */ - val = readl(&omap->otg_wrapper->utmi_otg_status); - writel(val, &omap->otg_wrapper->utmi_otg_status); - - /* Enable interrupts */ - writel(USBOTGSS_COREIRQ_EN, &omap->otg_wrapper->irqenable_set_0); - val = (USBOTGSS_IRQ_SET_1_IDPULLUP_FALL_EN | - USBOTGSS_IRQ_SET_1_DISCHRGVBUS_FALL_EN | - USBOTGSS_IRQ_SET_1_CHRGVBUS_FALL_EN | - USBOTGSS_IRQ_SET_1_DRVVBUS_FALL_EN | - USBOTGSS_IRQ_SET_1_IDPULLUP_RISE_EN | - USBOTGSS_IRQ_SET_1_DISCHRGVBUS_RISE_EN | - USBOTGSS_IRQ_SET_1_CHRGVBUS_RISE_EN | - USBOTGSS_IRQ_SET_1_DRVVBUS_RISE_EN | - USBOTGSS_IRQ_SET_1_OEVT_EN); - writel(val, &omap->otg_wrapper->irqenable_set_1); - - /* Clear the IRQ status */ - val = readl(&omap->otg_wrapper->irqstatus_1); - writel(val, &omap->otg_wrapper->irqstatus_1); - val = readl(&omap->otg_wrapper->irqstatus_0); - writel(val, &omap->otg_wrapper->irqstatus_0); - - /* Enable the USB OTG Super speed clocks */ - val = (OPTFCLKEN_REFCLK960M | OTG_SS_CLKCTRL_MODULEMODE_HW); - setbits_le32((*prcm)->cm_l3init_usb_otg_ss_clkctrl, val); - -}; -#endif /* CONFIG_OMAP_USB3PHY1_HOST */ - -#ifdef CONFIG_OMAP_USB2PHY2_HOST -static void omap_enable_usb2_phy2(struct omap_xhci *omap) -{ - u32 reg, val; - - val = (~USB2PHY_AUTORESUME_EN & USB2PHY_DISCHGDET); - writel(val, (*ctrl)->control_srcomp_north_side); - - setbits_le32((*prcm)->cm_coreaon_usb_phy2_core_clkctrl, - USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K); - - setbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, - (USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K | - OTG_SS_CLKCTRL_MODULEMODE_HW)); - - /* This is an undocumented Reserved register */ - reg = 0x4a0086c0; - val = readl(reg); - val |= 0x100; - setbits_le32(reg, val); -} - -void usb_phy_power(int on) -{ - return; -} -#endif /* CONFIG_OMAP_USB2PHY2_HOST */ - -#ifdef CONFIG_AM437X_USB2PHY2_HOST -static void am437x_enable_usb2_phy2(struct omap_xhci *omap) -{ - const u32 usb_otg_ss_clk_val = (USBOTGSSX_CLKCTRL_MODULE_EN | - USBOTGSSX_CLKCTRL_OPTFCLKEN_REFCLK960); - - writel(usb_otg_ss_clk_val, PRM_PER_USB_OTG_SS0_CLKCTRL); - writel(usb_otg_ss_clk_val, PRM_PER_USB_OTG_SS1_CLKCTRL); - - writel(USBPHYOCPSCP_MODULE_EN, PRM_PER_USBPHYOCP2SCP0_CLKCTRL); - writel(USBPHYOCPSCP_MODULE_EN, PRM_PER_USBPHYOCP2SCP1_CLKCTRL); -} - -void usb_phy_power(int on) -{ - return; -} -#endif /* CONFIG_AM437X_USB2PHY2_HOST */ - -void omap_reset_usb_phy(struct dwc3 *dwc3_reg) -{ - /* Assert USB3 PHY reset */ - setbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); - - /* Assert USB2 PHY reset */ - setbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); - - mdelay(100); - - /* Clear USB3 PHY reset */ - clrbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); - - /* Clear USB2 PHY reset */ - clrbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); - -} - -void omap_enable_phy(struct omap_xhci *omap) -{ -#ifdef CONFIG_OMAP_USB2PHY2_HOST - omap_enable_usb2_phy2(omap); -#endif - -#ifdef CONFIG_AM437X_USB2PHY2_HOST - am437x_enable_usb2_phy2(omap); -#endif - -#ifdef CONFIG_OMAP_USB3PHY1_HOST - omap_enable_usb3_phy(omap); - omap_usb3_phy_init(omap->usb3_phy); -#endif -} diff --git a/qemu/roms/u-boot/drivers/usb/phy/twl4030.c b/qemu/roms/u-boot/drivers/usb/phy/twl4030.c deleted file mode 100644 index 6dcb336bb..000000000 --- a/qemu/roms/u-boot/drivers/usb/phy/twl4030.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2009 Wind River Systems, Inc. - * Tom Rix <Tom.Rix@windriver.com> - * - * This is file is based on - * repository git.gitorious.org/u-boot-omap3/mainline.git, - * branch omap3-dev-usb, file drivers/usb/gadget/twl4030_usb.c - * - * This is the unique part of its copyright : - * - * ------------------------------------------------------------------------ - * - * * (C) Copyright 2009 Atin Malaviya (atin.malaviya@gmail.com) - * - * Based on: twl4030_usb.c in linux 2.6 (drivers/i2c/chips/twl4030_usb.c) - * Copyright (C) 2004-2007 Texas Instruments - * Copyright (C) 2008 Nokia Corporation - * Contact: Felipe Balbi <felipe.balbi@nokia.com> - * - * Author: Atin Malaviya (atin.malaviya@gmail.com) - * - * ------------------------------------------------------------------------ - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <twl4030.h> - -/* Defines for bits in registers */ -#define OPMODE_MASK (3 << 3) -#define XCVRSELECT_MASK (3 << 0) -#define CARKITMODE (1 << 2) -#define OTG_ENAB (1 << 5) -#define PHYPWD (1 << 0) -#define CLOCKGATING_EN (1 << 2) -#define CLK32K_EN (1 << 1) -#define REQ_PHY_DPLL_CLK (1 << 0) -#define PHY_DPLL_CLK (1 << 0) - -static int twl4030_usb_write(u8 address, u8 data) -{ - int ret; - - ret = twl4030_i2c_write_u8(TWL4030_CHIP_USB, address, data); - if (ret != 0) - printf("TWL4030:USB:Write[0x%x] Error %d\n", address, ret); - - return ret; -} - -static int twl4030_usb_read(u8 address) -{ - u8 data; - int ret; - - ret = twl4030_i2c_read_u8(TWL4030_CHIP_USB, address, &data); - if (ret == 0) - ret = data; - else - printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret); - - return ret; -} - -static void twl4030_usb_ldo_init(void) -{ - /* Enable writing to power configuration registers */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, - TWL4030_PM_MASTER_PROTECT_KEY, 0xC0); - twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, - TWL4030_PM_MASTER_PROTECT_KEY, 0x0C); - - /* put VUSB3V1 LDO in active state */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, - TWL4030_PM_RECEIVER_VUSB_DEDICATED2, 0x00); - - /* input to VUSB3V1 LDO is from VBAT, not VBUS */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, - TWL4030_PM_RECEIVER_VUSB_DEDICATED1, 0x14); - - /* turn on 3.1V regulator */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, - TWL4030_PM_RECEIVER_VUSB3V1_DEV_GRP, 0x20); - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, - TWL4030_PM_RECEIVER_VUSB3V1_TYPE, 0x00); - - /* turn on 1.5V regulator */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, - TWL4030_PM_RECEIVER_VUSB1V5_DEV_GRP, 0x20); - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, - TWL4030_PM_RECEIVER_VUSB1V5_TYPE, 0x00); - - /* turn on 1.8V regulator */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, - TWL4030_PM_RECEIVER_VUSB1V8_DEV_GRP, 0x20); - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, - TWL4030_PM_RECEIVER_VUSB1V8_TYPE, 0x00); - - /* disable access to power configuration registers */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, - TWL4030_PM_MASTER_PROTECT_KEY, 0x00); -} - -static void twl4030_phy_power(void) -{ - u8 pwr, clk; - - /* Power the PHY */ - pwr = twl4030_usb_read(TWL4030_USB_PHY_PWR_CTRL); - pwr &= ~PHYPWD; - twl4030_usb_write(TWL4030_USB_PHY_PWR_CTRL, pwr); - /* Enable clocks */ - clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL); - clk |= CLOCKGATING_EN | CLK32K_EN; - twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk); -} - -/* - * Initiaze the ULPI interface - * ULPI : Universal Transceiver Macrocell Low Pin Interface - * An interface between the USB link controller like musb and the - * the PHY or transceiver that drives the actual bus. - */ -int twl4030_usb_ulpi_init(void) -{ - long timeout = 1000 * 1000; /* 1 sec */; - u8 clk, sts, pwr; - - /* twl4030 ldo init */ - twl4030_usb_ldo_init(); - - /* Enable the twl4030 phy */ - twl4030_phy_power(); - - /* Enable DPLL to access PHY registers over I2C */ - clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL); - clk |= REQ_PHY_DPLL_CLK; - twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk); - - /* Check if the PHY DPLL is locked */ - sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS); - while (!(sts & PHY_DPLL_CLK) && 0 < timeout) { - udelay(10); - sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS); - timeout -= 10; - } - - /* Final check */ - sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS); - if (!(sts & PHY_DPLL_CLK)) { - printf("Error:TWL4030:USB Timeout setting PHY DPLL clock\n"); - return -1; - } - - /* - * There are two circuit blocks attached to the PHY, - * Carkit and USB OTG. Disable Carkit and enable USB OTG - */ - twl4030_usb_write(TWL4030_USB_IFC_CTRL_CLR, CARKITMODE); - pwr = twl4030_usb_read(TWL4030_USB_POWER_CTRL); - pwr |= OTG_ENAB; - twl4030_usb_write(TWL4030_USB_POWER_CTRL_SET, pwr); - - /* Clear the opmode bits to ensure normal encode */ - twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, OPMODE_MASK); - - /* Clear the xcvrselect bits to enable the high speed transeiver */ - twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, XCVRSELECT_MASK); - - /* Let ULPI control the DPLL clock */ - clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL); - clk &= ~REQ_PHY_DPLL_CLK; - twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/ulpi/Makefile b/qemu/roms/u-boot/drivers/usb/ulpi/Makefile deleted file mode 100644 index a21fe2c93..000000000 --- a/qemu/roms/u-boot/drivers/usb/ulpi/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Copyright (C) 2011 Jana Rapava <fermata7@gmail.com> -# -# SPDX-License-Identifier: GPL-2.0+ -# - -obj-$(CONFIG_USB_ULPI) += ulpi.o -obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi-viewport.o -obj-$(CONFIG_USB_ULPI_VIEWPORT_OMAP) += omap-ulpi-viewport.o diff --git a/qemu/roms/u-boot/drivers/usb/ulpi/omap-ulpi-viewport.c b/qemu/roms/u-boot/drivers/usb/ulpi/omap-ulpi-viewport.c deleted file mode 100644 index 4db7fa43c..000000000 --- a/qemu/roms/u-boot/drivers/usb/ulpi/omap-ulpi-viewport.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * OMAP ulpi viewport support - * Based on drivers/usb/ulpi/ulpi-viewport.c - * - * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com - * Author: Govindraj R <govindraj.raja@ti.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 of - * the License as published by the Free Software Foundation. - * - * 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, see <http://www.gnu.org/licenses/>. - */ - -#include <common.h> -#include <asm/io.h> -#include <usb/ulpi.h> - -#define OMAP_ULPI_WR_OPSEL (2 << 22) -#define OMAP_ULPI_RD_OPSEL (3 << 22) -#define OMAP_ULPI_START (1 << 31) - -/* - * Wait for having ulpi in done state - */ -static int ulpi_wait(struct ulpi_viewport *ulpi_vp, u32 mask) -{ - int timeout = CONFIG_USB_ULPI_TIMEOUT; - - while (--timeout) { - if (!(readl(ulpi_vp->viewport_addr) & mask)) - return 0; - - udelay(1); - } - - return ULPI_ERROR; -} - -/* - * Issue a ULPI read/write request - */ -static int ulpi_request(struct ulpi_viewport *ulpi_vp, u32 value) -{ - int err; - - writel(value, ulpi_vp->viewport_addr); - - err = ulpi_wait(ulpi_vp, OMAP_ULPI_START); - if (err) - debug("ULPI request timed out\n"); - - return err; -} - -int ulpi_write(struct ulpi_viewport *ulpi_vp, u8 *reg, u32 value) -{ - u32 val = OMAP_ULPI_START | (((ulpi_vp->port_num + 1) & 0xf) << 24) | - OMAP_ULPI_WR_OPSEL | ((u32)reg << 16) | (value & 0xff); - - return ulpi_request(ulpi_vp, val); -} - -u32 ulpi_read(struct ulpi_viewport *ulpi_vp, u8 *reg) -{ - int err; - u32 val = OMAP_ULPI_START | (((ulpi_vp->port_num + 1) & 0xf) << 24) | - OMAP_ULPI_RD_OPSEL | ((u32)reg << 16); - - err = ulpi_request(ulpi_vp, val); - if (err) - return err; - - return readl(ulpi_vp->viewport_addr) & 0xff; -} diff --git a/qemu/roms/u-boot/drivers/usb/ulpi/ulpi-viewport.c b/qemu/roms/u-boot/drivers/usb/ulpi/ulpi-viewport.c deleted file mode 100644 index b4974ed2a..000000000 --- a/qemu/roms/u-boot/drivers/usb/ulpi/ulpi-viewport.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2011 Jana Rapava <fermata7@gmail.com> - * Copyright (C) 2011 CompuLab, Ltd. <www.compulab.co.il> - * - * Authors: Jana Rapava <fermata7@gmail.com> - * Igor Grinberg <grinberg@compulab.co.il> - * - * Based on: - * linux/drivers/usb/otg/ulpi_viewport.c - * - * Original Copyright follow: - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * - */ - -#include <common.h> -#include <asm/io.h> -#include <usb/ulpi.h> - -/* ULPI viewport control bits */ -#define ULPI_SS (1 << 27) -#define ULPI_RWCTRL (1 << 29) -#define ULPI_RWRUN (1 << 30) -#define ULPI_WU (1 << 31) - -/* - * Wait for the ULPI request to complete - * - * @ulpi_viewport - the address of the viewport - * @mask - expected value to wait for - * - * returns 0 on mask match, ULPI_ERROR on time out. - */ -static int ulpi_wait(struct ulpi_viewport *ulpi_vp, u32 mask) -{ - int timeout = CONFIG_USB_ULPI_TIMEOUT; - - /* Wait for the bits in mask to become zero. */ - while (--timeout) { - if ((readl(ulpi_vp->viewport_addr) & mask) == 0) - return 0; - - udelay(1); - } - - return ULPI_ERROR; -} - -/* - * Wake the ULPI PHY up for communication - * - * returns 0 on success. - */ -static int ulpi_wakeup(struct ulpi_viewport *ulpi_vp) -{ - int err; - - if (readl(ulpi_vp->viewport_addr) & ULPI_SS) - return 0; /* already awake */ - - writel(ULPI_WU, ulpi_vp->viewport_addr); - - err = ulpi_wait(ulpi_vp, ULPI_WU); - if (err) - printf("ULPI wakeup timed out\n"); - - return err; -} - -/* - * Issue a ULPI read/write request - * - * @value - the ULPI request - */ -static int ulpi_request(struct ulpi_viewport *ulpi_vp, u32 value) -{ - int err; - - err = ulpi_wakeup(ulpi_vp); - if (err) - return err; - - writel(value, ulpi_vp->viewport_addr); - - err = ulpi_wait(ulpi_vp, ULPI_RWRUN); - if (err) - printf("ULPI request timed out\n"); - - return err; -} - -int ulpi_write(struct ulpi_viewport *ulpi_vp, u8 *reg, u32 value) -{ - u32 val = ULPI_RWRUN | ULPI_RWCTRL | ((u32)reg << 16) | (value & 0xff); - - val |= (ulpi_vp->port_num & 0x7) << 24; - return ulpi_request(ulpi_vp, val); -} - -u32 ulpi_read(struct ulpi_viewport *ulpi_vp, u8 *reg) -{ - int err; - u32 val = ULPI_RWRUN | ((u32)reg << 16); - - val |= (ulpi_vp->port_num & 0x7) << 24; - err = ulpi_request(ulpi_vp, val); - if (err) - return err; - - return (readl(ulpi_vp->viewport_addr) >> 8) & 0xff; -} diff --git a/qemu/roms/u-boot/drivers/usb/ulpi/ulpi.c b/qemu/roms/u-boot/drivers/usb/ulpi/ulpi.c deleted file mode 100644 index f3d18564b..000000000 --- a/qemu/roms/u-boot/drivers/usb/ulpi/ulpi.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2011 Jana Rapava <fermata7@gmail.com> - * Copyright (C) 2011 CompuLab, Ltd. <www.compulab.co.il> - * - * Authors: Jana Rapava <fermata7@gmail.com> - * Igor Grinberg <grinberg@compulab.co.il> - * - * Based on: - * linux/drivers/usb/otg/ulpi.c - * Generic ULPI USB transceiver support - * - * Original Copyright follow: - * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de> - * - * Based on sources from - * - * Sascha Hauer <s.hauer@pengutronix.de> - * Freescale Semiconductors - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <exports.h> -#include <usb/ulpi.h> - -#define ULPI_ID_REGS_COUNT 4 -#define ULPI_TEST_VALUE 0x55 /* 0x55 == 0b01010101 */ - -static struct ulpi_regs *ulpi = (struct ulpi_regs *)0; - -static int ulpi_integrity_check(struct ulpi_viewport *ulpi_vp) -{ - u32 val, tval = ULPI_TEST_VALUE; - int err, i; - - /* Use the 'special' test value to check all bits */ - for (i = 0; i < 2; i++, tval <<= 1) { - err = ulpi_write(ulpi_vp, &ulpi->scratch, tval); - if (err) - return err; - - val = ulpi_read(ulpi_vp, &ulpi->scratch); - if (val != tval) { - printf("ULPI integrity check failed\n"); - return val; - } - } - - return 0; -} - -int ulpi_init(struct ulpi_viewport *ulpi_vp) -{ - u32 val, id = 0; - u8 *reg = &ulpi->product_id_high; - int i; - - /* Assemble ID from four ULPI ID registers (8 bits each). */ - for (i = 0; i < ULPI_ID_REGS_COUNT; i++) { - val = ulpi_read(ulpi_vp, reg - i); - if (val == ULPI_ERROR) - return val; - - id = (id << 8) | val; - } - - /* Split ID into vendor and product ID. */ - debug("ULPI transceiver ID 0x%04x:0x%04x\n", id >> 16, id & 0xffff); - - return ulpi_integrity_check(ulpi_vp); -} - -int ulpi_select_transceiver(struct ulpi_viewport *ulpi_vp, unsigned speed) -{ - u32 tspeed = ULPI_FC_FULL_SPEED; - u32 val; - - switch (speed) { - case ULPI_FC_HIGH_SPEED: - case ULPI_FC_FULL_SPEED: - case ULPI_FC_LOW_SPEED: - case ULPI_FC_FS4LS: - tspeed = speed; - break; - default: - printf("ULPI: %s: wrong transceiver speed specified: %u, " - "falling back to full speed\n", __func__, speed); - } - - val = ulpi_read(ulpi_vp, &ulpi->function_ctrl); - if (val == ULPI_ERROR) - return val; - - /* clear the previous speed setting */ - val = (val & ~ULPI_FC_XCVRSEL_MASK) | tspeed; - - return ulpi_write(ulpi_vp, &ulpi->function_ctrl, val); -} - -int ulpi_set_vbus(struct ulpi_viewport *ulpi_vp, int on, int ext_power) -{ - u32 flags = ULPI_OTG_DRVVBUS; - u8 *reg = on ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear; - - if (ext_power) - flags |= ULPI_OTG_DRVVBUS_EXT; - - return ulpi_write(ulpi_vp, reg, flags); -} - -int ulpi_set_vbus_indicator(struct ulpi_viewport *ulpi_vp, int external, - int passthu, int complement) -{ - u32 flags, val; - u8 *reg; - - reg = external ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear; - val = ulpi_write(ulpi_vp, reg, ULPI_OTG_EXTVBUSIND); - if (val) - return val; - - flags = passthu ? ULPI_IFACE_PASSTHRU : 0; - flags |= complement ? ULPI_IFACE_EXTVBUS_COMPLEMENT : 0; - - val = ulpi_read(ulpi_vp, &ulpi->iface_ctrl); - if (val == ULPI_ERROR) - return val; - - val = val & ~(ULPI_IFACE_PASSTHRU & ULPI_IFACE_EXTVBUS_COMPLEMENT); - val |= flags; - val = ulpi_write(ulpi_vp, &ulpi->iface_ctrl, val); - if (val) - return val; - - return 0; -} - -int ulpi_set_pd(struct ulpi_viewport *ulpi_vp, int enable) -{ - u32 val = ULPI_OTG_DP_PULLDOWN | ULPI_OTG_DM_PULLDOWN; - u8 *reg = enable ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear; - - return ulpi_write(ulpi_vp, reg, val); -} - -int ulpi_opmode_sel(struct ulpi_viewport *ulpi_vp, unsigned opmode) -{ - u32 topmode = ULPI_FC_OPMODE_NORMAL; - u32 val; - - switch (opmode) { - case ULPI_FC_OPMODE_NORMAL: - case ULPI_FC_OPMODE_NONDRIVING: - case ULPI_FC_OPMODE_DISABLE_NRZI: - case ULPI_FC_OPMODE_NOSYNC_NOEOP: - topmode = opmode; - break; - default: - printf("ULPI: %s: wrong OpMode specified: %u, " - "falling back to OpMode Normal\n", __func__, opmode); - } - - val = ulpi_read(ulpi_vp, &ulpi->function_ctrl); - if (val == ULPI_ERROR) - return val; - - /* clear the previous opmode setting */ - val = (val & ~ULPI_FC_OPMODE_MASK) | topmode; - - return ulpi_write(ulpi_vp, &ulpi->function_ctrl, val); -} - -int ulpi_serial_mode_enable(struct ulpi_viewport *ulpi_vp, unsigned smode) -{ - switch (smode) { - case ULPI_IFACE_6_PIN_SERIAL_MODE: - case ULPI_IFACE_3_PIN_SERIAL_MODE: - break; - default: - printf("ULPI: %s: unrecognized Serial Mode specified: %u\n", - __func__, smode); - return ULPI_ERROR; - } - - return ulpi_write(ulpi_vp, &ulpi->iface_ctrl_set, smode); -} - -int ulpi_suspend(struct ulpi_viewport *ulpi_vp) -{ - int err; - - err = ulpi_write(ulpi_vp, &ulpi->function_ctrl_clear, - ULPI_FC_SUSPENDM); - if (err) - printf("ULPI: %s: failed writing the suspend bit\n", __func__); - - return err; -} - -/* - * Wait for ULPI PHY reset to complete. - * Actual wait for reset must be done in a view port specific way, - * because it involves checking the DIR line. - */ -static int __ulpi_reset_wait(struct ulpi_viewport *ulpi_vp) -{ - u32 val; - int timeout = CONFIG_USB_ULPI_TIMEOUT; - - /* Wait for the RESET bit to become zero */ - while (--timeout) { - /* - * This function is generic and suppose to work - * with any viewport, so we cheat here and don't check - * for the error of ulpi_read(), if there is one, then - * there will be a timeout. - */ - val = ulpi_read(ulpi_vp, &ulpi->function_ctrl); - if (!(val & ULPI_FC_RESET)) - return 0; - - udelay(1); - } - - printf("ULPI: %s: reset timed out\n", __func__); - - return ULPI_ERROR; -} -int ulpi_reset_wait(struct ulpi_viewport *ulpi_vp) - __attribute__((weak, alias("__ulpi_reset_wait"))); - -int ulpi_reset(struct ulpi_viewport *ulpi_vp) -{ - int err; - - err = ulpi_write(ulpi_vp, - &ulpi->function_ctrl_set, ULPI_FC_RESET); - if (err) { - printf("ULPI: %s: failed writing reset bit\n", __func__); - return err; - } - - return ulpi_reset_wait(ulpi_vp); -} |