diff options
author | H. Nikolaus Schaller <hns@goldelico.com> | 2012-03-26 20:55:28 +0200 |
---|---|---|
committer | H. Nikolaus Schaller <hns@goldelico.com> | 2012-03-26 20:55:28 +0200 |
commit | 92988a21ad4c4c9504295ccb580c9f806134471b (patch) | |
tree | 5effc9f14170112450de05c67dafbe8d5034d595 /drivers/usb | |
parent | ca2b506783b676c95762c54ea24dcfdaae1947c9 (diff) | |
download | bootable_bootloader_goldelico_gta04-92988a21ad4c4c9504295ccb580c9f806134471b.zip bootable_bootloader_goldelico_gta04-92988a21ad4c4c9504295ccb580c9f806134471b.tar.gz bootable_bootloader_goldelico_gta04-92988a21ad4c4c9504295ccb580c9f806134471b.tar.bz2 |
added boot script files to repository
Diffstat (limited to 'drivers/usb')
60 files changed, 0 insertions, 25490 deletions
diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile deleted file mode 100644 index 6a5f25a..0000000 --- a/drivers/usb/eth/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright (c) 2011 The Chromium OS Authors. -# See file CREDITS for list of people who contributed to this -# project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# - -include $(TOPDIR)/config.mk - -LIB := $(obj)libusb_eth.a - -# new USB host ethernet layer dependencies -COBJS-$(CONFIG_USB_HOST_ETHER) += usb_ether.o -ifdef CONFIG_USB_ETHER_ASIX -COBJS-y += asix.o -endif - -COBJS := $(COBJS-y) -SRCS := $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(COBJS)) - -all: $(LIB) - -$(LIB): $(obj).depend $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c deleted file mode 100644 index 9b012e4..0000000 --- a/drivers/usb/eth/asix.c +++ /dev/null @@ -1,635 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <usb.h> -#include <linux/mii.h> -#include "usb_ether.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_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_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 - -/* local vars */ -static int curr_eth_dev; /* index for name of next device detected */ - -/* - * 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) -{ - __le16 res; - - 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) -{ - __le16 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) -{ - 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%04x\n", *((__le16 *)buf)); - 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) -{ - __le16 v; - 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; -} - -/* - * 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; -} - -/* - * Asix callbacks - */ -static int asix_init(struct eth_device *eth, bd_t *bd) -{ - int embd_phy; - unsigned char buf[ETH_ALEN]; - u16 rx_ctl; - 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_gpio(dev, - AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5) < 0) - goto out_err; - - /* 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"); - goto out_err; - } - - if (asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL) < 0) - goto out_err; - - if (asix_sw_reset(dev, AX_SWRESET_CLEAR) < 0) - goto out_err; - - if (embd_phy) { - if (asix_sw_reset(dev, AX_SWRESET_IPRL) < 0) - goto out_err; - } else { - if (asix_sw_reset(dev, AX_SWRESET_PRTE) < 0) - goto out_err; - } - - 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) - goto out_err; - - rx_ctl = asix_read_rx_ctl(dev); - debug("RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); - - /* Get the MAC address */ - if (asix_read_cmd(dev, AX_CMD_READ_NODE_ID, - 0, 0, ETH_ALEN, buf) < 0) { - debug("Failed to read MAC address.\n"); - goto out_err; - } - memcpy(eth->enetaddr, buf, ETH_ALEN); - debug("MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - eth->enetaddr[0], eth->enetaddr[1], - eth->enetaddr[2], eth->enetaddr[3], - eth->enetaddr[4], eth->enetaddr[5]); - - dev->phy_id = asix_get_phy_addr(dev); - if (dev->phy_id < 0) - debug("Failed to read phy id\n"); - - if (asix_sw_reset(dev, AX_SWRESET_PRL) < 0) - goto out_err; - - if (asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL) < 0) - goto out_err; - - 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) - goto out_err; - - 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"); - goto out_err; - } - - 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, volatile void *packet, int length) -{ - struct ueth_data *dev = (struct ueth_data *)eth->priv; - int err; - u32 packet_len; - int actual_len; - 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); - if (length & 1) - 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; - static 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) ^ 0xffff) != (packet_len & 0xffff)) { - debug("Rx: malformed packet length: %#x (%#x:%#x)\n", - packet_len, (packet_len >> 16) ^ 0xffff, - packet_len & 0xffff); - return -1; - } - packet_len = packet_len & 0xffff; - 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; -}; - -static struct asix_dongle asix_dongles[] = { - { 0x05ac, 0x1402 }, /* Apple USB Ethernet Adapter */ - { 0x07d1, 0x3c05 }, /* D-Link DUB-E100 H/W Ver B1 */ - { 0x0b95, 0x772a }, /* Cables-to-Go USB Ethernet Adapter */ - { 0x0b95, 0x7720 }, /* Trendnet TU2-ET100 V3.0R */ - { 0x0b95, 0x1720 }, /* SMC */ - { 0x0db0, 0xa877 }, /* MSI - ASIX 88772a */ - { 0x13b1, 0x0018 }, /* Linksys 200M v2.1 */ - { 0x1557, 0x7720 }, /* 0Q0 cable ethernet */ - { 0x2001, 0x3c05 }, /* DLink DUB-E100 H/W Ver B1 Alternate */ - { 0x0000, 0x0000 } /* 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 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; - - /* - * 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; - return 1; -} - -int asix_eth_get_info(struct usb_device *dev, struct ueth_data *ss, - struct eth_device *eth) -{ - 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; - eth->priv = ss; - - return 1; -} diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c deleted file mode 100644 index 9e3d006..0000000 --- a/drivers/usb/eth/usb_ether.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#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 - { }, /* 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) -{ - 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 - */ - if (prob_dev[j].get_info(dev, - &usb_eth[usb_max_eth_dev], - &usb_eth[usb_max_eth_dev].eth_dev)) { - /* 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(&usb_eth[usb_max_eth_dev - 1].eth_dev); - 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 bus for ethernet devices... "); - - old_async = usb_disable_asynch(1); /* asynch transfer not allowed */ - - for (i = 0; i < USB_MAX_ETH_DEV; i++) - memset(&usb_eth[i], 0, sizeof(usb_eth[i])); - - 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 avaiable */ - - /* 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/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile deleted file mode 100644 index 7d5b504..0000000 --- a/drivers/usb/gadget/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -# -# (C) Copyright 2000-2007 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# See file CREDITS for list of people who contributed to this -# project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# - -include $(TOPDIR)/config.mk - -LIB := $(obj)libusb_gadget.o - -# new USB gadget layer dependencies -ifdef CONFIG_USB_ETHER -COBJS-y += ether.o epautoconf.o config.o usbstring.o -COBJS-$(CONFIG_USB_ETH_RNDIS) += rndis.o -else -# Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE -ifdef CONFIG_USB_DEVICE -COBJS-y += core.o -COBJS-y += ep0.o -COBJS-$(CONFIG_OMAP1510) += omap1510_udc.o -COBJS-$(CONFIG_OMAP1610) += omap1510_udc.o -COBJS-$(CONFIG_MPC885_FAMILY) += mpc8xx_udc.o -COBJS-$(CONFIG_PXA27X) += pxa27x_udc.o -COBJS-$(CONFIG_SPEARUDC) += spr_udc.o -endif -endif - -COBJS := $(COBJS-y) -SRCS := $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(COBJS)) - -all: $(LIB) - -$(LIB): $(obj).depend $(OBJS) - $(call cmd_link_o_target, $(OBJS)) - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c deleted file mode 100644 index f9163a8..0000000 --- a/drivers/usb/gadget/config.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * usb/gadget/config.c -- simplify building config descriptors - * - * Copyright (C) 2003 David Brownell - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * 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/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; - *cp = *config; - - /* 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; - cp->wTotalLength = cpu_to_le16(len); - cp->bmAttributes |= USB_CONFIG_ATT_ONE; - return len; -} diff --git a/drivers/usb/gadget/core.c b/drivers/usb/gadget/core.c deleted file mode 100644 index 67b6681..0000000 --- a/drivers/usb/gadget/core.c +++ /dev/null @@ -1,683 +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> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#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; - } - /*usbdbg("%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/drivers/usb/gadget/ep0.c b/drivers/usb/gadget/ep0.c deleted file mode 100644 index 2b4ec44..0000000 --- a/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> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* - * 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 */ - char *cp; - - /*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; - cp = (char*)urb->buffer; - - 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 a USB device supports both a full speed and low speed operation - * we must send a Device_Qualifier descriptor here - */ - return -1; - } - 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/drivers/usb/gadget/ep0.h b/drivers/usb/gadget/ep0.h deleted file mode 100644 index 3bec106..0000000 --- a/drivers/usb/gadget/ep0.h +++ /dev/null @@ -1,39 +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> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __USBDCORE_EP0_H__ -#define __USBDCORE_EP0_H__ - - -int ep0_recv_setup (struct urb *urb); - - -#endif diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c deleted file mode 100644 index 1896489..0000000 --- a/drivers/usb/gadget/epautoconf.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers - * - * Copyright (C) 2004 David Brownell - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * 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 "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(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 ((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; - desc->wMaxPacketSize = cpu_to_le16(size); - } - 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/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c deleted file mode 100644 index 9fb0e80..0000000 --- a/drivers/usb/gadget/ether.c +++ /dev/null @@ -1,2554 +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 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#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 DEV_CONFIG_CDC 1 -#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(DEV_CONFIG_SUBSET) - return 1; /* only cdc possible */ -#elif !defined(DEV_CONFIG_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 DEV_CONFIG_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(DEV_CONFIG_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 DEV_CONFIG_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(DEV_CONFIG_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 DEV_CONFIG_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 DEV_CONFIG_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, -}; - -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, -}; - -static const struct usb_descriptor_header *fs_eth_function[11] = { - (struct usb_descriptor_header *) &otg_descriptor, -#ifdef DEV_CONFIG_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 /* DEV_CONFIG_CDC */ -}; - -static inline void fs_subset_descriptors(void) -{ -#ifdef DEV_CONFIG_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(DEV_CONFIG_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 /* DEV_CONFIG_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 DEV_CONFIG_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 /* DEV_CONFIG_CDC */ -}; - -static inline void hs_subset_descriptors(void) -{ -#ifdef DEV_CONFIG_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 DEV_CONFIG_CDC - { STRING_CDC, "CDC Ethernet", }, - { STRING_CONTROL, "CDC Communications Control", }, -#endif -#ifdef DEV_CONFIG_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, -}; - -/*============================================================================*/ -static u8 control_req[USB_BUFSIZ]; -static u8 status_req[STATUS_BYTECOUNT] __attribute__ ((aligned(4))); - - -/** - * 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(DEV_CONFIG_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 DEV_CONFIG_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); - goto done_set_intf; - } - -#ifdef DEV_CONFIG_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 /* DEV_CONFIG_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 DEV_CONFIG_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 /* DEV_CONFIG_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__); - - 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; - } - - if (i == 6) /* it looks ok */ - return 1; - } - 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 DEV_CONFIG_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(DEV_CONFIG_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 DEV_CONFIG_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(DEV_CONFIG_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(DEV_CONFIG_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, - volatile 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), - (void *)packet, length); - packet = rndis_pkt; - length += sizeof(struct rndis_packet_msg_type); - } - req->buf = (void *)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/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h deleted file mode 100644 index 9bb7e2e..0000000 --- a/drivers/usb/gadget/gadget_chips.h +++ /dev/null @@ -1,220 +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 - -#ifdef CONFIG_USB_GADGET_LH7A40X -#define gadget_is_lh7a40x(g) (!strcmp("lh7a40x_udc", (g)->name)) -#else -#define gadget_is_lh7a40x(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_USB_GADGET_MUSB_HDRC -#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 - - -/* - * 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_lh7a40x(gadget)) - return 0x09; - else if (gadget_is_n9604(gadget)) - return 0x10; - else if (gadget_is_pxa27x(gadget)) - return 0x11; - else if (gadget_is_s3c2410(gadget)) - return 0x12; - else if (gadget_is_at91(gadget)) - return 0x13; - else if (gadget_is_imx(gadget)) - return 0x14; - else if (gadget_is_musbhsfc(gadget)) - return 0x15; - else if (gadget_is_musbhdrc(gadget)) - return 0x16; - else if (gadget_is_mpc8272(gadget)) - return 0x17; - else if (gadget_is_atmel_usba(gadget)) - return 0x18; - else if (gadget_is_fsl_usb2(gadget)) - return 0x19; - else if (gadget_is_amd5536udc(gadget)) - return 0x20; - else if (gadget_is_m66592(gadget)) - return 0x21; - return -ENOENT; -} diff --git a/drivers/usb/gadget/mpc8xx_udc.c b/drivers/usb/gadget/mpc8xx_udc.c deleted file mode 100644 index da3fbba..0000000 --- a/drivers/usb/gadget/mpc8xx_udc.c +++ /dev/null @@ -1,1399 +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. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -/* - * 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 "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/drivers/usb/gadget/ndis.h b/drivers/usb/gadget/ndis.h deleted file mode 100644 index 753838f..0000000 --- a/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/drivers/usb/gadget/omap1510_udc.c b/drivers/usb/gadget/omap1510_udc.c deleted file mode 100644 index 90f7907..0000000 --- a/drivers/usb/gadget/omap1510_udc.c +++ /dev/null @@ -1,1567 +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 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <common.h> -#include <asm/io.h> -#ifdef CONFIG_OMAP_SX1 -#include <i2c.h> -#endif -#include <usbdevice.h> -#include <usb/omap1510_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/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c deleted file mode 100644 index e6ccd49..0000000 --- a/drivers/usb/gadget/pxa27x_udc.c +++ /dev/null @@ -1,702 +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> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - - -#include <common.h> -#include <config.h> -#include <asm/byteorder.h> -#include <usbdcore.h> -#include <usbdcore_ep0.h> -#include <asm/arch/hardware.h> -#include <usb/pxa27x_udc.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) -{ - 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 *addr32 = (u32 *) &UDCDN(ep_num); - u32 *data32 = (u32 *) urb->buffer; - u8 *addr8 = (u8 *) &UDCDN(ep_num); - 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) - UDCCSN(ep_num) = UDCCSR_PC; - - for (i = 0; i < w; i++) - *addr32 = data32[endpoint->sent/4 + i]; - for (i = 0; i < b; i++) - *addr8 = data8[endpoint->sent + w*4 + i]; - - /* Set "Packet Complete" if less data then tx_packetSize */ - if (is_short) - UDCCSN(ep_num) = ep_num ? UDCCSR_SP : UDCCSR0_IPR; - - /* Wait for data sent */ - while (!(UDCCSN(ep_num) & (ep_num ? UDCCSR_PC : UDCCSR0_IPR))) { - if (ep_num) { - 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->tx_urb->actual_length - endpoint->sent) <= 0) { - 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 *addr32 = (u32 *) &UDCDN(ep_num); - u32 *data32 = (u32 *) urb->buffer; - unsigned int i, n, is_short ; - - 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 (UDCCSN(ep_num) & UDCCSR_BNE) - n = UDCBCN(ep_num) & 0x3ff; - else /* zlp */ - n = 0; - is_short = n != endpoint->rcv_packetSize; - - usbdbg("n %d%s", n, is_short ? "-s" : ""); - for (i = 0; i < n; i += 4) - data32[urb->actual_length/4 + i/4] = *addr32; - - 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 *addr32 = (u32 *) &UDCDN(0); - u32 *data32 = (u32 *) ep0_urb->buffer; - u8 *addr8 = (u8 *) &UDCDN(0); - u8 *data8 = (u8 *) ep0_urb->buffer; - unsigned int i, n, w, b; - - n = UDCBCR0; - w = n / 4; - b = n % 4; - - for (i = 0; i < w; i++) { - data32[ep0_urb->actual_length/4 + i] = *addr32; - ep0_urb->actual_length += 4; - } - - for (i = 0; i < b; i++) { - data8[ep0_urb->actual_length + w*4 + i] = *addr8; - ep0_urb->actual_length++; - } - - UDCCSR0 = UDCCSR0_OPC | UDCCSR0_IPR; - 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 = 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"); - UDCCSR0 = UDCCSR0_SST; - 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 = 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 ((UDCCSR0 & UDCCSR0_RNE) == 0) { - usberr("setup packet too short:%d", i); - goto stall; - } - data[i] = UDCDR0; - } - - UDCCSR0 |= (UDCCSR0_OPC | UDCCSR0_SA); - if ((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; - } - UDCCSR0 = UDCCSR0_IPR; - 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; - UDCCSR0 = UDCCSR0_IPR; - } 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; - - UDCCSR0 = UDCCSR0_SA | - UDCCSR0_OPC | UDCCSR0_FST | - UDCCS0_FTF; - - 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) - */ - UDCCSR0 = udccsr0 & (UDCCSR0_SA | UDCCSR0_OPC); - } - 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) { - UDCCSR0 = UDCCSR0_OPC | UDCCSR0_FTF; - 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: - UDCCSR0 = UDCCSR0_IPR; - ep0state = EP0_IDLE; - break; - - default: - usbdbg("Default\n"); - } - USIR0 = USIR0_IR0; -} - -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 = UDCCSN(ep_num) & (UDCCSR_SST | UDCCSR_TRN); - if (flags) - UDCCSN(ep_num) = flags; - - if (ep_isout) - udc_read_urb(endpoint); - else - udc_write_urb(endpoint); - - UDCCSN(ep_num) = UDCCSR_PC; -} - -static void udc_state_changed(void) -{ - int config, interface, alternate; - - UDCCR |= UDCCR_SMAC; - - config = (UDCCR & UDCCR_ACN) >> UDCCR_ACN_S; - interface = (UDCCR & UDCCR_AIN) >> UDCCR_AIN_S; - alternate = (UDCCR & UDCCR_AAISN) >> UDCCR_AAISN_S; - - usbdbg("New UDC settings are: conf %d - inter %d - alter %d", - config, interface, alternate); - - usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0); - UDCISR1 = UDCISR1_IRCC; -} - -void udc_irq(void) -{ - int handled; - struct usb_endpoint_instance *endpoint; - int ep_num, i; - u32 udcisr0; - - do { - handled = 0; - /* Suspend Interrupt Request */ - if (USIR1 & UDCCR_SUSIR) { - usbdbg("Suspend\n"); - udc_ack_int_UDCCR(UDCCR_SUSIR); - handled = 1; - ep0state = EP0_IDLE; - } - - /* Resume Interrupt Request */ - if (USIR1 & UDCCR_RESIR) { - udc_ack_int_UDCCR(UDCCR_RESIR); - handled = 1; - usbdbg("USB resume\n"); - } - - if (USIR1 & (1<<31)) { - handled = 1; - udc_state_changed(); - } - - /* Reset Interrupt Request */ - if (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 (USIR0) - usbdbg("UISR0: %x \n", USIR0); - - if (USIR0 & 0x2) - USIR0 = 0x2; - - /* Control traffic */ - if (USIR0 & USIR0_IR0) { - handled = 1; - udc_handle_ep0(udc_device->bus->endpoint_array); - USIR0 = USIR0_IR0; - } - - 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 = UDCISR0; - if (udcisr0 & - UDCISR_INT(ep_num, UDC_INT_PACKETCMP)) { - UDCISR0 = UDCISR_INT(ep_num, - UDC_INT_PACKETCMP); - 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) -{ - UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS); -} - -static inline void udc_clear_mask_UDCCR(int mask) -{ - UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS); -} - -static void pio_irq_enable(int ep_num) -{ - if (ep_num < 16) - UDCICR0 |= 3 << (ep_num * 2); - else { - ep_num -= 16; - UDCICR1 |= 3 << (ep_num * 2); - } -} - -/* - * 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; - - UDCCN(ep_num) = tmp; - - usbdbg("UDCCR%c = %x", 'A' + ep_num-1, UDCCN(ep_num)); - usbdbg("UDCCSR%c = %x", 'A' + ep_num-1, UDCCSN(ep_num)); -} - -#define CONFIG_USB_DEV_PULLUP_GPIO 87 - -/* Connect the USB device to the bus */ -void udc_connect(void) -{ - usbdbg("UDC connect"); - - /* Turn on the USB connection by enabling the pullup resistor */ - set_GPIO_mode(CONFIG_USB_DEV_PULLUP_GPIO | GPIO_OUT); - GPSR(CONFIG_USB_DEV_PULLUP_GPIO) = GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO); -} - -/* Disconnect the USB device to the bus */ -void udc_disconnect(void) -{ - usbdbg("UDC disconnect"); - - /* Turn off the USB connection by disabling the pullup resistor */ - GPCR(CONFIG_USB_DEV_PULLUP_GPIO) = GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO); -} - -/* Switch on the UDC */ -void udc_enable(struct usb_device_instance *device) -{ - - ep0state = EP0_IDLE; - CKEN |= CKEN11_USB; - - /* enable endpoint 0, A, B's Packet Complete Interrupt. */ - UDCICR0 = 0x0000003f; - UDCICR1 = 0xa8000000; - - /* clear the interrupt status/control registers */ - UDCISR0 = 0xffffffff; - UDCISR1 = 0xffffffff; - - /* 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 */ - CKEN &= ~CKEN11_USB; - - /* 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"); - - /* Disable the UDC */ - udc_clear_mask_UDCCR(UDCCR_UDE); - - /* Disable clock for USB device */ - CKEN &= ~CKEN11_USB; - - /* Disable IRQs: we don't use them */ - UDCICR0 = UDCICR1 = 0; - - return 0; -} diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c deleted file mode 100644 index 886c093..0000000 --- a/drivers/usb/gadget/rndis.c +++ /dev/null @@ -1,1317 +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/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h deleted file mode 100644 index d9e3a75..0000000 --- a/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/drivers/usb/gadget/spr_udc.c b/drivers/usb/gadget/spr_udc.c deleted file mode 100644 index f2b06d6..0000000 --- a/drivers/usb/gadget/spr_udc.c +++ /dev/null @@ -1,998 +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. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/io.h> - -#include <usbdevice.h> -#include "ep0.h" -#include <usb/spr_udc.h> -#include <asm/arch/hardware.h> -#include <asm/arch/spr_misc.h> - -#define UDC_INIT_MDELAY 80 /* Device settle delay */ - -/* Some kind of debugging output... */ -#ifndef DEBUG_SPRUSBTTY -#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; - - if (readl(&udc_regs_p->dev_stat) & DEV_STAT_RXFIFO_EMPTY) - return -1; - - nw = len / sizeof(u32); - nb = len % sizeof(u32); - - 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); - - 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++; - } -} - -/* - * spear_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 spear_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 spear_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. spear_write_noniso_tx_fifo - * will update endpoint->last with the number of bytes written - * to the FIFO. - */ - spear_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 spear_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 spear_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"); - spear_write_noniso_tx_fifo(endpoint); - - ep_addr = endpoint->endpoint_address; - writel(0x0, &inep_regs_p[ep_addr].write_done); - } - } -} - -static struct usb_endpoint_instance *spear_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 spear_udc_epn_rx(int ep) -{ - int nbytes = 0; - struct urb *urb; - struct usb_endpoint_instance *endpoint = spear_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 spear_udc_epn_tx(int ep) -{ - struct usb_endpoint_instance *endpoint = spear_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 && endpoint->tx_urb && endpoint->tx_urb->actual_length) { - if (endpoint->last == endpoint->tx_packetSize) { - /* handle zero length packet here */ - writel(0x0, &inep_regs_p[ep].write_done); - } - /* 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 */ - spear_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); - - udc_disconnect(); - - 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); - - writel(DEV_CONF_FS_SPEED | DEV_CONF_REMWAKEUP | DEV_CONF_SELFPOW | - /* Dev_Conf_SYNCFRAME | */ - DEV_CONF_PHYINT_16, &udc_regs_p->dev_conf); - - writel(0x0, &udc_regs_p->dev_cntl); - - /* Clear all interrupts pending */ - writel(DEV_INT_MSK, &udc_regs_p->dev_int); - - return 0; -} - -/* - * 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; - - 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); - - writel((packet_size << 19) | ENDP_EPTYPE_CNTL, - &udc_regs_p->udc_endp_reg[ep_num]); - - } 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; - - 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; - - 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 SPEAr 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 - */ -void spear_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 { - /* - * USB cable detached - * Reset the PHY and switch the mode. - */ - udc_disconnect(); - 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 - */ -void spear_udc_dev_irq(void) -{ - if (readl(&udc_regs_p->dev_int) & DEV_INT_USBRESET) { - writel(~0x0, &udc_regs_p->endp_int_mask); - - udc_connect(); - - 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); - - 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 - */ -void spear_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) { - spear_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) { - spear_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) { - spear_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); - } - - while (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) { - - spear_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); - spear_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)) - spear_udc_plug_irq(); - - while (readl(&udc_regs_p->dev_int)) - spear_udc_dev_irq(); - - if (readl(&udc_regs_p->endp_int)) - spear_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/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c deleted file mode 100644 index 95555cf..0000000 --- a/drivers/usb/gadget/usbstring.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2003 David Brownell - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * 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; - - /* 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/drivers/usb/host/Makefile b/drivers/usb/host/Makefile deleted file mode 100644 index 51b2494..0000000 --- a/drivers/usb/host/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -# -# (C) Copyright 2000-2007 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# See file CREDITS for list of people who contributed to this -# project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# - -include $(TOPDIR)/config.mk - -LIB := $(obj)libusb_host.o - -# ohci -COBJS-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o -COBJS-$(CONFIG_USB_ATMEL) += ohci-at91.o -COBJS-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o -COBJS-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o -COBJS-$(CONFIG_USB_S3C64XX) += s3c64xx-hcd.o -COBJS-$(CONFIG_USB_SL811HS) += sl811-hcd.o - -# echi -COBJS-$(CONFIG_USB_EHCI) += ehci-hcd.o -ifdef CONFIG_MPC512X -COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-mpc512x.o -else -COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o -endif -COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o -COBJS-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o -COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o -COBJS-$(CONFIG_USB_EHCI_KIRKWOOD) += ehci-kirkwood.o -COBJS-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o -COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o - -COBJS := $(COBJS-y) -SRCS := $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(COBJS)) - -all: $(LIB) - -$(LIB): $(obj).depend $(OBJS) - $(call cmd_link_o_target, $(OBJS)) - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### diff --git a/drivers/usb/host/ehci-core.h b/drivers/usb/host/ehci-core.h deleted file mode 100644 index 39e5c5e..0000000 --- a/drivers/usb/host/ehci-core.h +++ /dev/null @@ -1,29 +0,0 @@ -/*- - * Copyright (c) 2007-2008, Juniper Networks, Inc. - * Copyright (c) 2008, Excito Elektronik i SkÃ¥ne AB - * 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_CORE_H -#define USB_EHCI_CORE_H - -extern int rootdev; -extern struct ehci_hccr *hccr; -extern volatile struct ehci_hcor *hcor; - -#endif diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c deleted file mode 100644 index 6e0043a..0000000 --- a/drivers/usb/host/ehci-fsl.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * (C) Copyright 2009 Freescale Semiconductor, Inc. - * - * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB - * - * Author: Tor Krill tor@excito.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <pci.h> -#include <usb.h> -#include <asm/io.h> -#include <usb/ehci-fsl.h> - -#include "ehci.h" -#include "ehci-core.h" - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - * - * Excerpts from linux ehci fsl driver. - */ -int ehci_hcd_init(void) -{ - struct usb_ehci *ehci; - - ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_ADDR; - 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 (!strcmp(getenv("usb_phy_type"), "utmi")) - out_le32(&(hcor->or_portsc[0]), PORT_PTS_UTMI); - else - out_le32(&(hcor->or_portsc[0]), PORT_PTS_ULPI); - - /* Enable interface. */ - setbits_be32(&ehci->control, USB_EN); - - out_be32(&ehci->prictrl, 0x0000000c); - out_be32(&ehci->age_cnt_limit, 0x00000040); - out_be32(&ehci->sictrl, 0x00000001); - - in_le32(&ehci->usbmode); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(void) -{ - return 0; -} diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c deleted file mode 100644 index 70c02c9..0000000 --- a/drivers/usb/host/ehci-hcd.c +++ /dev/null @@ -1,900 +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 <asm/byteorder.h> -#include <usb.h> -#include <asm/io.h> -#include <malloc.h> -#include <watchdog.h> - -#include "ehci.h" - -int rootdev; -struct ehci_hccr *hccr; /* R/O registers, not need for volatile */ -volatile struct ehci_hcor *hcor; - -static uint16_t portreset; -static struct QH qh_list __attribute__((aligned(32))); - -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 */ - 0xff, /* 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 - -#if defined(CONFIG_EHCI_DCACHE) -/* - * Routines to handle (flush/invalidate) the dcache for the QH and qTD - * structures and data buffers. This is needed on platforms using this - * EHCI support with dcache enabled. - */ -static void flush_invalidate(u32 addr, int size, int flush) -{ - if (flush) - flush_dcache_range(addr, addr + size); - else - invalidate_dcache_range(addr, addr + size); -} - -static void cache_qtd(struct qTD *qtd, int flush) -{ - u32 *ptr = (u32 *)qtd->qt_buffer[0]; - int len = (qtd->qt_token & 0x7fff0000) >> 16; - - flush_invalidate((u32)qtd, sizeof(struct qTD), flush); - if (ptr && len) - flush_invalidate((u32)ptr, len, flush); -} - - -static inline struct QH *qh_addr(struct QH *qh) -{ - return (struct QH *)((u32)qh & 0xffffffe0); -} - -static void cache_qh(struct QH *qh, int flush) -{ - struct qTD *qtd; - struct qTD *next; - static struct qTD *first_qtd; - - /* - * Walk the QH list and flush/invalidate all entries - */ - while (1) { - flush_invalidate((u32)qh_addr(qh), sizeof(struct QH), flush); - if ((u32)qh & QH_LINK_TYPE_QH) - break; - qh = qh_addr(qh); - qh = (struct QH *)qh->qh_link; - } - qh = qh_addr(qh); - - /* - * Save first qTD pointer, needed for invalidating pass on this QH - */ - if (flush) - first_qtd = qtd = (struct qTD *)(*(u32 *)&qh->qh_overlay & - 0xffffffe0); - else - qtd = first_qtd; - - /* - * Walk the qTD list and flush/invalidate all entries - */ - while (1) { - if (qtd == NULL) - break; - cache_qtd(qtd, flush); - next = (struct qTD *)((u32)qtd->qt_next & 0xffffffe0); - if (next == qtd) - break; - qtd = next; - } -} - -static inline void ehci_flush_dcache(struct QH *qh) -{ - cache_qh(qh, 1); -} - -static inline void ehci_invalidate_dcache(struct QH *qh) -{ - cache_qh(qh, 0); -} -#else /* CONFIG_EHCI_DCACHE */ -/* - * - */ -static inline void ehci_flush_dcache(struct QH *qh) -{ -} - -static inline void ehci_invalidate_dcache(struct QH *qh) -{ -} -#endif /* CONFIG_EHCI_DCACHE */ - -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 void ehci_free(void *p, size_t sz) -{ - -} - -static int ehci_reset(void) -{ - uint32_t cmd; - uint32_t tmp; - uint32_t *reg_ptr; - int ret = 0; - - cmd = ehci_readl(&hcor->or_usbcmd); - cmd = (cmd & ~CMD_RUN) | CMD_RESET; - ehci_writel(&hcor->or_usbcmd, cmd); - ret = handshake((uint32_t *)&hcor->or_usbcmd, CMD_RESET, 0, 250 * 1000); - if (ret < 0) { - printf("EHCI fail to reset\n"); - goto out; - } - - if (ehci_is_TDI()) { - reg_ptr = (uint32_t *)((u8 *)hcor + 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); - } -out: - return ret; -} - -static void *ehci_alloc(size_t sz, size_t align) -{ - static struct QH qh __attribute__((aligned(32))); - static struct qTD td[3] __attribute__((aligned (32))); - static int ntds; - void *p; - - switch (sz) { - case sizeof(struct QH): - p = &qh; - ntds = 0; - break; - case sizeof(struct qTD): - if (ntds == 3) { - debug("out of TDs\n"); - return NULL; - } - p = &td[ntds]; - ntds++; - break; - default: - debug("unknown allocation size\n"); - return NULL; - } - - memset(p, 0, sz); - return p; -} - -static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz) -{ - uint32_t addr, delta, next; - int idx; - - addr = (uint32_t) buf; - idx = 0; - while (idx < 5) { - td->qt_buffer[idx] = cpu_to_hc32(addr); - td->qt_buffer_hi[idx] = 0; - next = (addr + 4096) & ~4095; - delta = next - addr; - if (delta >= sz) - break; - sz -= delta; - addr = next; - idx++; - } - - if (idx == 5) { - debug("out of buffer pointers (%u bytes left)\n", sz); - return -1; - } - - return 0; -} - -static int -ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, struct devrequest *req) -{ - struct QH *qh; - struct qTD *td; - volatile struct qTD *vtd; - unsigned long ts; - uint32_t *tdp; - uint32_t endpt, token, usbsts; - uint32_t c, toggle; - uint32_t cmd; - int timeout; - int ret = 0; - - 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)); - - qh = ehci_alloc(sizeof(struct QH), 32); - if (qh == NULL) { - debug("unable to allocate QH\n"); - return -1; - } - qh->qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH); - c = (usb_pipespeed(pipe) != USB_SPEED_HIGH && - usb_pipeendpoint(pipe) == 0) ? 1 : 0; - endpt = (8 << 28) | - (c << 27) | - (usb_maxpacket(dev, pipe) << 16) | - (0 << 15) | - (1 << 14) | - (usb_pipespeed(pipe) << 12) | - (usb_pipeendpoint(pipe) << 8) | - (0 << 7) | (usb_pipedevice(pipe) << 0); - qh->qh_endpt1 = cpu_to_hc32(endpt); - endpt = (1 << 30) | - (dev->portnr << 23) | - (dev->parent->devnum << 16) | (0 << 8) | (0 << 0); - qh->qh_endpt2 = cpu_to_hc32(endpt); - qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - - td = NULL; - tdp = &qh->qh_overlay.qt_next; - - toggle = - usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); - - if (req != NULL) { - td = ehci_alloc(sizeof(struct qTD), 32); - if (td == NULL) { - debug("unable to allocate SETUP td\n"); - goto fail; - } - td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - token = (0 << 31) | - (sizeof(*req) << 16) | - (0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0); - td->qt_token = cpu_to_hc32(token); - if (ehci_td_buffer(td, req, sizeof(*req)) != 0) { - debug("unable construct SETUP td\n"); - ehci_free(td, sizeof(*td)); - goto fail; - } - *tdp = cpu_to_hc32((uint32_t) td); - tdp = &td->qt_next; - toggle = 1; - } - - if (length > 0 || req == NULL) { - td = ehci_alloc(sizeof(struct qTD), 32); - if (td == NULL) { - debug("unable to allocate DATA td\n"); - goto fail; - } - td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - token = (toggle << 31) | - (length << 16) | - ((req == NULL ? 1 : 0) << 15) | - (0 << 12) | - (3 << 10) | - ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0); - td->qt_token = cpu_to_hc32(token); - if (ehci_td_buffer(td, buffer, length) != 0) { - debug("unable construct DATA td\n"); - ehci_free(td, sizeof(*td)); - goto fail; - } - *tdp = cpu_to_hc32((uint32_t) td); - tdp = &td->qt_next; - } - - if (req != NULL) { - td = ehci_alloc(sizeof(struct qTD), 32); - if (td == NULL) { - debug("unable to allocate ACK td\n"); - goto fail; - } - td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - token = (toggle << 31) | - (0 << 16) | - (1 << 15) | - (0 << 12) | - (3 << 10) | - ((usb_pipein(pipe) ? 0 : 1) << 8) | (0x80 << 0); - td->qt_token = cpu_to_hc32(token); - *tdp = cpu_to_hc32((uint32_t) td); - tdp = &td->qt_next; - } - - qh_list.qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH); - - /* Flush dcache */ - ehci_flush_dcache(&qh_list); - - usbsts = ehci_readl(&hcor->or_usbsts); - ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f)); - - /* Enable async. schedule. */ - cmd = ehci_readl(&hcor->or_usbcmd); - cmd |= CMD_ASE; - ehci_writel(&hcor->or_usbcmd, cmd); - - ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, STD_ASS, - 100 * 1000); - if (ret < 0) { - printf("EHCI fail timeout STD_ASS set\n"); - goto fail; - } - - /* Wait for TDs to be processed. */ - ts = get_timer(0); - vtd = td; - timeout = USB_TIMEOUT_MS(pipe); - do { - /* Invalidate dcache */ - ehci_invalidate_dcache(&qh_list); - token = hc32_to_cpu(vtd->qt_token); - if (!(token & 0x80)) - break; - WATCHDOG_RESET(); - } while (get_timer(ts) < timeout); - - /* Check that the TD processing happened */ - if (token & 0x80) { - printf("EHCI timed out on TD - token=%#x\n", token); - goto fail; - } - - /* Disable async schedule. */ - cmd = ehci_readl(&hcor->or_usbcmd); - cmd &= ~CMD_ASE; - ehci_writel(&hcor->or_usbcmd, cmd); - - ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, 0, - 100 * 1000); - if (ret < 0) { - printf("EHCI fail timeout STD_ASS reset\n"); - goto fail; - } - - qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH); - - token = hc32_to_cpu(qh->qh_overlay.qt_token); - if (!(token & 0x80)) { - debug("TOKEN=%#x\n", token); - switch (token & 0xfc) { - case 0: - toggle = token >> 31; - usb_settoggle(dev, usb_pipeendpoint(pipe), - usb_pipeout(pipe), toggle); - dev->status = 0; - break; - case 0x40: - dev->status = USB_ST_STALLED; - break; - case 0xa0: - case 0x20: - dev->status = USB_ST_BUF_ERR; - break; - case 0x50: - case 0x10: - dev->status = USB_ST_BABBLE_DET; - break; - default: - dev->status = USB_ST_CRC_ERR; - if ((token & 0x40) == 0x40) - dev->status |= USB_ST_STALLED; - break; - } - dev->act_len = length - ((token >> 16) & 0x7fff); - } else { - dev->act_len = 0; - debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n", - dev->devnum, ehci_readl(&hcor->or_usbsts), - ehci_readl(&hcor->or_portsc[0]), - ehci_readl(&hcor->or_portsc[1])); - } - - return (dev->status != USB_ST_NOT_PROC) ? 0 : -1; - -fail: - td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next); - while (td != (void *)QT_NEXT_TERMINATE) { - qh->qh_overlay.qt_next = td->qt_next; - ehci_free(td, sizeof(*td)); - td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next); - } - ehci_free(qh, sizeof(*qh)); - return -1; -} - -static inline int min3(int a, int b, int c) -{ - - if (b < a) - a = b; - if (c < a) - a = c; - return a; -} - -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; - - if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { - printf("The request port(%d) is not configured\n", - le16_to_cpu(req->index) - 1); - return -1; - } - status_reg = (uint32_t *)&hcor->or_portsc[ - le16_to_cpu(req->index) - 1]; - 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 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\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 = 0x8; - 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"); - 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 ((reg >> 26) & 3) { - case 0: - break; - case 1: - tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; - break; - case 2: - 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 (portreset & (1 << le16_to_cpu(req->index))) - 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(&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", - req->index - 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 - */ - wait_ms(50); - /* terminate the reset */ - 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) - portreset |= - 1 << le16_to_cpu(req->index); - else - printf("port(%d) reset error\n", - le16_to_cpu(req->index) - 1); - } - break; - default: - debug("unknown feature %x\n", le16_to_cpu(req->value)); - goto unknown; - } - /* unblock posted writes */ - (void) ehci_readl(&hcor->or_usbcmd); - break; - case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - reg = ehci_readl(status_reg); - switch (le16_to_cpu(req->value)) { - case USB_PORT_FEAT_ENABLE: - reg &= ~EHCI_PS_PE; - break; - case USB_PORT_FEAT_C_ENABLE: - reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE; - break; - case USB_PORT_FEAT_POWER: - if (HCS_PPC(ehci_readl(&hccr->cr_hcsparams))) - reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP); - case USB_PORT_FEAT_C_CONNECTION: - reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC; - break; - case USB_PORT_FEAT_OVER_CURRENT: - reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC; - break; - case USB_PORT_FEAT_C_RESET: - portreset &= ~(1 << le16_to_cpu(req->index)); - 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(&hcor->or_usbcmd); - break; - default: - debug("Unknown request\n"); - goto unknown; - } - - wait_ms(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(void) -{ - return ehci_hcd_stop(); -} - -int usb_lowlevel_init(void) -{ - uint32_t reg; - uint32_t cmd; - - if (ehci_hcd_init() != 0) - return -1; - - /* EHCI spec section 4.1 */ - if (ehci_reset() != 0) - return -1; - -#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET) - if (ehci_hcd_init() != 0) - return -1; -#endif - - /* 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((1 << 15) | (USB_SPEED_HIGH << 12)); - 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(0x40); - - /* Set async. queue head pointer. */ - ehci_writel(&hcor->or_asynclistaddr, (uint32_t)&qh_list); - - reg = ehci_readl(&hccr->cr_hcsparams); - descriptor.hub.bNbrPorts = HCS_N_PORTS(reg); - printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); - /* Port Indicators */ - if (HCS_INDICATOR(reg)) - descriptor.hub.wHubCharacteristics |= 0x80; - /* Port Power Control */ - if (HCS_PPC(reg)) - descriptor.hub.wHubCharacteristics |= 0x01; - - /* Start the host controller. */ - cmd = ehci_readl(&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(&hcor->or_usbcmd, cmd); - - /* take control over the ports */ - cmd = ehci_readl(&hcor->or_configflag); - cmd |= FLAG_CF; - ehci_writel(&hcor->or_configflag, cmd); - /* unblock posted write */ - cmd = ehci_readl(&hcor->or_usbcmd); - wait_ms(5); - reg = HC_VERSION(ehci_readl(&hccr->cr_capbase)); - printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff); - - rootdev = 0; - - 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) -{ - - if (usb_pipetype(pipe) != PIPE_CONTROL) { - debug("non-control pipe (type=%lu)", usb_pipetype(pipe)); - return -1; - } - - if (usb_pipedevice(pipe) == rootdev) { - if (rootdev == 0) - dev->speed = USB_SPEED_HIGH; - return ehci_submit_root(dev, pipe, buffer, length, setup); - } - return ehci_submit_async(dev, pipe, buffer, length, setup); -} - -int -submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, int interval) -{ - - debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d", - dev, pipe, buffer, length, interval); - return -1; -} diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c deleted file mode 100644 index b8f15ae..0000000 --- a/drivers/usb/host/ehci-ixp4xx.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * (C) Copyright 2008, Michael Trimarchi <trimarchimichael@yahoo.it> - * - * Author: Michael Trimarchi <trimarchimichael@yahoo.it> - * This code is based on ehci freescale driver - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include <common.h> -#include <usb.h> - -#include "ehci.h" -#include "ehci-core.h" -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(void) -{ - hccr = (struct ehci_hccr *)(0xcd000100); - hcor = (struct ehci_hcor *)((uint32_t) hccr - + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); - - printf("IXP4XX 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(void) -{ - return 0; -} diff --git a/drivers/usb/host/ehci-kirkwood.c b/drivers/usb/host/ehci-kirkwood.c deleted file mode 100644 index 5570fc6..0000000 --- a/drivers/usb/host/ehci-kirkwood.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * (C) Copyright 2009 - * Marvell Semiconductor <www.marvell.com> - * Written-by: Prafulla Wadaskar <prafulla@marvell.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include "ehci.h" -#include "ehci-core.h" -#include <asm/arch/kirkwood.h> - -#define rdl(off) readl(KW_USB20_BASE + (off)) -#define wrl(off, val) writel((val), KW_USB20_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, attrib; - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - - /* Enable DRAM bank */ - switch (i) { - case 0: - attrib = KWCPU_ATTR_DRAM_CS0; - break; - case 1: - attrib = KWCPU_ATTR_DRAM_CS1; - break; - case 2: - attrib = KWCPU_ATTR_DRAM_CS2; - break; - case 3: - attrib = KWCPU_ATTR_DRAM_CS3; - break; - default: - /* invalide bank, disable access */ - attrib = 0; - break; - } - - size = kw_sdram_bs(i); - if ((size) && (attrib)) - wrl(USB_WINDOW_CTRL(i), - KWCPU_WIN_CTRL_DATA(size, USB_TARGET_DRAM, - attrib, KWCPU_WIN_ENABLE)); - else - wrl(USB_WINDOW_CTRL(i), KWCPU_WIN_DISABLE); - - wrl(USB_WINDOW_BASE(i), kw_sdram_bar(i)); - } -} - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(void) -{ - usb_brg_adrdec_setup(); - - hccr = (struct ehci_hccr *)(KW_USB20_BASE + 0x100); - hcor = (struct ehci_hcor *)((uint32_t) hccr - + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); - - debug("Kirkwood-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(void) -{ - return 0; -} diff --git a/drivers/usb/host/ehci-mpc512x.c b/drivers/usb/host/ehci-mpc512x.c deleted file mode 100644 index d360108..0000000 --- a/drivers/usb/host/ehci-mpc512x.c +++ /dev/null @@ -1,159 +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 - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <pci.h> -#include <usb.h> -#include <asm/io.h> -#include <usb/ehci-fsl.h> - -#include "ehci.h" -#include "ehci-core.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(void) -{ - volatile struct usb_ehci *ehci; - - /* Hook the memory mapped registers for EHCI-Controller */ - ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_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(void) -{ - volatile struct usb_ehci *ehci; - int exit_status = 0; - - if (hcor) { - /* Unhook struct */ - hccr = NULL; - hcor = NULL; - - /* Reset the USB controller */ - ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_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/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c deleted file mode 100644 index 8d7b380..0000000 --- a/drivers/usb/host/ehci-mxc.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include <common.h> -#include <usb.h> -#include <asm/io.h> -#include <asm/arch/mx31-regs.h> -#include <usb/ehci-fsl.h> -#include <errno.h> - -#include "ehci.h" -#include "ehci-core.h" - -#define USBCTRL_OTGBASE_OFFSET 0x600 - -#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) - -static int mxc_set_usbcontrol(int port, unsigned int flags) -{ - unsigned int v; -#ifdef CONFIG_MX31 - v = readl(MX31_OTG_BASE_ADDR + USBCTRL_OTGBASE_OFFSET); - - 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; - } - - writel(v, MX31_OTG_BASE_ADDR + - USBCTRL_OTGBASE_OFFSET); -#endif - return 0; -} - -int ehci_hcd_init(void) -{ - u32 tmp; - struct usb_ehci *ehci; - struct clock_control_regs *sc_regs = - (struct clock_control_regs *)CCM_BASE; - - tmp = __raw_readl(&sc_regs->ccmr); - __raw_writel(__raw_readl(&sc_regs->ccmr) | (1 << 9), &sc_regs->ccmr) ; - - udelay(80); - - /* Take USB2 */ - ehci = (struct usb_ehci *)(MX31_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); - setbits_le32(&ehci->control, USB_EN); - - __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); - - mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS); - - udelay(10000); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(void) -{ - return 0; -} diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c deleted file mode 100644 index cff3438..0000000 --- a/drivers/usb/host/ehci-pci.c +++ /dev/null @@ -1,70 +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 <pci.h> -#include <usb.h> - -#include "ehci.h" -#include "ehci-core.h" - -#ifdef CONFIG_PCI_EHCI_DEVICE -static struct pci_device_id ehci_pci_ids[] = { - /* Please add supported PCI EHCI controller ids here */ - {0x1033, 0x00E0}, - {0, 0} -}; -#endif - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(void) -{ - pci_dev_t pdev; - uint32_t addr; - - pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE); - if (pdev == -1) { - printf("EHCI host controller not found\n"); - return -1; - } - - pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &addr); - hccr = (struct ehci_hccr *)addr; - 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))); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(void) -{ - return 0; -} diff --git a/drivers/usb/host/ehci-ppc4xx.c b/drivers/usb/host/ehci-ppc4xx.c deleted file mode 100644 index 1179919..0000000 --- a/drivers/usb/host/ehci-ppc4xx.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * (C) Copyright 2010, Chris Zhang <chris@seamicro.com> - * - * Author: Chris Zhang <chris@seamicro.com> - * This code is based on ehci freescale driver - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include <common.h> -#include <usb.h> - -#include "ehci.h" -#include "ehci-core.h" - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(void) -{ - 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(void) -{ - return 0; -} diff --git a/drivers/usb/host/ehci-vct.c b/drivers/usb/host/ehci-vct.c deleted file mode 100644 index 3063dd1..0000000 --- a/drivers/usb/host/ehci-vct.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * (C) Copyright 2009 Stefan Roese <sr@denx.de>, DENX Software Engineering - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <usb.h> - -#include "ehci.h" -#include "ehci-core.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(void) -{ - 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(void) -{ - return 0; -} diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h deleted file mode 100644 index 945ab64..0000000 --- a/drivers/usb/host/ehci.h +++ /dev/null @@ -1,203 +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 - -#if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 -#endif - -/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */ -#define DeviceRequest \ - ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8) - -#define DeviceOutRequest \ - ((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8) - -#define InterfaceRequest \ - ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8) - -#define EndpointRequest \ - ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8) - -#define EndpointOutRequest \ - ((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8) - -/* - * 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)); - -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 STD_ASS (1 << 15) -#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_[9]; - 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]; - uint32_t or_systune; -} __attribute__ ((packed)); - -#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 */ - uint32_t qt_buffer[5]; /* see EHCI 3.5.4 */ - uint32_t qt_buffer_hi[5]; /* Appendix B */ - /* pad struct for 32 byte alignment */ - uint32_t unused[3]; -}; - -/* 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; - uint32_t qh_endpt2; - uint32_t qh_curtd; - struct qTD qh_overlay; - /* - * Add dummy fill value to make the size of this struct - * aligned to 32 bytes - */ - uint8_t fill[16]; -}; - -/* Low level init functions */ -int ehci_hcd_init(void); -int ehci_hcd_stop(void); - -#endif /* USB_EHCI_H */ diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c deleted file mode 100644 index abdcbb4..0000000 --- a/drivers/usb/host/isp116x-hcd.c +++ /dev/null @@ -1,1441 +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> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * - * 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 ---------------------------------------------------- */ - -/* Device descriptor */ -static __u8 root_hub_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; */ - 0x01, /* __u8 iProduct; */ - 0x00, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - -/* Configuration descriptor */ -static __u8 root_hub_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 */ - 0x00, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ - 0x02, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - -static unsigned char root_hub_str_index0[] = { - 0x04, /* __u8 bLength; */ - 0x03, /* __u8 bDescriptorType; String-descriptor */ - 0x09, /* __u8 lang ID */ - 0x04, /* __u8 lang ID */ -}; - -static unsigned char root_hub_str_index1[] = { - 0x22, /* __u8 bLength; */ - 0x03, /* __u8 bDescriptorType; String-descriptor */ - 'I', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'S', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'P', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - '1', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - '1', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - '6', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'x', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - ' ', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'R', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'o', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'o', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 't', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - ' ', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'H', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'u', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'b', /* __u8 Unicode */ - 0, /* __u8 Unicode */ -}; - -/* - * 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. */ - wait_ms(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 = usb_pipeslow(pipe); - 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 - wait_ms(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; - wait_ms(1); - } - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PRS); - wait_ms(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 */ - wait_ms(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; - wait_ms(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(void) -{ - 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(void) -{ - struct isp116x *isp116x = &isp116x_dev; - - DBG(""); - - if (!isp116x->disabled) - isp116x_stop(isp116x); - - return 0; -} diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h deleted file mode 100644 index a3ce3b5..0000000 --- a/drivers/usb/host/isp116x.h +++ /dev/null @@ -1,489 +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 - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#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/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c deleted file mode 100644 index 64fde68..0000000 --- a/drivers/usb/host/ohci-at91.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * (C) Copyright 2006 - * DENX Software Engineering <mk@denx.de> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> - -#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) - -#include <asm/arch/hardware.h> -#include <asm/arch/io.h> -#include <asm/arch/at91_pmc.h> -#include <asm/arch/clk.h> - -int usb_cpu_init(void) -{ - at91_pmc_t *pmc = (at91_pmc_t *)AT91_PMC_BASE; - -#if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \ - defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \ - defined(CONFIG_AT91SAM9261) - /* Enable PLLB */ - writel(get_pllb_init(), &pmc->pllbr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB) - ; -#elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) - /* 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. */ - writel(1 << AT91_ID_UHP, &pmc->pcer); -#ifdef CONFIG_AT91SAM9261 - writel(AT91_PMC_UHP | AT91_PMC_HCK0, &pmc->scer); -#else - writel(AT91_PMC_UHP, &pmc->scer); -#endif - - return 0; -} - -int usb_cpu_stop(void) -{ - at91_pmc_t *pmc = (at91_pmc_t *)AT91_PMC_BASE; - - /* Disable USB host clock. */ - writel(1 << AT91_ID_UHP, &pmc->pcdr); -#ifdef CONFIG_AT91SAM9261 - writel(AT91_PMC_UHP | AT91_PMC_HCK0, &pmc->scdr); -#else - writel(AT91_PMC_UHP, &pmc->scdr); -#endif - -#if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \ - defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) - /* Disable PLLB */ - writel(0, &pmc->pllbr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != 0) - ; -#elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) - /* 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/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c deleted file mode 100644 index bc8bb20..0000000 --- a/drivers/usb/host/ohci-hcd.c +++ /dev/null @@ -1,2004 +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 - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ -/* - * 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_S3C6400) || \ - 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_pipeslow(pipe) << 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 tdINFO, tdBE, tdCBP; - urb_priv_t *lurb_priv = td->ed->purb; - - tdINFO = m32_swap(td->hwINFO); - 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 - *-------------------------------------------------------------------------*/ - -/* Device descriptor */ -static __u8 root_hub_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; */ - 0x01, /* __u8 iProduct; */ - 0x00, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - -/* Configuration descriptor */ -static __u8 root_hub_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 */ - 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ - 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - -static unsigned char root_hub_str_index0[] = -{ - 0x04, /* __u8 bLength; */ - 0x03, /* __u8 bDescriptorType; String-descriptor */ - 0x09, /* __u8 lang ID */ - 0x04, /* __u8 lang ID */ -}; - -static unsigned char root_hub_str_index1[] = -{ - 28, /* __u8 bLength; */ - 0x03, /* __u8 bDescriptorType; String-descriptor */ - 'O', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'H', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'C', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'I', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - ' ', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'R', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'o', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'o', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 't', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - ' ', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'H', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'u', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'b', /* __u8 Unicode */ - 0, /* __u8 Unicode */ -}; - -/* 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; - __u32 datab[4]; - __u8 *data_buf = (__u8 *)datab; - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - -#ifdef DEBUG -pkt_print(NULL, dev, pipe, buffer, transfer_len, - cmd, "SUB(rh)", usb_pipein(pipe)); -#else - wait_ms(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 *) data_buf = cpu_to_le16(1); - OK(2); - case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *) data_buf = cpu_to_le16(0); - OK(2); - case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *) data_buf = cpu_to_le16(0); - OK(2); - case RH_GET_STATUS | RH_CLASS: - *(__u32 *) data_buf = cpu_to_le32( - RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); - OK(4); - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - *(__u32 *) data_buf = 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); - wait_ms(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)); - 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; -#ifdef CONFIG_AT91C_PQFP_UHPBUG - data_buf [2] = (data_buf [2] == 2) ? 1:0; -#endif - 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 [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 - wait_ms(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 - pkt_print(NULL, dev, pipe, buffer, - transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); -#else - wait_ms(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 - wait_ms(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 - wait_ms(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) { - wait_ms(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 = transfer_len; - -#ifdef DEBUG - pkt_print(urb, dev, pipe, buffer, transfer_len, - setup, "RET(ctlr)", usb_pipein(pipe)); -#else - wait_ms(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 - wait_ms(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) { - wait_ms(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 */ - -#define mdelay(n) ({unsigned long msec = (n); while (msec--) udelay(1000); }) - /* 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; -} - -/*-------------------------------------------------------------------------*/ - -/* Poll USB interrupt. */ -void usb_event_poll(void) -{ - hc_interrupt(); -} - -/* 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 - wait_ms(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) { - wait_ms(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; - wait_ms(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(void) -{ -#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 (usb_board_init()) - 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 */ - usb_board_init_fail(); -#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 - wait_ms(1); -#endif - ohci_inited = 1; - return 0; -} - -int usb_lowlevel_stop(void) -{ - /* 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/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h deleted file mode 100644 index d977e8f..0000000 --- a/drivers/usb/host/ohci.h +++ /dev/null @@ -1,494 +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 */ -extern int usb_board_init(void); -extern int usb_board_stop(void); -extern int usb_board_init_fail(void); - -extern int usb_cpu_init(void); -extern int usb_cpu_stop(void); -extern 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/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c deleted file mode 100644 index db611b6..0000000 --- a/drivers/usb/host/r8a66597-hcd.c +++ /dev/null @@ -1,945 +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 unsigned short clock = CONFIG_R8A66597_XTAL; -static unsigned short vif = CONFIG_R8A66597_LDRV; -static unsigned short endian = CONFIG_R8A66597_ENDIAN; -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, clock, 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, vif & 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, endian & BIGEND, CFIFOSEL); - r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL); - r8a66597_bset(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) { - wait_ms(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) -{ - wait_ms(10); - r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, get_dvstctr_reg(port)); - wait_ms(50); - r8a66597_mdfy(r8a66597, UACT, USBRST | UACT, get_dvstctr_reg(port)); - wait_ms(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 - *-------------------------------------------------------------------------*/ - -/* Device descriptor */ -static __u8 root_hub_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; */ - 0x01, /* __u8 iProduct; */ - 0x00, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - -/* Configuration descriptor */ -static __u8 root_hub_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; */ - - 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 */ - 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ - 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - -static unsigned char root_hub_str_index0[] = -{ - 0x04, /* __u8 bLength; */ - 0x03, /* __u8 bDescriptorType; String-descriptor */ - 0x09, /* __u8 lang ID */ - 0x04, /* __u8 lang ID */ -}; - -static unsigned char root_hub_str_index1[] = -{ - 34, /* __u8 bLength; */ - 0x03, /* __u8 bDescriptorType; String-descriptor */ - 'R', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - '8', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'A', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - '6', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - '6', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - '5', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - '9', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - '7', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - ' ', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'R', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'o', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'o', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 't', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'H', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'u', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'b', /* __u8 Unicode */ - 0, /* __u8 Unicode */ -}; - -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 wIndex; - __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); - wIndex = cpu_to_le16 (cmd->index); - 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; - } - - wait_ms(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; -} - -void usb_event_poll(void) -{ - /* no implement */ - R8A66597_DPRINT("%s\n", __func__); -} - -int usb_lowlevel_init(void) -{ - struct r8a66597 *r8a66597 = &gr8a66597; - - R8A66597_DPRINT("%s\n", __func__); - - memset(r8a66597, 0, sizeof(r8a66597)); - r8a66597->reg = CONFIG_R8A66597_BASE_ADDR; - - disable_controller(r8a66597); - wait_ms(100); - - enable_controller(r8a66597); - r8a66597_port_power(r8a66597, 0 , 1); - - /* check usb device */ - check_usb_device_connecting(r8a66597); - - wait_ms(50); - - return 0; -} - -int usb_lowlevel_stop(void) -{ - disable_controller(&gr8a66597); - - return 0; -} diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h deleted file mode 100644 index 9af6446..0000000 --- a/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++) - inl(p[i], 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/drivers/usb/host/s3c64xx-hcd.c b/drivers/usb/host/s3c64xx-hcd.c deleted file mode 100644 index cd295da..0000000 --- a/drivers/usb/host/s3c64xx-hcd.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) initialization for USB on the S3C64XX. - * - * Copyright (C) 2008, - * Guennadi Liakhovetski, DENX Software Engineering <lg@denx.de> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -#include <common.h> -#include <asm/arch/s3c6400.h> - -int usb_cpu_init(void) -{ - OTHERS_REG |= 0x10000; - return 0; -} - -int usb_cpu_stop(void) -{ - OTHERS_REG &= ~0x10000; - return 0; -} - -void usb_cpu_init_fail(void) -{ - OTHERS_REG &= ~0x10000; -} diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c deleted file mode 100644 index 82a8b36..0000000 --- a/drivers/usb/host/sl811-hcd.c +++ /dev/null @@ -1,734 +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> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#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) - -#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);}) - -#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(void) -{ - root_hub_devnum = 0; - sl811_hc_reset(); - return 0; -} - -int usb_lowlevel_stop(void) -{ - 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) && - usb_pipeslow(pipe); - - 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; - __u16 wIndex; - __u16 wLength; - - if (usb_pipeint(pipe)) { - PDEBUG(0, "interrupt transfer unimplemented!\n"); - 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); - - 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/drivers/usb/host/sl811.h b/drivers/usb/host/sl811.h deleted file mode 100644 index c1f9f01..0000000 --- a/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/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile deleted file mode 100644 index 20b5503..0000000 --- a/drivers/usb/musb/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -# -# (C) Copyright 2000-2007 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# See file CREDITS for list of people who contributed to this -# project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# - -include $(TOPDIR)/config.mk - -LIB := $(obj)libusb_musb.o - -COBJS-$(CONFIG_MUSB_HCD) += musb_hcd.o musb_core.o -COBJS-$(CONFIG_MUSB_UDC) += musb_udc.o musb_core.o -COBJS-$(CONFIG_USB_BLACKFIN) += blackfin_usb.o -COBJS-$(CONFIG_USB_DAVINCI) += davinci.o -COBJS-$(CONFIG_USB_OMAP3) += omap3.o -COBJS-$(CONFIG_USB_DA8XX) += da8xx.o -COBJS-$(CONFIG_USB_AM35X) += am35x.o - -COBJS := $(COBJS-y) -SRCS := $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(COBJS)) - -all: $(LIB) - -$(LIB): $(obj).depend $(OBJS) - $(call cmd_link_o_target, $(OBJS)) - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c deleted file mode 100644 index 1706c13..0000000 --- a/drivers/usb/musb/am35x.c +++ /dev/null @@ -1,150 +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 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#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/drivers/usb/musb/am35x.h b/drivers/usb/musb/am35x.h deleted file mode 100644 index 756c3ae..0000000 --- a/drivers/usb/musb/am35x.h +++ /dev/null @@ -1,94 +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 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#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/drivers/usb/musb/blackfin_usb.c b/drivers/usb/musb/blackfin_usb.c deleted file mode 100644 index 38aceb2..0000000 --- a/drivers/usb/musb/blackfin_usb.c +++ /dev/null @@ -1,143 +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/mach-common/bits/usb.h> - -#include "musb_core.h" - -/* 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"))); - -int musb_platform_init(void) -{ - /* board specific initialization */ - board_musb_init(); - - if (ANOMALY_05000346) { - bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); - SSYNC(); - } - - if (ANOMALY_05000347) { - bfin_write_USB_APHY_CNTRL(0x0); - SSYNC(); - } - - /* Configure PLL oscillator register */ - bfin_write_USB_PLLOSC_CTRL(0x30a8); - 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/drivers/usb/musb/blackfin_usb.h b/drivers/usb/musb/blackfin_usb.h deleted file mode 100644 index de994bf..0000000 --- a/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/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c deleted file mode 100644 index 617d88e..0000000 --- a/drivers/usb/musb/da8xx.c +++ /dev/null @@ -1,139 +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 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include <common.h> - -#include "da8xx.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/drivers/usb/musb/da8xx.h b/drivers/usb/musb/da8xx.h deleted file mode 100644 index b9660ba..0000000 --- a/drivers/usb/musb/da8xx.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * da8xx.h -- TI's DA8xx platform specific usb wrapper definitions. - * - * Author: Ajay Kumar Gupta <ajay.gupta@ti.com> - * - * Based on drivers/usb/musb/davinci.h - * - * Copyright (C) 2009 Texas Instruments Incorporated - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef __DA8XX_MUSB_H__ -#define __DA8XX_MUSB_H__ - -#include <asm/arch/hardware.h> -#include <asm/arch/gpio_defs.h> -#include "musb_core.h" - -/* Base address of da8xx usb0 wrapper */ -#define DA8XX_USB_OTG_BASE 0x01E00000 - -/* Base address of da8xx musb core */ -#define DA8XX_USB_OTG_CORE_BASE (DA8XX_USB_OTG_BASE + 0x400) - -/* Timeout for DA8xx usb module */ -#define DA8XX_USB_OTG_TIMEOUT 0x3FFFFFF - -/* - * DA8xx platform USB wrapper register overlay. - */ -struct da8xx_usb_regs { - dv_reg revision; - dv_reg control; - dv_reg status; - dv_reg emulation; - dv_reg mode; - dv_reg autoreq; - dv_reg srpfixtime; - dv_reg teardown; - dv_reg intsrc; - dv_reg intsrc_set; - dv_reg intsrc_clr; - dv_reg intmsk; - dv_reg intmsk_set; - dv_reg intmsk_clr; - dv_reg intsrcmsk; - dv_reg eoi; - dv_reg intvector; - dv_reg grndis_size[4]; -}; - -#define da8xx_usb_regs ((struct da8xx_usb_regs *)DA8XX_USB_OTG_BASE) - -/* DA8XX interrupt bits definitions */ -#define DA8XX_USB_TX_ENDPTS_MASK 0x1f /* ep0 + 4 tx */ -#define DA8XX_USB_RX_ENDPTS_MASK 0x1e /* 4 rx */ -#define DA8XX_USB_TXINT_SHIFT 0 -#define DA8XX_USB_RXINT_SHIFT 8 - -#define DA8XX_USB_USBINT_MASK 0x01ff0000 /* 8 Mentor, DRVVBUS */ -#define DA8XX_USB_TXINT_MASK \ - (DA8XX_USB_TX_ENDPTS_MASK << DA8XX_USB_TXINT_SHIFT) -#define DA8XX_USB_RXINT_MASK \ - (DA8XX_USB_RX_ENDPTS_MASK << DA8XX_USB_RXINT_SHIFT) - -/* DA8xx CFGCHIP2 (USB 2.0 PHY Control) register bits */ -#define CFGCHIP2_PHYCLKGD (1 << 17) -#define CFGCHIP2_VBUSSENSE (1 << 16) -#define CFGCHIP2_RESET (1 << 15) -#define CFGCHIP2_OTGMODE (3 << 13) -#define CFGCHIP2_NO_OVERRIDE (0 << 13) -#define CFGCHIP2_FORCE_HOST (1 << 13) -#define CFGCHIP2_FORCE_DEVICE (2 << 13) -#define CFGCHIP2_FORCE_HOST_VBUS_LOW (3 << 13) -#define CFGCHIP2_USB1PHYCLKMUX (1 << 12) -#define CFGCHIP2_USB2PHYCLKMUX (1 << 11) -#define CFGCHIP2_PHYPWRDN (1 << 10) -#define CFGCHIP2_OTGPWRDN (1 << 9) -#define CFGCHIP2_DATPOL (1 << 8) -#define CFGCHIP2_USB1SUSPENDM (1 << 7) -#define CFGCHIP2_PHY_PLLON (1 << 6) /* override PLL suspend */ -#define CFGCHIP2_SESENDEN (1 << 5) /* Vsess_end comparator */ -#define CFGCHIP2_VBDTCTEN (1 << 4) /* Vbus comparator */ -#define CFGCHIP2_REFFREQ (0xf << 0) -#define CFGCHIP2_REFFREQ_12MHZ (1 << 0) -#define CFGCHIP2_REFFREQ_24MHZ (2 << 0) -#define CFGCHIP2_REFFREQ_48MHZ (3 << 0) - -#define DA8XX_USB_VBUS_GPIO (1 << 15) -#endif /* __DA8XX_MUSB_H__ */ diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c deleted file mode 100644 index f56f2df..0000000 --- a/drivers/usb/musb/davinci.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * TI's Davinci platform specific USB wrapper functions. - * - * Copyright (c) 2008 Texas Instruments - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments - */ - -#include <common.h> -#include <asm/io.h> -#include "davinci.h" -#include <asm/arch/hardware.h> - -/* 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(USBPHY_SESNDEN | USBPHY_VBDTCTEN, 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); -} - -/* - * This function performs Davinci platform specific initialization for usb0. - */ -int musb_platform_init(void) -{ - u32 revision; - - /* enable USB VBUS */ -#ifndef DAVINCI_DM365EVM - enable_vbus(); -#endif - /* 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/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h deleted file mode 100644 index e0829d6..0000000 --- a/drivers/usb/musb/davinci.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * TI's Davinci platform specific USB wrapper functions. - * - * Copyright (c) 2008 Texas Instruments - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * 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/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c deleted file mode 100644 index 545ebf4..0000000 --- a/drivers/usb/musb/musb_core.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Mentor USB OTG Core functionality common for both Host and Device - * functionality. - * - * Copyright (c) 2008 Texas Instruments - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * 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/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h deleted file mode 100644 index a8adcce..0000000 --- a/drivers/usb/musb/musb_core.h +++ /dev/null @@ -1,396 +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.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, aligned(32))); -#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/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h deleted file mode 100644 index 62380ff..0000000 --- a/drivers/usb/musb/musb_debug.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2009 Wind River Systems, Inc. - * Tom Rix <Tom.Rix@windriver.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* 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/drivers/usb/musb/musb_hcd.c b/drivers/usb/musb/musb_hcd.c deleted file mode 100644 index 8b0c61d..0000000 --- a/drivers/usb/musb/musb_hcd.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* - * Mentor USB OTG Core host controller driver. - * - * Copyright (c) 2008 Texas Instruments - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments - */ - -#include <common.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; - -/* Device descriptor */ -static const u8 root_hub_dev_des[] = { - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x00, /* __u16 bcdUSB; v1.1 */ - 0x02, - 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; */ - 0x01, /* __u8 iProduct; */ - 0x00, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - -/* Configuration descriptor */ -static const u8 root_hub_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 */ - 0x00, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ - 0x02, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - -static const unsigned char root_hub_str_index0[] = { - 0x04, /* __u8 bLength; */ - 0x03, /* __u8 bDescriptorType; String-descriptor */ - 0x09, /* __u8 lang ID */ - 0x04, /* __u8 lang ID */ -}; - -static const unsigned char root_hub_str_index1[] = { - 0x1c, /* __u8 bLength; */ - 0x03, /* __u8 bDescriptorType; String-descriptor */ - 'M', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'U', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'S', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'B', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - ' ', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'R', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'o', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'o', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 't', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - ' ', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'H', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'u', /* __u8 Unicode */ - 0, /* __u8 Unicode */ - 'b', /* __u8 Unicode */ - 0, /* __u8 Unicode */ -}; -#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 u8 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 u8 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); - writew(csr | MUSB_CSR0_H_DIS_PING | MUSB_CSR0_TXPKTRDY, - &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_H_DIS_PING | MUSB_CSR0_TXPKTRDY | - MUSB_CSR0_H_STATUSPKT); - 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_DIS_PING | MUSB_CSR0_H_REQPKT | MUSB_CSR0_H_STATUSPKT; - 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 %d\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); - u16 csr; - u8 devspeed; - -#ifdef MUSB_NO_MULTIPOINT - /* Control message is for the HUB? */ - if (devnum == rh_devnum) - return musb_submit_rh_msg(dev, pipe, buffer, len, setup); -#endif - - /* select control endpoint */ - writeb(MUSB_CONTROL_EP, &musbr->index); - csr = 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)) { - 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)) { - 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(void) -{ - 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], - sizeof(epinfo) / sizeof(struct musb_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(void) -{ - /* 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)) { - 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; -} - - -#ifdef CONFIG_SYS_USB_EVENT_POLL -/* - * This function polls for USB keyboard data. - */ -void usb_event_poll() -{ - struct stdio_dev *dev; - struct usb_device *usb_kbd_dev; - struct usb_interface *iface; - struct usb_endpoint_descriptor *ep; - int pipe; - int maxp; - - /* Get the pointer to USB Keyboard device pointer */ - dev = stdio_get_by_name("usbkbd"); - usb_kbd_dev = (struct usb_device *)dev->priv; - iface = &usb_kbd_dev->config.if_desc[0]; - ep = &iface->ep_desc[0]; - pipe = usb_rcvintpipe(usb_kbd_dev, ep->bEndpointAddress); - - /* Submit a interrupt transfer request */ - maxp = usb_maxpacket(usb_kbd_dev, pipe); - usb_submit_int_msg(usb_kbd_dev, pipe, &new[0], - maxp > 8 ? 8 : maxp, ep->bInterval); -} -#endif /* CONFIG_SYS_USB_EVENT_POLL */ diff --git a/drivers/usb/musb/musb_hcd.h b/drivers/usb/musb/musb_hcd.h deleted file mode 100644 index dde7d37..0000000 --- a/drivers/usb/musb/musb_hcd.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Mentor USB OTG Core host controller driver. - * - * Copyright (c) 2008 Texas Instruments - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * 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/drivers/usb/musb/musb_udc.c b/drivers/usb/musb/musb_udc.c deleted file mode 100644 index 6f6ed61..0000000 --- a/drivers/usb/musb/musb_udc.c +++ /dev/null @@ -1,965 +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) - * - * ------------------------------------------------------------------------- - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <usb/musb_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; - u8 intrusb; - u16 intrrx, intrtx; - - /* Power off MUSB */ - power = readb(&musbr->power); - power &= ~MUSB_POWER_SOFTCONN; - writeb(power, &musbr->power); - - /* Read intr to clear */ - intrusb = readb(&musbr->intrusb); - intrrx = readw(&musbr->intrrx); - intrtx = 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 = 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], - sizeof(epinfo) / sizeof(struct musb_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/drivers/usb/musb/omap3.c b/drivers/usb/musb/omap3.c deleted file mode 100644 index c7876ed..0000000 --- a/drivers/usb/musb/omap3.c +++ /dev/null @@ -1,156 +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 - * - * ------------------------------------------------------------------------ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#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_BASE + 0x33C); - *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/drivers/usb/musb/omap3.h b/drivers/usb/musb/omap3.h deleted file mode 100644 index b2acdf4..0000000 --- a/drivers/usb/musb/omap3.h +++ /dev/null @@ -1,52 +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 - * - * -------------------------------------------------------------------- - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#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/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile deleted file mode 100644 index 5547570..0000000 --- a/drivers/usb/phy/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright (c) 2009 Wind River Systems, Inc. -# Tom Rix <Tom.Rix@windriver.com> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# - -include $(TOPDIR)/config.mk - -LIB := $(obj)libusb_phy.o - -COBJS-$(CONFIG_TWL4030_USB) += twl4030.o - -COBJS := $(COBJS-y) -SRCS := $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(COBJS)) - -all: $(LIB) - -$(LIB): $(obj).depend $(OBJS) - $(call cmd_link_o_target, $(OBJS)) - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### diff --git a/drivers/usb/phy/twl4030.c b/drivers/usb/phy/twl4030.c deleted file mode 100644 index 54d2e61..0000000 --- a/drivers/usb/phy/twl4030.c +++ /dev/null @@ -1,189 +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) - * - * ------------------------------------------------------------------------ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#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, data, address); - 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, &data, address); - 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, 0xC0, - TWL4030_PM_MASTER_PROTECT_KEY); - twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x0C, - TWL4030_PM_MASTER_PROTECT_KEY); - - /* put VUSB3V1 LDO in active state */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00, - TWL4030_PM_RECEIVER_VUSB_DEDICATED2); - - /* input to VUSB3V1 LDO is from VBAT, not VBUS */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x14, - TWL4030_PM_RECEIVER_VUSB_DEDICATED1); - - /* turn on 3.1V regulator */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20, - TWL4030_PM_RECEIVER_VUSB3V1_DEV_GRP); - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00, - TWL4030_PM_RECEIVER_VUSB3V1_TYPE); - - /* turn on 1.5V regulator */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20, - TWL4030_PM_RECEIVER_VUSB1V5_DEV_GRP); - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00, - TWL4030_PM_RECEIVER_VUSB1V5_TYPE); - - /* turn on 1.8V regulator */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20, - TWL4030_PM_RECEIVER_VUSB1V8_DEV_GRP); - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00, - TWL4030_PM_RECEIVER_VUSB1V8_TYPE); - - /* disable access to power configuration registers */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x00, - TWL4030_PM_MASTER_PROTECT_KEY); -} - -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; -} |