Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
This commit is contained in:
@@ -297,13 +297,34 @@ config USB_S3C2410_DEBUG
|
||||
|
||||
# musb builds in ../musb along with host support
|
||||
config USB_GADGET_MUSB_HDRC
|
||||
boolean "Inventra HDRC USB Peripheral (TI, ...)"
|
||||
boolean "Inventra HDRC USB Peripheral (TI, ADI, ...)"
|
||||
depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
|
||||
select USB_GADGET_DUALSPEED
|
||||
select USB_GADGET_SELECTED
|
||||
help
|
||||
This OTG-capable silicon IP is used in dual designs including
|
||||
the TI DaVinci, OMAP 243x, OMAP 343x, and TUSB 6010.
|
||||
the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin
|
||||
|
||||
config USB_GADGET_IMX
|
||||
boolean "Freescale IMX USB Peripheral Controller"
|
||||
depends on ARCH_MX1
|
||||
help
|
||||
Freescale's IMX series include an integrated full speed
|
||||
USB 1.1 device controller. The controller in the IMX series
|
||||
is register-compatible.
|
||||
|
||||
It has Six fixed-function endpoints, as well as endpoint
|
||||
zero (for control transfers).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "imx_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_IMX
|
||||
tristate
|
||||
depends on USB_GADGET_IMX
|
||||
default USB_GADGET
|
||||
select USB_GADGET_SELECTED
|
||||
|
||||
config USB_GADGET_M66592
|
||||
boolean "Renesas M66592 USB Peripheral Controller"
|
||||
@@ -377,6 +398,24 @@ config USB_FSL_QE
|
||||
default USB_GADGET
|
||||
select USB_GADGET_SELECTED
|
||||
|
||||
config USB_GADGET_CI13XXX
|
||||
boolean "MIPS USB CI13xxx"
|
||||
depends on PCI
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
MIPS USB IP core family device controller
|
||||
Currently it only supports IP part number CI13412
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "ci13xxx_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_CI13XXX
|
||||
tristate
|
||||
depends on USB_GADGET_CI13XXX
|
||||
default USB_GADGET
|
||||
select USB_GADGET_SELECTED
|
||||
|
||||
config USB_GADGET_NET2280
|
||||
boolean "NetChip 228x"
|
||||
depends on PCI
|
||||
|
@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_NET2280) += net2280.o
|
||||
obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o
|
||||
obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o
|
||||
obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o
|
||||
obj-$(CONFIG_USB_IMX) += imx_udc.o
|
||||
obj-$(CONFIG_USB_GOKU) += goku_udc.o
|
||||
obj-$(CONFIG_USB_OMAP) += omap_udc.o
|
||||
obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o
|
||||
@@ -19,6 +20,7 @@ obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
|
||||
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
|
||||
obj-$(CONFIG_USB_M66592) += m66592-udc.o
|
||||
obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
|
||||
obj-$(CONFIG_USB_CI13XXX) += ci13xxx_udc.o
|
||||
|
||||
#
|
||||
# USB gadget drivers
|
||||
|
@@ -1474,7 +1474,7 @@ static struct at91_udc controller = {
|
||||
.ep0 = &controller.ep[0].ep,
|
||||
.name = driver_name,
|
||||
.dev = {
|
||||
.bus_id = "gadget",
|
||||
.init_name = "gadget",
|
||||
.release = nop_release,
|
||||
}
|
||||
},
|
||||
|
@@ -1034,7 +1034,7 @@ static struct usba_udc the_udc = {
|
||||
.is_dualspeed = 1,
|
||||
.name = "atmel_usba_udc",
|
||||
.dev = {
|
||||
.bus_id = "gadget",
|
||||
.init_name = "gadget",
|
||||
.release = nop_release,
|
||||
},
|
||||
},
|
||||
|
2830
drivers/usb/gadget/ci13xxx_udc.c
Normal file
2830
drivers/usb/gadget/ci13xxx_udc.c
Normal file
File diff suppressed because it is too large
Load Diff
195
drivers/usb/gadget/ci13xxx_udc.h
Normal file
195
drivers/usb/gadget/ci13xxx_udc.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* ci13xxx_udc.h - structures, registers, and macros MIPS USB IP core
|
||||
*
|
||||
* Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
|
||||
*
|
||||
* Author: David Lopo
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Description: MIPS USB IP core family device controller
|
||||
* Structures, registers and logging macros
|
||||
*/
|
||||
|
||||
#ifndef _CI13XXX_h_
|
||||
#define _CI13XXX_h_
|
||||
|
||||
/******************************************************************************
|
||||
* DEFINE
|
||||
*****************************************************************************/
|
||||
#define ENDPT_MAX (16)
|
||||
#define CTRL_PAYLOAD_MAX (64)
|
||||
#define RX (0) /* similar to USB_DIR_OUT but can be used as an index */
|
||||
#define TX (1) /* similar to USB_DIR_IN but can be used as an index */
|
||||
|
||||
/******************************************************************************
|
||||
* STRUCTURES
|
||||
*****************************************************************************/
|
||||
/* DMA layout of transfer descriptors */
|
||||
struct ci13xxx_td {
|
||||
/* 0 */
|
||||
u32 next;
|
||||
#define TD_TERMINATE BIT(0)
|
||||
/* 1 */
|
||||
u32 token;
|
||||
#define TD_STATUS (0x00FFUL << 0)
|
||||
#define TD_STATUS_TR_ERR BIT(3)
|
||||
#define TD_STATUS_DT_ERR BIT(5)
|
||||
#define TD_STATUS_HALTED BIT(6)
|
||||
#define TD_STATUS_ACTIVE BIT(7)
|
||||
#define TD_MULTO (0x0003UL << 10)
|
||||
#define TD_IOC BIT(15)
|
||||
#define TD_TOTAL_BYTES (0x7FFFUL << 16)
|
||||
/* 2 */
|
||||
u32 page[5];
|
||||
#define TD_CURR_OFFSET (0x0FFFUL << 0)
|
||||
#define TD_FRAME_NUM (0x07FFUL << 0)
|
||||
#define TD_RESERVED_MASK (0x0FFFUL << 0)
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* DMA layout of queue heads */
|
||||
struct ci13xxx_qh {
|
||||
/* 0 */
|
||||
u32 cap;
|
||||
#define QH_IOS BIT(15)
|
||||
#define QH_MAX_PKT (0x07FFUL << 16)
|
||||
#define QH_ZLT BIT(29)
|
||||
#define QH_MULT (0x0003UL << 30)
|
||||
/* 1 */
|
||||
u32 curr;
|
||||
/* 2 - 8 */
|
||||
struct ci13xxx_td td;
|
||||
/* 9 */
|
||||
u32 RESERVED;
|
||||
struct usb_ctrlrequest setup;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Extension of usb_request */
|
||||
struct ci13xxx_req {
|
||||
struct usb_request req;
|
||||
unsigned map;
|
||||
struct list_head queue;
|
||||
struct ci13xxx_td *ptr;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
/* Extension of usb_ep */
|
||||
struct ci13xxx_ep {
|
||||
struct usb_ep ep;
|
||||
const struct usb_endpoint_descriptor *desc;
|
||||
u8 dir;
|
||||
u8 num;
|
||||
u8 type;
|
||||
char name[16];
|
||||
struct {
|
||||
struct list_head queue;
|
||||
struct ci13xxx_qh *ptr;
|
||||
dma_addr_t dma;
|
||||
} qh[2];
|
||||
struct usb_request *status;
|
||||
int wedge;
|
||||
|
||||
/* global resources */
|
||||
spinlock_t *lock;
|
||||
struct device *device;
|
||||
struct dma_pool *td_pool;
|
||||
};
|
||||
|
||||
/* CI13XXX UDC descriptor & global resources */
|
||||
struct ci13xxx {
|
||||
spinlock_t *lock; /* ctrl register bank access */
|
||||
|
||||
struct dma_pool *qh_pool; /* DMA pool for queue heads */
|
||||
struct dma_pool *td_pool; /* DMA pool for transfer descs */
|
||||
|
||||
struct usb_gadget gadget; /* USB slave device */
|
||||
struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */
|
||||
|
||||
struct usb_gadget_driver *driver; /* 3rd party gadget driver */
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* REGISTERS
|
||||
*****************************************************************************/
|
||||
/* register size */
|
||||
#define REG_BITS (32)
|
||||
|
||||
/* HCCPARAMS */
|
||||
#define HCCPARAMS_LEN BIT(17)
|
||||
|
||||
/* DCCPARAMS */
|
||||
#define DCCPARAMS_DEN (0x1F << 0)
|
||||
#define DCCPARAMS_DC BIT(7)
|
||||
|
||||
/* TESTMODE */
|
||||
#define TESTMODE_FORCE BIT(0)
|
||||
|
||||
/* USBCMD */
|
||||
#define USBCMD_RS BIT(0)
|
||||
#define USBCMD_RST BIT(1)
|
||||
#define USBCMD_SUTW BIT(13)
|
||||
|
||||
/* USBSTS & USBINTR */
|
||||
#define USBi_UI BIT(0)
|
||||
#define USBi_UEI BIT(1)
|
||||
#define USBi_PCI BIT(2)
|
||||
#define USBi_URI BIT(6)
|
||||
#define USBi_SLI BIT(8)
|
||||
|
||||
/* DEVICEADDR */
|
||||
#define DEVICEADDR_USBADRA BIT(24)
|
||||
#define DEVICEADDR_USBADR (0x7FUL << 25)
|
||||
|
||||
/* PORTSC */
|
||||
#define PORTSC_SUSP BIT(7)
|
||||
#define PORTSC_HSP BIT(9)
|
||||
#define PORTSC_PTC (0x0FUL << 16)
|
||||
|
||||
/* DEVLC */
|
||||
#define DEVLC_PSPD (0x03UL << 25)
|
||||
#define DEVLC_PSPD_HS (0x02UL << 25)
|
||||
|
||||
/* USBMODE */
|
||||
#define USBMODE_CM (0x03UL << 0)
|
||||
#define USBMODE_CM_IDLE (0x00UL << 0)
|
||||
#define USBMODE_CM_DEVICE (0x02UL << 0)
|
||||
#define USBMODE_CM_HOST (0x03UL << 0)
|
||||
#define USBMODE_SLOM BIT(3)
|
||||
|
||||
/* ENDPTCTRL */
|
||||
#define ENDPTCTRL_RXS BIT(0)
|
||||
#define ENDPTCTRL_RXT (0x03UL << 2)
|
||||
#define ENDPTCTRL_RXR BIT(6) /* reserved for port 0 */
|
||||
#define ENDPTCTRL_RXE BIT(7)
|
||||
#define ENDPTCTRL_TXS BIT(16)
|
||||
#define ENDPTCTRL_TXT (0x03UL << 18)
|
||||
#define ENDPTCTRL_TXR BIT(22) /* reserved for port 0 */
|
||||
#define ENDPTCTRL_TXE BIT(23)
|
||||
|
||||
/******************************************************************************
|
||||
* LOGGING
|
||||
*****************************************************************************/
|
||||
#define ci13xxx_printk(level, format, args...) \
|
||||
do { \
|
||||
if (_udc == NULL) \
|
||||
printk(level "[%s] " format "\n", __func__, ## args); \
|
||||
else \
|
||||
dev_printk(level, _udc->gadget.dev.parent, \
|
||||
"[%s] " format "\n", __func__, ## args); \
|
||||
} while (0)
|
||||
|
||||
#define err(format, args...) ci13xxx_printk(KERN_ERR, format, ## args)
|
||||
#define warn(format, args...) ci13xxx_printk(KERN_WARNING, format, ## args)
|
||||
#define info(format, args...) ci13xxx_printk(KERN_INFO, format, ## args)
|
||||
|
||||
#ifdef TRACE
|
||||
#define trace(format, args...) ci13xxx_printk(KERN_DEBUG, format, ## args)
|
||||
#define dbg_trace(format, args...) dev_dbg(dev, format, ##args)
|
||||
#else
|
||||
#define trace(format, args...) do {} while (0)
|
||||
#define dbg_trace(format, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* _CI13XXX_h_ */
|
@@ -161,7 +161,7 @@ ep_matches (
|
||||
/* report address */
|
||||
desc->bEndpointAddress &= USB_DIR_IN;
|
||||
if (isdigit (ep->name [2])) {
|
||||
u8 num = simple_strtol (&ep->name [2], NULL, 10);
|
||||
u8 num = simple_strtoul (&ep->name [2], NULL, 10);
|
||||
desc->bEndpointAddress |= num;
|
||||
#ifdef MANY_ENDPOINTS
|
||||
} else if (desc->bEndpointAddress & USB_DIR_IN) {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* file_storage.c -- File-backed USB Storage Gadget, for USB development
|
||||
*
|
||||
* Copyright (C) 2003-2007 Alan Stern
|
||||
* Copyright (C) 2003-2008 Alan Stern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -38,16 +38,17 @@
|
||||
|
||||
/*
|
||||
* The File-backed Storage Gadget acts as a USB Mass Storage device,
|
||||
* appearing to the host as a disk drive. In addition to providing an
|
||||
* example of a genuinely useful gadget driver for a USB device, it also
|
||||
* illustrates a technique of double-buffering for increased throughput.
|
||||
* Last but not least, it gives an easy way to probe the behavior of the
|
||||
* Mass Storage drivers in a USB host.
|
||||
* appearing to the host as a disk drive or as a CD-ROM drive. In addition
|
||||
* to providing an example of a genuinely useful gadget driver for a USB
|
||||
* device, it also illustrates a technique of double-buffering for increased
|
||||
* throughput. Last but not least, it gives an easy way to probe the
|
||||
* behavior of the Mass Storage drivers in a USB host.
|
||||
*
|
||||
* Backing storage is provided by a regular file or a block device, specified
|
||||
* by the "file" module parameter. Access can be limited to read-only by
|
||||
* setting the optional "ro" module parameter. The gadget will indicate that
|
||||
* it has removable media if the optional "removable" module parameter is set.
|
||||
* setting the optional "ro" module parameter. (For CD-ROM emulation,
|
||||
* access is always read-only.) The gadget will indicate that it has
|
||||
* removable media if the optional "removable" module parameter is set.
|
||||
*
|
||||
* The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
|
||||
* and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
|
||||
@@ -64,7 +65,12 @@
|
||||
* The default number of LUNs is taken from the number of "file" elements;
|
||||
* it is 1 if "file" is not given. If "removable" is not set then a backing
|
||||
* file must be specified for each LUN. If it is set, then an unspecified
|
||||
* or empty backing filename means the LUN's medium is not loaded.
|
||||
* or empty backing filename means the LUN's medium is not loaded. Ideally
|
||||
* each LUN would be settable independently as a disk drive or a CD-ROM
|
||||
* drive, but currently all LUNs have to be the same type. The CD-ROM
|
||||
* emulation includes a single data track and no audio tracks; hence there
|
||||
* need be only one backing file per LUN. Note also that the CD-ROM block
|
||||
* length is set to 512 rather than the more common value 2048.
|
||||
*
|
||||
* Requirements are modest; only a bulk-in and a bulk-out endpoint are
|
||||
* needed (an interrupt-out endpoint is also needed for CBI). The memory
|
||||
@@ -91,6 +97,8 @@
|
||||
* USB device controller (usually true),
|
||||
* boolean to permit the driver to halt
|
||||
* bulk endpoints
|
||||
* cdrom Default false, boolean for whether to emulate
|
||||
* a CD-ROM drive
|
||||
* transport=XXX Default BBB, transport name (CB, CBI, or BBB)
|
||||
* protocol=YYY Default SCSI, protocol name (RBC, 8020 or
|
||||
* ATAPI, QIC, UFI, 8070, or SCSI;
|
||||
@@ -103,15 +111,16 @@
|
||||
* PAGE_CACHE_SIZE)
|
||||
*
|
||||
* If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
|
||||
* "removable", "luns", and "stall" options are available; default values
|
||||
* are used for everything else.
|
||||
* "removable", "luns", "stall", and "cdrom" options are available; default
|
||||
* values are used for everything else.
|
||||
*
|
||||
* The pathnames of the backing files and the ro settings are available in
|
||||
* the attribute files "file" and "ro" in the lun<n> subdirectory of the
|
||||
* gadget's sysfs directory. If the "removable" option is set, writing to
|
||||
* these files will simulate ejecting/loading the medium (writing an empty
|
||||
* line means eject) and adjusting a write-enable tab. Changes to the ro
|
||||
* setting are not allowed when the medium is loaded.
|
||||
* setting are not allowed when the medium is loaded or if CD-ROM emulation
|
||||
* is being used.
|
||||
*
|
||||
* This gadget driver is heavily based on "Gadget Zero" by David Brownell.
|
||||
* The driver's SCSI command interface was based on the "Information
|
||||
@@ -261,7 +270,7 @@
|
||||
|
||||
#define DRIVER_DESC "File-backed Storage Gadget"
|
||||
#define DRIVER_NAME "g_file_storage"
|
||||
#define DRIVER_VERSION "7 August 2007"
|
||||
#define DRIVER_VERSION "20 November 2008"
|
||||
|
||||
static const char longname[] = DRIVER_DESC;
|
||||
static const char shortname[] = DRIVER_NAME;
|
||||
@@ -341,6 +350,7 @@ static struct {
|
||||
|
||||
int removable;
|
||||
int can_stall;
|
||||
int cdrom;
|
||||
|
||||
char *transport_parm;
|
||||
char *protocol_parm;
|
||||
@@ -359,6 +369,7 @@ static struct {
|
||||
.protocol_parm = "SCSI",
|
||||
.removable = 0,
|
||||
.can_stall = 1,
|
||||
.cdrom = 0,
|
||||
.vendor = DRIVER_VENDOR_ID,
|
||||
.product = DRIVER_PRODUCT_ID,
|
||||
.release = 0xffff, // Use controller chip type
|
||||
@@ -382,6 +393,9 @@ MODULE_PARM_DESC(removable, "true to simulate removable media");
|
||||
module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
|
||||
|
||||
module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
|
||||
|
||||
|
||||
/* In the non-TEST version, only the module parameters listed above
|
||||
* are available. */
|
||||
@@ -411,6 +425,10 @@ MODULE_PARM_DESC(buflen, "I/O buffer size");
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* SCSI device types */
|
||||
#define TYPE_DISK 0x00
|
||||
#define TYPE_CDROM 0x05
|
||||
|
||||
/* USB protocol value = the transport method */
|
||||
#define USB_PR_CBI 0x00 // Control/Bulk/Interrupt
|
||||
#define USB_PR_CB 0x01 // Control/Bulk w/o interrupt
|
||||
@@ -487,6 +505,8 @@ struct interrupt_data {
|
||||
#define SC_READ_12 0xa8
|
||||
#define SC_READ_CAPACITY 0x25
|
||||
#define SC_READ_FORMAT_CAPACITIES 0x23
|
||||
#define SC_READ_HEADER 0x44
|
||||
#define SC_READ_TOC 0x43
|
||||
#define SC_RELEASE 0x17
|
||||
#define SC_REQUEST_SENSE 0x03
|
||||
#define SC_RESERVE 0x16
|
||||
@@ -2006,23 +2026,28 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
|
||||
u8 *buf = (u8 *) bh->buf;
|
||||
|
||||
static char vendor_id[] = "Linux ";
|
||||
static char product_id[] = "File-Stor Gadget";
|
||||
static char product_disk_id[] = "File-Stor Gadget";
|
||||
static char product_cdrom_id[] = "File-CD Gadget ";
|
||||
|
||||
if (!fsg->curlun) { // Unsupported LUNs are okay
|
||||
fsg->bad_lun_okay = 1;
|
||||
memset(buf, 0, 36);
|
||||
buf[0] = 0x7f; // Unsupported, no device-type
|
||||
buf[4] = 31; // Additional length
|
||||
return 36;
|
||||
}
|
||||
|
||||
memset(buf, 0, 8); // Non-removable, direct-access device
|
||||
memset(buf, 0, 8);
|
||||
buf[0] = (mod_data.cdrom ? TYPE_CDROM : TYPE_DISK);
|
||||
if (mod_data.removable)
|
||||
buf[1] = 0x80;
|
||||
buf[2] = 2; // ANSI SCSI level 2
|
||||
buf[3] = 2; // SCSI-2 INQUIRY data format
|
||||
buf[4] = 31; // Additional length
|
||||
// No special options
|
||||
sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, product_id,
|
||||
sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,
|
||||
(mod_data.cdrom ? product_cdrom_id :
|
||||
product_disk_id),
|
||||
mod_data.release);
|
||||
return 36;
|
||||
}
|
||||
@@ -2101,6 +2126,75 @@ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
|
||||
}
|
||||
|
||||
|
||||
static void store_cdrom_address(u8 *dest, int msf, u32 addr)
|
||||
{
|
||||
if (msf) {
|
||||
/* Convert to Minutes-Seconds-Frames */
|
||||
addr >>= 2; /* Convert to 2048-byte frames */
|
||||
addr += 2*75; /* Lead-in occupies 2 seconds */
|
||||
dest[3] = addr % 75; /* Frames */
|
||||
addr /= 75;
|
||||
dest[2] = addr % 60; /* Seconds */
|
||||
addr /= 60;
|
||||
dest[1] = addr; /* Minutes */
|
||||
dest[0] = 0; /* Reserved */
|
||||
} else {
|
||||
/* Absolute sector */
|
||||
put_be32(dest, addr);
|
||||
}
|
||||
}
|
||||
|
||||
static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
|
||||
{
|
||||
struct lun *curlun = fsg->curlun;
|
||||
int msf = fsg->cmnd[1] & 0x02;
|
||||
u32 lba = get_be32(&fsg->cmnd[2]);
|
||||
u8 *buf = (u8 *) bh->buf;
|
||||
|
||||
if ((fsg->cmnd[1] & ~0x02) != 0) { /* Mask away MSF */
|
||||
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
return -EINVAL;
|
||||
}
|
||||
if (lba >= curlun->num_sectors) {
|
||||
curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(buf, 0, 8);
|
||||
buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */
|
||||
store_cdrom_address(&buf[4], msf, lba);
|
||||
return 8;
|
||||
}
|
||||
|
||||
|
||||
static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
|
||||
{
|
||||
struct lun *curlun = fsg->curlun;
|
||||
int msf = fsg->cmnd[1] & 0x02;
|
||||
int start_track = fsg->cmnd[6];
|
||||
u8 *buf = (u8 *) bh->buf;
|
||||
|
||||
if ((fsg->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */
|
||||
start_track > 1) {
|
||||
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(buf, 0, 20);
|
||||
buf[1] = (20-2); /* TOC data length */
|
||||
buf[2] = 1; /* First track number */
|
||||
buf[3] = 1; /* Last track number */
|
||||
buf[5] = 0x16; /* Data track, copying allowed */
|
||||
buf[6] = 0x01; /* Only track is number 1 */
|
||||
store_cdrom_address(&buf[8], msf, 0);
|
||||
|
||||
buf[13] = 0x16; /* Lead-out track is data */
|
||||
buf[14] = 0xAA; /* Lead-out track number */
|
||||
store_cdrom_address(&buf[16], msf, curlun->num_sectors);
|
||||
return 20;
|
||||
}
|
||||
|
||||
|
||||
static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
|
||||
{
|
||||
struct lun *curlun = fsg->curlun;
|
||||
@@ -2848,6 +2942,26 @@ static int do_scsi_command(struct fsg_dev *fsg)
|
||||
reply = do_read_capacity(fsg, bh);
|
||||
break;
|
||||
|
||||
case SC_READ_HEADER:
|
||||
if (!mod_data.cdrom)
|
||||
goto unknown_cmnd;
|
||||
fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
|
||||
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
|
||||
(3<<7) | (0x1f<<1), 1,
|
||||
"READ HEADER")) == 0)
|
||||
reply = do_read_header(fsg, bh);
|
||||
break;
|
||||
|
||||
case SC_READ_TOC:
|
||||
if (!mod_data.cdrom)
|
||||
goto unknown_cmnd;
|
||||
fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
|
||||
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
|
||||
(7<<6) | (1<<1), 1,
|
||||
"READ TOC")) == 0)
|
||||
reply = do_read_toc(fsg, bh);
|
||||
break;
|
||||
|
||||
case SC_READ_FORMAT_CAPACITIES:
|
||||
fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
|
||||
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
|
||||
@@ -2933,6 +3047,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
|
||||
// Fall through
|
||||
|
||||
default:
|
||||
unknown_cmnd:
|
||||
fsg->data_size_from_cmnd = 0;
|
||||
sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
|
||||
if ((reply = check_command(fsg, fsg->cmnd_size,
|
||||
@@ -3498,6 +3613,7 @@ static int open_backing_file(struct lun *curlun, const char *filename)
|
||||
struct inode *inode = NULL;
|
||||
loff_t size;
|
||||
loff_t num_sectors;
|
||||
loff_t min_sectors;
|
||||
|
||||
/* R/W if we can, R/O if we must */
|
||||
ro = curlun->ro;
|
||||
@@ -3541,8 +3657,19 @@ static int open_backing_file(struct lun *curlun, const char *filename)
|
||||
rc = (int) size;
|
||||
goto out;
|
||||
}
|
||||
num_sectors = size >> 9; // File size in 512-byte sectors
|
||||
if (num_sectors == 0) {
|
||||
num_sectors = size >> 9; // File size in 512-byte blocks
|
||||
min_sectors = 1;
|
||||
if (mod_data.cdrom) {
|
||||
num_sectors &= ~3; // Reduce to a multiple of 2048
|
||||
min_sectors = 300*4; // Smallest track is 300 frames
|
||||
if (num_sectors >= 256*60*75*4) {
|
||||
num_sectors = (256*60*75 - 1) * 4;
|
||||
LINFO(curlun, "file too big: %s\n", filename);
|
||||
LINFO(curlun, "using only first %d blocks\n",
|
||||
(int) num_sectors);
|
||||
}
|
||||
}
|
||||
if (num_sectors < min_sectors) {
|
||||
LINFO(curlun, "file too small: %s\n", filename);
|
||||
rc = -ETOOSMALL;
|
||||
goto out;
|
||||
@@ -3845,9 +3972,12 @@ static int __init fsg_bind(struct usb_gadget *gadget)
|
||||
goto out;
|
||||
|
||||
if (mod_data.removable) { // Enable the store_xxx attributes
|
||||
dev_attr_ro.attr.mode = dev_attr_file.attr.mode = 0644;
|
||||
dev_attr_ro.store = store_ro;
|
||||
dev_attr_file.attr.mode = 0644;
|
||||
dev_attr_file.store = store_file;
|
||||
if (!mod_data.cdrom) {
|
||||
dev_attr_ro.attr.mode = 0644;
|
||||
dev_attr_ro.store = store_ro;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find out how many LUNs there should be */
|
||||
@@ -3872,6 +4002,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
|
||||
for (i = 0; i < fsg->nluns; ++i) {
|
||||
curlun = &fsg->luns[i];
|
||||
curlun->ro = mod_data.ro[i];
|
||||
if (mod_data.cdrom)
|
||||
curlun->ro = 1;
|
||||
curlun->dev.release = lun_release;
|
||||
curlun->dev.parent = &gadget->dev;
|
||||
curlun->dev.driver = &fsg_driver.driver;
|
||||
@@ -4031,9 +4163,9 @@ static int __init fsg_bind(struct usb_gadget *gadget)
|
||||
mod_data.protocol_name, mod_data.protocol_type);
|
||||
DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
|
||||
mod_data.vendor, mod_data.product, mod_data.release);
|
||||
DBG(fsg, "removable=%d, stall=%d, buflen=%u\n",
|
||||
DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",
|
||||
mod_data.removable, mod_data.can_stall,
|
||||
mod_data.buflen);
|
||||
mod_data.cdrom, mod_data.buflen);
|
||||
DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
|
||||
|
||||
set_bit(REGISTERED, &fsg->atomic_bitflags);
|
||||
@@ -4050,6 +4182,7 @@ out:
|
||||
fsg->state = FSG_STATE_TERMINATED; // The thread is dead
|
||||
fsg_unbind(gadget);
|
||||
close_all_backing_files(fsg);
|
||||
complete(&fsg->thread_notifier);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
@@ -370,6 +371,9 @@ static int qe_ep_bd_init(struct qe_udc *udc, unsigned char pipe_num)
|
||||
/* alloc multi-ram for BD rings and set the ep parameters */
|
||||
tmp_addr = cpm_muram_alloc(sizeof(struct qe_bd) * (bdring_len +
|
||||
USB_BDRING_LEN_TX), QE_ALIGNMENT_OF_BD);
|
||||
if (IS_ERR_VALUE(tmp_addr))
|
||||
return -ENOMEM;
|
||||
|
||||
out_be16(&epparam->rbase, (u16)tmp_addr);
|
||||
out_be16(&epparam->tbase, (u16)(tmp_addr +
|
||||
(sizeof(struct qe_bd) * bdring_len)));
|
||||
@@ -689,7 +693,7 @@ en_done2:
|
||||
en_done1:
|
||||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
en_done:
|
||||
dev_dbg(udc->dev, "failed to initialize %s\n", ep->ep.name);
|
||||
dev_err(udc->dev, "failed to initialize %s\n", ep->ep.name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -2408,6 +2412,8 @@ static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev)
|
||||
tmp_addr = cpm_muram_alloc((USB_MAX_ENDPOINTS *
|
||||
sizeof(struct usb_ep_para)),
|
||||
USB_EP_PARA_ALIGNMENT);
|
||||
if (IS_ERR_VALUE(tmp_addr))
|
||||
goto cleanup;
|
||||
|
||||
for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
|
||||
out_be16(&usbpram->epptr[i], (u16)tmp_addr);
|
||||
@@ -2513,7 +2519,7 @@ static int __devinit qe_udc_probe(struct of_device *ofdev,
|
||||
/* Initialize the udc structure including QH member and other member */
|
||||
udc_controller = qe_udc_config(ofdev);
|
||||
if (!udc_controller) {
|
||||
dev_dbg(&ofdev->dev, "udc_controll is NULL\n");
|
||||
dev_err(&ofdev->dev, "failed to initialize\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -2545,7 +2551,7 @@ static int __devinit qe_udc_probe(struct of_device *ofdev,
|
||||
|
||||
device_initialize(&udc_controller->gadget.dev);
|
||||
|
||||
strcpy(udc_controller->gadget.dev.bus_id, "gadget");
|
||||
dev_set_name(&udc_controller->gadget.dev, "gadget");
|
||||
|
||||
udc_controller->gadget.dev.release = qe_udc_release;
|
||||
udc_controller->gadget.dev.parent = &ofdev->dev;
|
||||
@@ -2568,7 +2574,7 @@ static int __devinit qe_udc_probe(struct of_device *ofdev,
|
||||
/* create a buf for ZLP send, need to remain zeroed */
|
||||
udc_controller->nullbuf = kzalloc(256, GFP_KERNEL);
|
||||
if (udc_controller->nullbuf == NULL) {
|
||||
dev_dbg(udc_controller->dev, "cannot alloc nullbuf\n");
|
||||
dev_err(udc_controller->dev, "cannot alloc nullbuf\n");
|
||||
ret = -ENOMEM;
|
||||
goto err3;
|
||||
}
|
||||
|
@@ -110,7 +110,6 @@
|
||||
#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
|
||||
@@ -158,6 +157,11 @@
|
||||
#define gadget_is_fsl_qe(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_CI13XXX
|
||||
#define gadget_is_ci13xxx(g) (!strcmp("ci13xxx_udc", (g)->name))
|
||||
#else
|
||||
#define gadget_is_ci13xxx(g) 0
|
||||
#endif
|
||||
|
||||
// CONFIG_USB_GADGET_SX2
|
||||
// CONFIG_USB_GADGET_AU1X00
|
||||
@@ -225,6 +229,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
|
||||
return 0x21;
|
||||
else if (gadget_is_fsl_qe(gadget))
|
||||
return 0x22;
|
||||
else if (gadget_is_ci13xxx(gadget))
|
||||
return 0x23;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
@@ -1349,7 +1349,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
|
||||
int retval;
|
||||
|
||||
if (!driver
|
||||
|| driver->speed != USB_SPEED_FULL
|
||||
|| driver->speed < USB_SPEED_FULL
|
||||
|| !driver->bind
|
||||
|| !driver->disconnect
|
||||
|| !driver->setup)
|
||||
|
1516
drivers/usb/gadget/imx_udc.c
Normal file
1516
drivers/usb/gadget/imx_udc.c
Normal file
File diff suppressed because it is too large
Load Diff
344
drivers/usb/gadget/imx_udc.h
Normal file
344
drivers/usb/gadget/imx_udc.h
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Mike Lee(eemike@gmail.com)
|
||||
*
|
||||
* This udc driver is now under testing and code is based on pxa2xx_udc.h
|
||||
* Please use it with your own risk!
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_GADGET_IMX_H
|
||||
#define __LINUX_USB_GADGET_IMX_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Helper macros */
|
||||
#define EP_NO(ep) ((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */
|
||||
#define EP_DIR(ep) ((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0)
|
||||
#define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/
|
||||
#define ep_to_irq(ep) (EP_NO((ep)) + USBD_INT0)
|
||||
#define IMX_USB_NB_EP 6
|
||||
|
||||
/* Driver structures */
|
||||
struct imx_request {
|
||||
struct usb_request req;
|
||||
struct list_head queue;
|
||||
unsigned int in_use;
|
||||
};
|
||||
|
||||
enum ep0_state {
|
||||
EP0_IDLE,
|
||||
EP0_IN_DATA_PHASE,
|
||||
EP0_OUT_DATA_PHASE,
|
||||
EP0_CONFIG,
|
||||
EP0_STALL,
|
||||
};
|
||||
|
||||
struct imx_ep_struct {
|
||||
struct usb_ep ep;
|
||||
struct imx_udc_struct *imx_usb;
|
||||
struct list_head queue;
|
||||
unsigned char stopped;
|
||||
unsigned char fifosize;
|
||||
unsigned char bEndpointAddress;
|
||||
unsigned char bmAttributes;
|
||||
};
|
||||
|
||||
struct imx_udc_struct {
|
||||
struct usb_gadget gadget;
|
||||
struct usb_gadget_driver *driver;
|
||||
struct device *dev;
|
||||
struct imx_ep_struct imx_ep[IMX_USB_NB_EP];
|
||||
struct clk *clk;
|
||||
enum ep0_state ep0state;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
unsigned char set_config;
|
||||
int cfg,
|
||||
intf,
|
||||
alt,
|
||||
usbd_int[7];
|
||||
};
|
||||
|
||||
/* USB registers */
|
||||
#define USB_FRAME (0x00) /* USB frame */
|
||||
#define USB_SPEC (0x04) /* USB Spec */
|
||||
#define USB_STAT (0x08) /* USB Status */
|
||||
#define USB_CTRL (0x0C) /* USB Control */
|
||||
#define USB_DADR (0x10) /* USB Desc RAM addr */
|
||||
#define USB_DDAT (0x14) /* USB Desc RAM/EP buffer data */
|
||||
#define USB_INTR (0x18) /* USB interrupt */
|
||||
#define USB_MASK (0x1C) /* USB Mask */
|
||||
#define USB_ENAB (0x24) /* USB Enable */
|
||||
#define USB_EP_STAT(x) (0x30 + (x*0x30)) /* USB status/control */
|
||||
#define USB_EP_INTR(x) (0x34 + (x*0x30)) /* USB interrupt */
|
||||
#define USB_EP_MASK(x) (0x38 + (x*0x30)) /* USB mask */
|
||||
#define USB_EP_FDAT(x) (0x3C + (x*0x30)) /* USB FIFO data */
|
||||
#define USB_EP_FDAT0(x) (0x3C + (x*0x30)) /* USB FIFO data */
|
||||
#define USB_EP_FDAT1(x) (0x3D + (x*0x30)) /* USB FIFO data */
|
||||
#define USB_EP_FDAT2(x) (0x3E + (x*0x30)) /* USB FIFO data */
|
||||
#define USB_EP_FDAT3(x) (0x3F + (x*0x30)) /* USB FIFO data */
|
||||
#define USB_EP_FSTAT(x) (0x40 + (x*0x30)) /* USB FIFO status */
|
||||
#define USB_EP_FCTRL(x) (0x44 + (x*0x30)) /* USB FIFO control */
|
||||
#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last read frame pointer */
|
||||
#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last write frame pointer */
|
||||
#define USB_EP_FALRM(x) (0x50 + (x*0x30)) /* USB FIFO alarm */
|
||||
#define USB_EP_FRDP(x) (0x54 + (x*0x30)) /* USB FIFO read pointer */
|
||||
#define USB_EP_FWRP(x) (0x58 + (x*0x30)) /* USB FIFO write pointer */
|
||||
/* USB Control Register Bit Fields.*/
|
||||
#define CTRL_CMDOVER (1<<6) /* UDC status */
|
||||
#define CTRL_CMDERROR (1<<5) /* UDC status */
|
||||
#define CTRL_FE_ENA (1<<3) /* Enable Font End logic */
|
||||
#define CTRL_UDC_RST (1<<2) /* UDC reset */
|
||||
#define CTRL_AFE_ENA (1<<1) /* Analog Font end enable */
|
||||
#define CTRL_RESUME (1<<0) /* UDC resume */
|
||||
/* USB Status Register Bit Fields.*/
|
||||
#define STAT_RST (1<<8)
|
||||
#define STAT_SUSP (1<<7)
|
||||
#define STAT_CFG (3<<5)
|
||||
#define STAT_INTF (3<<3)
|
||||
#define STAT_ALTSET (7<<0)
|
||||
/* USB Interrupt Status/Mask Registers Bit fields */
|
||||
#define INTR_WAKEUP (1<<31) /* Wake up Interrupt */
|
||||
#define INTR_MSOF (1<<7) /* Missed Start of Frame */
|
||||
#define INTR_SOF (1<<6) /* Start of Frame */
|
||||
#define INTR_RESET_STOP (1<<5) /* Reset Signaling stop */
|
||||
#define INTR_RESET_START (1<<4) /* Reset Signaling start */
|
||||
#define INTR_RESUME (1<<3) /* Suspend to resume */
|
||||
#define INTR_SUSPEND (1<<2) /* Active to suspend */
|
||||
#define INTR_FRAME_MATCH (1<<1) /* Frame matched */
|
||||
#define INTR_CFG_CHG (1<<0) /* Configuration change occurred */
|
||||
/* USB Enable Register Bit Fields.*/
|
||||
#define ENAB_RST (1<<31) /* Reset USB modules */
|
||||
#define ENAB_ENAB (1<<30) /* Enable USB modules*/
|
||||
#define ENAB_SUSPEND (1<<29) /* Suspend USB modules */
|
||||
#define ENAB_ENDIAN (1<<28) /* Endian of USB modules */
|
||||
#define ENAB_PWRMD (1<<0) /* Power mode of USB modules */
|
||||
/* USB Descriptor Ram Address Register bit fields */
|
||||
#define DADR_CFG (1<<31) /* Configuration */
|
||||
#define DADR_BSY (1<<30) /* Busy status */
|
||||
#define DADR_DADR (0x1FF) /* Descriptor Ram Address */
|
||||
/* USB Descriptor RAM/Endpoint Buffer Data Register bit fields */
|
||||
#define DDAT_DDAT (0xFF) /* Descriptor Endpoint Buffer */
|
||||
/* USB Endpoint Status Register bit fields */
|
||||
#define EPSTAT_BCOUNT (0x7F<<16) /* Endpoint FIFO byte count */
|
||||
#define EPSTAT_SIP (1<<8) /* Endpoint setup in progress */
|
||||
#define EPSTAT_DIR (1<<7) /* Endpoint transfer direction */
|
||||
#define EPSTAT_MAX (3<<5) /* Endpoint Max packet size */
|
||||
#define EPSTAT_TYP (3<<3) /* Endpoint type */
|
||||
#define EPSTAT_ZLPS (1<<2) /* Send zero length packet */
|
||||
#define EPSTAT_FLUSH (1<<1) /* Endpoint FIFO Flush */
|
||||
#define EPSTAT_STALL (1<<0) /* Force stall */
|
||||
/* USB Endpoint FIFO Status Register bit fields */
|
||||
#define FSTAT_FRAME_STAT (0xF<<24) /* Frame status bit [0-3] */
|
||||
#define FSTAT_ERR (1<<22) /* FIFO error */
|
||||
#define FSTAT_UF (1<<21) /* FIFO underflow */
|
||||
#define FSTAT_OF (1<<20) /* FIFO overflow */
|
||||
#define FSTAT_FR (1<<19) /* FIFO frame ready */
|
||||
#define FSTAT_FULL (1<<18) /* FIFO full */
|
||||
#define FSTAT_ALRM (1<<17) /* FIFO alarm */
|
||||
#define FSTAT_EMPTY (1<<16) /* FIFO empty */
|
||||
/* USB Endpoint FIFO Control Register bit fields */
|
||||
#define FCTRL_WFR (1<<29) /* Write frame end */
|
||||
/* USB Endpoint Interrupt Status Regsiter bit fields */
|
||||
#define EPINTR_FIFO_FULL (1<<8) /* fifo full */
|
||||
#define EPINTR_FIFO_EMPTY (1<<7) /* fifo empty */
|
||||
#define EPINTR_FIFO_ERROR (1<<6) /* fifo error */
|
||||
#define EPINTR_FIFO_HIGH (1<<5) /* fifo high */
|
||||
#define EPINTR_FIFO_LOW (1<<4) /* fifo low */
|
||||
#define EPINTR_MDEVREQ (1<<3) /* multi Device request */
|
||||
#define EPINTR_EOT (1<<2) /* fifo end of transfer */
|
||||
#define EPINTR_DEVREQ (1<<1) /* Device request */
|
||||
#define EPINTR_EOF (1<<0) /* fifo end of frame */
|
||||
|
||||
/* Debug macros */
|
||||
#ifdef DEBUG
|
||||
|
||||
/* #define DEBUG_REQ */
|
||||
/* #define DEBUG_TRX */
|
||||
/* #define DEBUG_INIT */
|
||||
/* #define DEBUG_EP0 */
|
||||
/* #define DEBUG_EPX */
|
||||
/* #define DEBUG_IRQ */
|
||||
/* #define DEBUG_EPIRQ */
|
||||
/* #define DEBUG_DUMP */
|
||||
#define DEBUG_ERR
|
||||
|
||||
#ifdef DEBUG_REQ
|
||||
#define D_REQ(dev, args...) dev_dbg(dev, ## args)
|
||||
#else
|
||||
#define D_REQ(dev, args...) do {} while (0)
|
||||
#endif /* DEBUG_REQ */
|
||||
|
||||
#ifdef DEBUG_TRX
|
||||
#define D_TRX(dev, args...) dev_dbg(dev, ## args)
|
||||
#else
|
||||
#define D_TRX(dev, args...) do {} while (0)
|
||||
#endif /* DEBUG_TRX */
|
||||
|
||||
#ifdef DEBUG_INIT
|
||||
#define D_INI(dev, args...) dev_dbg(dev, ## args)
|
||||
#else
|
||||
#define D_INI(dev, args...) do {} while (0)
|
||||
#endif /* DEBUG_INIT */
|
||||
|
||||
#ifdef DEBUG_EP0
|
||||
static const char *state_name[] = {
|
||||
"EP0_IDLE",
|
||||
"EP0_IN_DATA_PHASE",
|
||||
"EP0_OUT_DATA_PHASE",
|
||||
"EP0_CONFIG",
|
||||
"EP0_STALL"
|
||||
};
|
||||
#define D_EP0(dev, args...) dev_dbg(dev, ## args)
|
||||
#else
|
||||
#define D_EP0(dev, args...) do {} while (0)
|
||||
#endif /* DEBUG_EP0 */
|
||||
|
||||
#ifdef DEBUG_EPX
|
||||
#define D_EPX(dev, args...) dev_dbg(dev, ## args)
|
||||
#else
|
||||
#define D_EPX(dev, args...) do {} while (0)
|
||||
#endif /* DEBUG_EP0 */
|
||||
|
||||
#ifdef DEBUG_IRQ
|
||||
static void dump_intr(const char *label, int irqreg, struct device *dev)
|
||||
{
|
||||
dev_dbg(dev, "<%s> USB_INTR=[%s%s%s%s%s%s%s%s%s]\n", label,
|
||||
(irqreg & INTR_WAKEUP) ? " wake" : "",
|
||||
(irqreg & INTR_MSOF) ? " msof" : "",
|
||||
(irqreg & INTR_SOF) ? " sof" : "",
|
||||
(irqreg & INTR_RESUME) ? " resume" : "",
|
||||
(irqreg & INTR_SUSPEND) ? " suspend" : "",
|
||||
(irqreg & INTR_RESET_STOP) ? " noreset" : "",
|
||||
(irqreg & INTR_RESET_START) ? " reset" : "",
|
||||
(irqreg & INTR_FRAME_MATCH) ? " fmatch" : "",
|
||||
(irqreg & INTR_CFG_CHG) ? " config" : "");
|
||||
}
|
||||
#else
|
||||
#define dump_intr(x, y, z) do {} while (0)
|
||||
#endif /* DEBUG_IRQ */
|
||||
|
||||
#ifdef DEBUG_EPIRQ
|
||||
static void dump_ep_intr(const char *label, int nr, int irqreg, struct device *dev)
|
||||
{
|
||||
dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr,
|
||||
(irqreg & EPINTR_FIFO_FULL) ? " full" : "",
|
||||
(irqreg & EPINTR_FIFO_EMPTY) ? " fempty" : "",
|
||||
(irqreg & EPINTR_FIFO_ERROR) ? " ferr" : "",
|
||||
(irqreg & EPINTR_FIFO_HIGH) ? " fhigh" : "",
|
||||
(irqreg & EPINTR_FIFO_LOW) ? " flow" : "",
|
||||
(irqreg & EPINTR_MDEVREQ) ? " mreq" : "",
|
||||
(irqreg & EPINTR_EOF) ? " eof" : "",
|
||||
(irqreg & EPINTR_DEVREQ) ? " devreq" : "",
|
||||
(irqreg & EPINTR_EOT) ? " eot" : "");
|
||||
}
|
||||
#else
|
||||
#define dump_ep_intr(x, y, z, i) do {} while (0)
|
||||
#endif /* DEBUG_IRQ */
|
||||
|
||||
#ifdef DEBUG_DUMP
|
||||
static void dump_usb_stat(const char *label, struct imx_udc_struct *imx_usb)
|
||||
{
|
||||
int temp = __raw_readl(imx_usb->base + USB_STAT);
|
||||
|
||||
dev_dbg(imx_usb->dev,
|
||||
"<%s> USB_STAT=[%s%s CFG=%d, INTF=%d, ALTR=%d]\n", label,
|
||||
(temp & STAT_RST) ? " reset" : "",
|
||||
(temp & STAT_SUSP) ? " suspend" : "",
|
||||
(temp & STAT_CFG) >> 5,
|
||||
(temp & STAT_INTF) >> 3,
|
||||
(temp & STAT_ALTSET));
|
||||
}
|
||||
|
||||
static void dump_ep_stat(const char *label, struct imx_ep_struct *imx_ep)
|
||||
{
|
||||
int temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
|
||||
|
||||
dev_dbg(imx_ep->imx_usb->dev,
|
||||
"<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep),
|
||||
(temp & EPINTR_FIFO_FULL) ? " full" : "",
|
||||
(temp & EPINTR_FIFO_EMPTY) ? " fempty" : "",
|
||||
(temp & EPINTR_FIFO_ERROR) ? " ferr" : "",
|
||||
(temp & EPINTR_FIFO_HIGH) ? " fhigh" : "",
|
||||
(temp & EPINTR_FIFO_LOW) ? " flow" : "",
|
||||
(temp & EPINTR_MDEVREQ) ? " mreq" : "",
|
||||
(temp & EPINTR_EOF) ? " eof" : "",
|
||||
(temp & EPINTR_DEVREQ) ? " devreq" : "",
|
||||
(temp & EPINTR_EOT) ? " eot" : "");
|
||||
|
||||
temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
|
||||
|
||||
dev_dbg(imx_ep->imx_usb->dev,
|
||||
"<%s> EP%d_STAT=[%s%s bcount=%d]\n", label, EP_NO(imx_ep),
|
||||
(temp & EPSTAT_SIP) ? " sip" : "",
|
||||
(temp & EPSTAT_STALL) ? " stall" : "",
|
||||
(temp & EPSTAT_BCOUNT) >> 16);
|
||||
|
||||
temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep)));
|
||||
|
||||
dev_dbg(imx_ep->imx_usb->dev,
|
||||
"<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep),
|
||||
(temp & FSTAT_ERR) ? " ferr" : "",
|
||||
(temp & FSTAT_UF) ? " funder" : "",
|
||||
(temp & FSTAT_OF) ? " fover" : "",
|
||||
(temp & FSTAT_FR) ? " fready" : "",
|
||||
(temp & FSTAT_FULL) ? " ffull" : "",
|
||||
(temp & FSTAT_ALRM) ? " falarm" : "",
|
||||
(temp & FSTAT_EMPTY) ? " fempty" : "");
|
||||
}
|
||||
|
||||
static void dump_req(const char *label, struct imx_ep_struct *imx_ep, struct usb_request *req)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!req || !req->buf) {
|
||||
dev_dbg(imx_ep->imx_usb->dev, "<%s> req or req buf is free\n", label);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE)
|
||||
|| (EP_NO(imx_ep) && EP_DIR(imx_ep))) {
|
||||
|
||||
dev_dbg(imx_ep->imx_usb->dev, "<%s> request dump <", label);
|
||||
for (i = 0; i < req->length; i++)
|
||||
printk("%02x-", *((u8 *)req->buf + i));
|
||||
printk(">\n");
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#define dump_ep_stat(x, y) do {} while (0)
|
||||
#define dump_usb_stat(x, y) do {} while (0)
|
||||
#define dump_req(x, y, z) do {} while (0)
|
||||
#endif /* DEBUG_DUMP */
|
||||
|
||||
#ifdef DEBUG_ERR
|
||||
#define D_ERR(dev, args...) dev_dbg(dev, ## args)
|
||||
#else
|
||||
#define D_ERR(dev, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define D_REQ(dev, args...) do {} while (0)
|
||||
#define D_TRX(dev, args...) do {} while (0)
|
||||
#define D_INI(dev, args...) do {} while (0)
|
||||
#define D_EP0(dev, args...) do {} while (0)
|
||||
#define D_EPX(dev, args...) do {} while (0)
|
||||
#define dump_ep_intr(x, y, z, i) do {} while (0)
|
||||
#define dump_intr(x, y, z) do {} while (0)
|
||||
#define dump_ep_stat(x, y) do {} while (0)
|
||||
#define dump_usb_stat(x, y) do {} while (0)
|
||||
#define dump_req(x, y, z) do {} while (0)
|
||||
#define D_ERR(dev, args...) do {} while (0)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#endif /* __LINUX_USB_GADGET_IMX_H */
|
@@ -1981,7 +1981,7 @@ static struct lh7a40x_udc memory = {
|
||||
.ep0 = &memory.ep[0].ep,
|
||||
.name = driver_name,
|
||||
.dev = {
|
||||
.bus_id = "gadget",
|
||||
.init_name = "gadget",
|
||||
.release = nop_release,
|
||||
},
|
||||
},
|
||||
|
@@ -1546,8 +1546,6 @@ static void nop_completion(struct usb_ep *ep, struct usb_request *r)
|
||||
{
|
||||
}
|
||||
|
||||
#define resource_len(r) (((r)->end - (r)->start) + 1)
|
||||
|
||||
static int __init m66592_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
@@ -1560,11 +1558,10 @@ static int __init m66592_probe(struct platform_device *pdev)
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
(char *)udc_name);
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -ENODEV;
|
||||
pr_err("platform_get_resource_byname error.\n");
|
||||
pr_err("platform_get_resource error.\n");
|
||||
goto clean_up;
|
||||
}
|
||||
|
||||
@@ -1575,7 +1572,7 @@ static int __init m66592_probe(struct platform_device *pdev)
|
||||
goto clean_up;
|
||||
}
|
||||
|
||||
reg = ioremap(res->start, resource_len(res));
|
||||
reg = ioremap(res->start, resource_size(res));
|
||||
if (reg == NULL) {
|
||||
ret = -ENOMEM;
|
||||
pr_err("ioremap error.\n");
|
||||
|
@@ -669,7 +669,7 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
|
||||
|
||||
/* 2280 may be polling VALID_BIT through ep->dma->dmadesc */
|
||||
wmb ();
|
||||
td->dmacount = cpu_to_le32p (&dmacount);
|
||||
td->dmacount = cpu_to_le32(dmacount);
|
||||
}
|
||||
|
||||
static const u32 dmactl_default =
|
||||
|
@@ -3006,7 +3006,7 @@ cleanup1:
|
||||
|
||||
cleanup0:
|
||||
if (xceiv)
|
||||
put_device(xceiv->dev);
|
||||
otg_put_transceiver(xceiv);
|
||||
|
||||
if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
|
||||
clk_disable(hhc_clk);
|
||||
@@ -3034,7 +3034,7 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
|
||||
|
||||
pullup_disable(udc);
|
||||
if (udc->transceiver) {
|
||||
put_device(udc->transceiver->dev);
|
||||
otg_put_transceiver(udc->transceiver);
|
||||
udc->transceiver = NULL;
|
||||
}
|
||||
omap_writew(0, UDC_SYSCON1);
|
||||
|
@@ -1833,7 +1833,7 @@ static struct pxa25x_udc memory = {
|
||||
.ep0 = &memory.ep[0].ep,
|
||||
.name = driver_name,
|
||||
.dev = {
|
||||
.bus_id = "gadget",
|
||||
.init_name = "gadget",
|
||||
.release = nop_release,
|
||||
},
|
||||
},
|
||||
@@ -2198,7 +2198,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
|
||||
udc_disable(dev);
|
||||
udc_reinit(dev);
|
||||
|
||||
dev->vbus = is_vbus_present();
|
||||
dev->vbus = !!is_vbus_present();
|
||||
|
||||
/* irq setup after old hardware state is cleaned up */
|
||||
retval = request_irq(irq, pxa25x_udc_irq,
|
||||
|
@@ -430,7 +430,6 @@ static void pio_irq_enable(struct pxa_ep *ep)
|
||||
/**
|
||||
* pio_irq_disable - Disables irq generation for one endpoint
|
||||
* @ep: udc endpoint
|
||||
* @index: endpoint number
|
||||
*/
|
||||
static void pio_irq_disable(struct pxa_ep *ep)
|
||||
{
|
||||
@@ -586,7 +585,6 @@ static void inc_ep_stats_reqs(struct pxa_ep *ep, int is_in)
|
||||
* inc_ep_stats_bytes - Update ep stats counts
|
||||
* @ep: physical endpoint
|
||||
* @count: bytes transfered on endpoint
|
||||
* @req: usb request
|
||||
* @is_in: ep direction (USB_DIR_IN or 0)
|
||||
*/
|
||||
static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)
|
||||
@@ -2162,7 +2160,7 @@ static struct pxa_udc memory = {
|
||||
.ep0 = &memory.udc_usb_ep[0].usb_ep,
|
||||
.name = driver_name,
|
||||
.dev = {
|
||||
.bus_id = "gadget",
|
||||
.init_name = "gadget",
|
||||
},
|
||||
},
|
||||
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
@@ -51,7 +52,6 @@
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/regs-gpio.h>
|
||||
|
||||
#include <plat/regs-udc.h>
|
||||
#include <plat/udc.h>
|
||||
@@ -1510,11 +1510,7 @@ static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev)
|
||||
|
||||
dprintk(DEBUG_NORMAL, "%s()\n", __func__);
|
||||
|
||||
/* some cpus cannot read from an line configured to IRQ! */
|
||||
s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_INPUT);
|
||||
value = s3c2410_gpio_getpin(udc_info->vbus_pin);
|
||||
s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_SFN2);
|
||||
|
||||
value = gpio_get_value(udc_info->vbus_pin) ? 1 : 0;
|
||||
if (udc_info->vbus_pin_inverted)
|
||||
value = !value;
|
||||
|
||||
@@ -1727,7 +1723,7 @@ static struct s3c2410_udc memory = {
|
||||
.ep0 = &memory.ep[0].ep,
|
||||
.name = gadget_name,
|
||||
.dev = {
|
||||
.bus_id = "gadget",
|
||||
.init_name = "gadget",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1802,7 +1798,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
|
||||
struct s3c2410_udc *udc = &memory;
|
||||
struct device *dev = &pdev->dev;
|
||||
int retval;
|
||||
unsigned int irq;
|
||||
int irq;
|
||||
|
||||
dev_dbg(dev, "%s()\n", __func__);
|
||||
|
||||
@@ -1861,7 +1857,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
|
||||
|
||||
/* irq setup after old hardware state is cleaned up */
|
||||
retval = request_irq(IRQ_USBD, s3c2410_udc_irq,
|
||||
IRQF_DISABLED, gadget_name, udc);
|
||||
IRQF_DISABLED, gadget_name, udc);
|
||||
|
||||
if (retval != 0) {
|
||||
dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval);
|
||||
@@ -1872,17 +1868,28 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
|
||||
dev_dbg(dev, "got irq %i\n", IRQ_USBD);
|
||||
|
||||
if (udc_info && udc_info->vbus_pin > 0) {
|
||||
irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
|
||||
retval = gpio_request(udc_info->vbus_pin, "udc vbus");
|
||||
if (retval < 0) {
|
||||
dev_err(dev, "cannot claim vbus pin\n");
|
||||
goto err_int;
|
||||
}
|
||||
|
||||
irq = gpio_to_irq(udc_info->vbus_pin);
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "no irq for gpio vbus pin\n");
|
||||
goto err_gpio_claim;
|
||||
}
|
||||
|
||||
retval = request_irq(irq, s3c2410_udc_vbus_irq,
|
||||
IRQF_DISABLED | IRQF_TRIGGER_RISING
|
||||
| IRQF_TRIGGER_FALLING | IRQF_SHARED,
|
||||
gadget_name, udc);
|
||||
|
||||
if (retval != 0) {
|
||||
dev_err(dev, "can't get vbus irq %i, err %d\n",
|
||||
dev_err(dev, "can't get vbus irq %d, err %d\n",
|
||||
irq, retval);
|
||||
retval = -EBUSY;
|
||||
goto err_int;
|
||||
goto err_gpio_claim;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "got irq %i\n", irq);
|
||||
@@ -1902,6 +1909,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
err_gpio_claim:
|
||||
if (udc_info && udc_info->vbus_pin > 0)
|
||||
gpio_free(udc_info->vbus_pin);
|
||||
err_int:
|
||||
free_irq(IRQ_USBD, udc);
|
||||
err_map:
|
||||
@@ -1927,7 +1937,7 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
|
||||
debugfs_remove(udc->regs_info);
|
||||
|
||||
if (udc_info && udc_info->vbus_pin > 0) {
|
||||
irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
|
||||
irq = gpio_to_irq(udc_info->vbus_pin);
|
||||
free_irq(irq, udc);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user