aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/at91_udc.c236
-rw-r--r--drivers/usb/gadget/at91_udc.h7
-rw-r--r--drivers/usb/gadget/dummy_hcd.c7
-rw-r--r--drivers/usb/gadget/file_storage.c2
-rw-r--r--drivers/usb/gadget/gmidi.c12
-rw-r--r--drivers/usb/gadget/goku_udc.c12
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c13
-rw-r--r--drivers/usb/gadget/net2280.c11
-rw-r--r--drivers/usb/gadget/omap_udc.c13
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c7
-rw-r--r--drivers/usb/gadget/serial.c2
11 files changed, 180 insertions, 142 deletions
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 3e0abbb49fe..812c733ba8c 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -43,14 +43,16 @@
#include <linux/usb_gadget.h>
#include <asm/byteorder.h>
+#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/mach-types.h>
-#include <asm/arch/hardware.h>
#include <asm/arch/gpio.h>
#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/at91sam9261_matrix.h>
#include "at91_udc.h"
@@ -78,27 +80,11 @@
static const char driver_name [] = "at91_udc";
static const char ep0name[] = "ep0";
-/*-------------------------------------------------------------------------*/
-/*
- * Read from a UDP register.
- */
-static inline unsigned long at91_udp_read(unsigned int reg)
-{
- void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP;
-
- return __raw_readl(udp_base + reg);
-}
-
-/*
- * Write to a UDP register.
- */
-static inline void at91_udp_write(unsigned int reg, unsigned long value)
-{
- void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP;
-
- __raw_writel(value, udp_base + reg);
-}
+#define at91_udp_read(dev, reg) \
+ __raw_readl((dev)->udp_baseaddr + (reg))
+#define at91_udp_write(dev, reg, val) \
+ __raw_writel((val), (dev)->udp_baseaddr + (reg))
/*-------------------------------------------------------------------------*/
@@ -210,13 +196,13 @@ static int proc_udc_show(struct seq_file *s, void *unused)
return 0;
}
- tmp = at91_udp_read(AT91_UDP_FRM_NUM);
+ tmp = at91_udp_read(udc, AT91_UDP_FRM_NUM);
seq_printf(s, "frame %05x:%s%s frame=%d\n", tmp,
(tmp & AT91_UDP_FRM_OK) ? " ok" : "",
(tmp & AT91_UDP_FRM_ERR) ? " err" : "",
(tmp & AT91_UDP_NUM));
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
seq_printf(s, "glbstate %02x:%s" FOURBITS "\n", tmp,
(tmp & AT91_UDP_RMWUPE) ? " rmwupe" : "",
(tmp & AT91_UDP_RSMINPR) ? " rsminpr" : "",
@@ -224,13 +210,13 @@ static int proc_udc_show(struct seq_file *s, void *unused)
(tmp & AT91_UDP_CONFG) ? " confg" : "",
(tmp & AT91_UDP_FADDEN) ? " fadden" : "");
- tmp = at91_udp_read(AT91_UDP_FADDR);
+ tmp = at91_udp_read(udc, AT91_UDP_FADDR);
seq_printf(s, "faddr %03x:%s fadd=%d\n", tmp,
(tmp & AT91_UDP_FEN) ? " fen" : "",
(tmp & AT91_UDP_FADD));
- proc_irq_show(s, "imr ", at91_udp_read(AT91_UDP_IMR));
- proc_irq_show(s, "isr ", at91_udp_read(AT91_UDP_ISR));
+ proc_irq_show(s, "imr ", at91_udp_read(udc, AT91_UDP_IMR));
+ proc_irq_show(s, "isr ", at91_udp_read(udc, AT91_UDP_ISR));
if (udc->enabled && udc->vbus) {
proc_ep_show(s, &udc->ep[0]);
@@ -286,6 +272,7 @@ static inline void remove_debug_file(struct at91_udc *udc) {}
static void done(struct at91_ep *ep, struct at91_request *req, int status)
{
unsigned stopped = ep->stopped;
+ struct at91_udc *udc = ep->udc;
list_del_init(&req->queue);
if (req->req.status == -EINPROGRESS)
@@ -301,7 +288,7 @@ static void done(struct at91_ep *ep, struct at91_request *req, int status)
/* ep0 is always ready; other endpoints need a non-empty queue */
if (list_empty(&ep->queue) && ep->int_mask != (1 << 0))
- at91_udp_write(AT91_UDP_IDR, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_IDR, ep->int_mask);
}
/*-------------------------------------------------------------------------*/
@@ -554,8 +541,8 @@ ok:
* reset/init endpoint fifo. NOTE: leaves fifo_bank alone,
* since endpoint resets don't reset hw pingpong state.
*/
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(dev, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(dev, AT91_UDP_RST_EP, 0);
local_irq_restore(flags);
return 0;
@@ -564,6 +551,7 @@ ok:
static int at91_ep_disable (struct usb_ep * _ep)
{
struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
+ struct at91_udc *udc = ep->udc;
unsigned long flags;
if (ep == &ep->udc->ep[0])
@@ -579,8 +567,8 @@ static int at91_ep_disable (struct usb_ep * _ep)
/* reset fifos and endpoint */
if (ep->udc->clocked) {
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
__raw_writel(0, ep->creg);
}
@@ -695,10 +683,10 @@ static int at91_ep_queue(struct usb_ep *_ep,
* reconfigures the endpoints.
*/
if (dev->wait_for_config_ack) {
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(dev, AT91_UDP_GLB_STAT);
tmp ^= AT91_UDP_CONFG;
VDBG("toggle config\n");
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(dev, AT91_UDP_GLB_STAT, tmp);
}
if (req->req.length == 0) {
ep0_in_status:
@@ -727,7 +715,7 @@ ep0_in_status:
if (req && !status) {
list_add_tail (&req->queue, &ep->queue);
- at91_udp_write(AT91_UDP_IER, ep->int_mask);
+ at91_udp_write(dev, AT91_UDP_IER, ep->int_mask);
}
done:
local_irq_restore(flags);
@@ -758,6 +746,7 @@ static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
static int at91_ep_set_halt(struct usb_ep *_ep, int value)
{
struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
+ struct at91_udc *udc = ep->udc;
u32 __iomem *creg;
u32 csr;
unsigned long flags;
@@ -785,8 +774,8 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value)
csr |= AT91_UDP_FORCESTALL;
VDBG("halt %s\n", ep->ep.name);
} else {
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
csr &= ~AT91_UDP_FORCESTALL;
}
__raw_writel(csr, creg);
@@ -813,9 +802,11 @@ static struct usb_ep_ops at91_ep_ops = {
static int at91_get_frame(struct usb_gadget *gadget)
{
+ struct at91_udc *udc = to_udc(gadget);
+
if (!to_udc(gadget)->clocked)
return -EINVAL;
- return at91_udp_read(AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
+ return at91_udp_read(udc, AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
}
static int at91_wakeup(struct usb_gadget *gadget)
@@ -833,11 +824,11 @@ static int at91_wakeup(struct usb_gadget *gadget)
/* NOTE: some "early versions" handle ESR differently ... */
- glbstate = at91_udp_read(AT91_UDP_GLB_STAT);
+ glbstate = at91_udp_read(udc, AT91_UDP_GLB_STAT);
if (!(glbstate & AT91_UDP_ESR))
goto done;
glbstate |= AT91_UDP_ESR;
- at91_udp_write(AT91_UDP_GLB_STAT, glbstate);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate);
done:
local_irq_restore(flags);
@@ -861,6 +852,7 @@ static void udc_reinit(struct at91_udc *udc)
ep->stopped = 0;
ep->fifo_bank = 0;
ep->ep.maxpacket = ep->maxpacket;
+ ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i);
// initialiser une queue par endpoint
INIT_LIST_HEAD(&ep->queue);
}
@@ -915,14 +907,41 @@ static void pullup(struct at91_udc *udc, int is_on)
if (!udc->enabled || !udc->vbus)
is_on = 0;
DBG("%sactive\n", is_on ? "" : "in");
+
if (is_on) {
clk_on(udc);
- at91_udp_write(AT91_UDP_TXVC, 0);
- at91_set_gpio_value(udc->board.pullup_pin, 1);
- } else {
+ at91_udp_write(udc, AT91_UDP_TXVC, 0);
+ if (cpu_is_at91rm9200())
+ at91_set_gpio_value(udc->board.pullup_pin, 1);
+ else if (cpu_is_at91sam9260()) {
+ u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+ txvc |= AT91_UDP_TXVC_PUON;
+ at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+ } else if (cpu_is_at91sam9261()) {
+ u32 usbpucr;
+
+ usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
+ usbpucr |= AT91_MATRIX_USBPUCR_PUON;
+ at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
+ }
+ } else {
stop_activity(udc);
- at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
- at91_set_gpio_value(udc->board.pullup_pin, 0);
+ at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+ if (cpu_is_at91rm9200())
+ at91_set_gpio_value(udc->board.pullup_pin, 0);
+ else if (cpu_is_at91sam9260()) {
+ u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+ txvc &= ~AT91_UDP_TXVC_PUON;
+ at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+ } else if (cpu_is_at91sam9261()) {
+ u32 usbpucr;
+
+ usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
+ usbpucr &= ~AT91_MATRIX_USBPUCR_PUON;
+ at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
+ }
clk_off(udc);
}
}
@@ -936,7 +955,10 @@ static int at91_vbus_session(struct usb_gadget *gadget, int is_active)
// VDBG("vbus %s\n", is_active ? "on" : "off");
local_irq_save(flags);
udc->vbus = (is_active != 0);
- pullup(udc, is_active);
+ if (udc->driver)
+ pullup(udc, is_active);
+ else
+ pullup(udc, 0);
local_irq_restore(flags);
return 0;
}
@@ -1086,7 +1108,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_SET_CONFIGURATION:
- tmp = at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
if (pkt.r.wValue)
udc->wait_for_config_ack = (tmp == 0);
else
@@ -1103,7 +1125,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_GET_STATUS:
tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED);
- if (at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
+ if (at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP);
PACKET("get device status\n");
__raw_writeb(tmp, dreg);
@@ -1114,17 +1136,17 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
| USB_REQ_SET_FEATURE:
if (w_value != USB_DEVICE_REMOTE_WAKEUP)
goto stall;
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp |= AT91_UDP_ESR;
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
goto succeed;
case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_CLEAR_FEATURE:
if (w_value != USB_DEVICE_REMOTE_WAKEUP)
goto stall;
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp &= ~AT91_UDP_ESR;
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
goto succeed;
/*
@@ -1206,8 +1228,8 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
} else if (ep->is_in)
goto stall;
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
tmp = __raw_readl(ep->creg);
tmp |= CLR_FX;
tmp &= ~(SET_FX | AT91_UDP_FORCESTALL);
@@ -1222,7 +1244,10 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
#undef w_length
/* pass request up to the gadget driver */
- status = udc->driver->setup(&udc->gadget, &pkt.r);
+ if (udc->driver)
+ status = udc->driver->setup(&udc->gadget, &pkt.r);
+ else
+ status = -ENODEV;
if (status < 0) {
stall:
VDBG("req %02x.%02x protocol STALL; stat %d\n",
@@ -1300,13 +1325,13 @@ static void handle_ep0(struct at91_udc *udc)
if (udc->wait_for_addr_ack) {
u32 tmp;
- at91_udp_write(AT91_UDP_FADDR,
+ at91_udp_write(udc, AT91_UDP_FADDR,
AT91_UDP_FEN | udc->addr);
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp &= ~AT91_UDP_FADDEN;
if (udc->addr)
tmp |= AT91_UDP_FADDEN;
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
udc->wait_for_addr_ack = 0;
VDBG("address %d\n", udc->addr);
@@ -1374,28 +1399,28 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
while (rescans--) {
u32 status;
- status = at91_udp_read(AT91_UDP_ISR)
- & at91_udp_read(AT91_UDP_IMR);
+ status = at91_udp_read(udc, AT91_UDP_ISR)
+ & at91_udp_read(udc, AT91_UDP_IMR);
if (!status)
break;
/* USB reset irq: not maskable */
if (status & AT91_UDP_ENDBUSRES) {
- at91_udp_write(AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
- at91_udp_write(AT91_UDP_IER, MINIMUS_INTERRUPTUS);
+ at91_udp_write(udc, AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
+ at91_udp_write(udc, AT91_UDP_IER, MINIMUS_INTERRUPTUS);
/* Atmel code clears this irq twice */
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
VDBG("end bus reset\n");
udc->addr = 0;
stop_activity(udc);
/* enable ep0 */
- at91_udp_write(AT91_UDP_CSR(0),
+ at91_udp_write(udc, AT91_UDP_CSR(0),
AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
udc->gadget.speed = USB_SPEED_FULL;
udc->suspended = 0;
- at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0));
+ at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_EP(0));
/*
* NOTE: this driver keeps clocks off unless the
@@ -1406,9 +1431,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
/* host initiated suspend (3+ms bus idle) */
} else if (status & AT91_UDP_RXSUSP) {
- at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXSUSP);
- at91_udp_write(AT91_UDP_IER, AT91_UDP_RXRSM);
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXSUSP);
+ at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXSUSP);
+ at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXSUSP);
// VDBG("bus suspend\n");
if (udc->suspended)
continue;
@@ -1425,9 +1450,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
/* host initiated resume */
} else if (status & AT91_UDP_RXRSM) {
- at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXRSM);
- at91_udp_write(AT91_UDP_IER, AT91_UDP_RXSUSP);
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXSUSP);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
// VDBG("bus resume\n");
if (!udc->suspended)
continue;
@@ -1485,8 +1510,6 @@ static struct at91_udc controller = {
},
.udc = &controller,
.maxpacket = 8,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(0)),
.int_mask = 1 << 0,
},
.ep[1] = {
@@ -1497,8 +1520,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 64,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(1)),
.int_mask = 1 << 1,
},
.ep[2] = {
@@ -1509,8 +1530,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 64,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(2)),
.int_mask = 1 << 2,
},
.ep[3] = {
@@ -1521,8 +1540,6 @@ static struct at91_udc controller = {
},
.udc = &controller,
.maxpacket = 8,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(3)),
.int_mask = 1 << 3,
},
.ep[4] = {
@@ -1533,8 +1550,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 256,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(4)),
.int_mask = 1 << 4,
},
.ep[5] = {
@@ -1545,8 +1560,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 256,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(5)),
.int_mask = 1 << 5,
},
/* ep6 and ep7 are also reserved (custom silicon might use them) */
@@ -1572,9 +1585,8 @@ 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->unbind
|| !driver->setup) {
DBG("bad parameter.\n");
return -EINVAL;
@@ -1595,6 +1607,10 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
if (retval) {
DBG("driver->bind() returned %d\n", retval);
udc->driver = NULL;
+ udc->gadget.dev.driver = NULL;
+ udc->gadget.dev.driver_data = NULL;
+ udc->enabled = 0;
+ udc->selfpowered = 0;
return retval;
}
@@ -1611,12 +1627,12 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
{
struct at91_udc *udc = &controller;
- if (!driver || driver != udc->driver)
+ if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
local_irq_disable();
udc->enabled = 0;
- at91_udp_write(AT91_UDP_IDR, ~0);
+ at91_udp_write(udc, AT91_UDP_IDR, ~0);
pullup(udc, 0);
local_irq_enable();
@@ -1641,6 +1657,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct at91_udc *udc;
int retval;
+ struct resource *res;
if (!dev->platform_data) {
/* small (so we copy it) but critical! */
@@ -1658,7 +1675,13 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (!request_mem_region(AT91RM9200_BASE_UDP, SZ_16K, driver_name)) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ if (!request_mem_region(res->start,
+ res->end - res->start + 1,
+ driver_name)) {
DBG("someone's using UDC memory\n");
return -EBUSY;
}
@@ -1668,15 +1691,23 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
udc->gadget.dev.parent = dev;
udc->board = *(struct at91_udc_data *) dev->platform_data;
udc->pdev = pdev;
- udc_reinit(udc);
udc->enabled = 0;
+ udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
+ if (!udc->udp_baseaddr) {
+ release_mem_region(res->start, res->end - res->start + 1);
+ return -ENOMEM;
+ }
+
+ udc_reinit(udc);
+
/* get interface and function clocks */
udc->iclk = clk_get(dev, "udc_clk");
udc->fclk = clk_get(dev, "udpck");
if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
DBG("clocks missing\n");
- return -ENODEV;
+ retval = -ENODEV;
+ goto fail0;
}
retval = device_register(&udc->gadget.dev);
@@ -1685,8 +1716,10 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
/* don't do anything until we have both gadget driver and VBUS */
clk_enable(udc->iclk);
- at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
- at91_udp_write(AT91_UDP_IDR, 0xffffffff);
+ at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+ at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
+ /* Clear all pending interrupts - UDP may be used by bootloader. */
+ at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
clk_disable(udc->iclk);
/* request UDC and maybe VBUS irqs */
@@ -1698,6 +1731,11 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
goto fail1;
}
if (udc->board.vbus_pin > 0) {
+ /*
+ * Get the initial state of VBUS - we cannot expect
+ * a pending interrupt.
+ */
+ udc->vbus = at91_get_gpio_value(udc->board.vbus_pin);
if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
IRQF_DISABLED, driver_name, udc)) {
DBG("request vbus irq %d failed\n",
@@ -1720,7 +1758,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
fail1:
device_unregister(&udc->gadget.dev);
fail0:
- release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
+ release_mem_region(res->start, res->end - res->start + 1);
DBG("%s probe failed, %d\n", driver_name, retval);
return retval;
}
@@ -1728,13 +1766,14 @@ fail0:
static int __devexit at91udc_remove(struct platform_device *pdev)
{
struct at91_udc *udc = platform_get_drvdata(pdev);
+ struct resource *res;
DBG("remove\n");
- pullup(udc, 0);
+ if (udc->driver)
+ return -EBUSY;
- if (udc->driver != 0)
- usb_gadget_unregister_driver(udc->driver);
+ pullup(udc, 0);
device_init_wakeup(&pdev->dev, 0);
remove_debug_file(udc);
@@ -1742,7 +1781,10 @@ static int __devexit at91udc_remove(struct platform_device *pdev)
free_irq(udc->board.vbus_pin, udc);
free_irq(udc->udp_irq, udc);
device_unregister(&udc->gadget.dev);
- release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
+
+ iounmap(udc->udp_baseaddr);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, res->end - res->start + 1);
clk_put(udc->iclk);
clk_put(udc->fclk);
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index 882af42e86c..677089baa59 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -51,10 +51,10 @@
#define AT91_UDP_EP(n) (1 << (n)) /* Endpoint Interrupt Status */
#define AT91_UDP_RXSUSP (1 << 8) /* USB Suspend Interrupt Status */
#define AT91_UDP_RXRSM (1 << 9) /* USB Resume Interrupt Status */
-#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status */
+#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status [AT91RM9200 only] */
#define AT91_UDP_SOFINT (1 << 11) /* Start of Frame Interrupt Status */
#define AT91_UDP_ENDBUSRES (1 << 12) /* End of Bus Reset Interrpt Status */
-#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status */
+#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status [AT91RM9200 only] */
#define AT91_UDP_ICR 0x20 /* Interrupt Clear Register */
#define AT91_UDP_RST_EP 0x28 /* Reset Endpoint Register */
@@ -84,7 +84,7 @@
#define AT91_UDP_TXVC 0x74 /* Transceiver Control Register */
#define AT91_UDP_TXVC_TXVDIS (1 << 8) /* Transceiver Disable */
-
+#define AT91_UDP_TXVC_PUON (1 << 9) /* PullUp On [AT91SAM9260 only] */
/*-------------------------------------------------------------------------*/
@@ -141,6 +141,7 @@ struct at91_udc {
struct clk *iclk, *fclk;
struct platform_device *pdev;
struct proc_dir_entry *pde;
+ void __iomem *udp_baseaddr;
int udp_irq;
};
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index f1f32d7be5f..3c2bc075ef4 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -779,7 +779,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
return -EINVAL;
if (dum->driver)
return -EBUSY;
- if (!driver->bind || !driver->unbind || !driver->setup
+ if (!driver->bind || !driver->setup
|| driver->speed == USB_SPEED_UNKNOWN)
return -EINVAL;
@@ -837,7 +837,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
err_bind_driver:
driver_unregister (&driver->driver);
err_register:
- driver->unbind (&dum->gadget);
+ if (driver->unbind)
+ driver->unbind (&dum->gadget);
spin_lock_irq (&dum->lock);
dum->pullup = 0;
set_link_state (dum);
@@ -857,7 +858,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!dum)
return -ENODEV;
- if (!driver || driver != dum->driver)
+ if (!driver || driver != dum->driver || !driver->unbind)
return -EINVAL;
dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index a265e262a2e..72f2ae96fbf 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -4100,7 +4100,7 @@ static struct usb_gadget_driver fsg_driver = {
#endif
.function = (char *) longname,
.bind = fsg_bind,
- .unbind = __exit_p(fsg_unbind),
+ .unbind = fsg_unbind,
.disconnect = fsg_disconnect,
.setup = fsg_setup,
.suspend = fsg_suspend,
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 31351826f2b..f1a679656c9 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -123,7 +123,7 @@ struct gmidi_device {
struct usb_request *req; /* for control responses */
u8 config;
struct usb_ep *in_ep, *out_ep;
- struct snd_card *card;
+ struct snd_card *card;
struct snd_rawmidi *rmidi;
struct snd_rawmidi_substream *in_substream;
struct snd_rawmidi_substream *out_substream;
@@ -490,7 +490,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req)
int status = req->status;
switch (status) {
- case 0: /* normal completion */
+ case 0: /* normal completion */
if (ep == dev->out_ep) {
/* we received stuff.
req is queued again, below */
@@ -505,7 +505,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req)
break;
/* this endpoint is normally active while we're configured */
- case -ECONNABORTED: /* hardware forced ep reset */
+ case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
@@ -656,7 +656,7 @@ gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags)
case USB_SPEED_LOW: speed = "low"; break;
case USB_SPEED_FULL: speed = "full"; break;
case USB_SPEED_HIGH: speed = "high"; break;
- default: speed = "?"; break;
+ default: speed = "?"; break;
}
dev->config = number;
@@ -1308,7 +1308,7 @@ static struct usb_gadget_driver gmidi_driver = {
.speed = USB_SPEED_FULL,
.function = (char *)longname,
.bind = gmidi_bind,
- .unbind = __exit_p(gmidi_unbind),
+ .unbind = gmidi_unbind,
.setup = gmidi_setup,
.disconnect = gmidi_disconnect,
@@ -1316,7 +1316,7 @@ static struct usb_gadget_driver gmidi_driver = {
.suspend = gmidi_suspend,
.resume = gmidi_resume,
- .driver = {
+ .driver = {
.name = (char *)shortname,
.owner = THIS_MODULE,
},
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 805a9826842..d0ef1d6b3fa 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1432,7 +1432,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!driver
|| driver->speed != USB_SPEED_FULL
|| !driver->bind
- || !driver->unbind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@@ -1495,7 +1494,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave(&dev->lock, flags);
@@ -1808,13 +1807,8 @@ static void goku_remove(struct pci_dev *pdev)
struct goku_udc *dev = pci_get_drvdata(pdev);
DBG(dev, "%s\n", __FUNCTION__);
- /* start with the driver above us */
- if (dev->driver) {
- /* should have been done already by driver model core */
- WARN(dev, "pci remove, driver '%s' is still registered\n",
- dev->driver->driver.name);
- usb_gadget_unregister_driver(dev->driver);
- }
+
+ BUG_ON(dev->driver);
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
remove_proc_entry(proc_node_name, NULL);
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 4a991564a03..a0a73c08a34 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -422,9 +422,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name);
if (!driver
- || driver->speed != USB_SPEED_FULL
- || !driver->bind
- || !driver->unbind || !driver->disconnect || !driver->setup)
+ || driver->speed != USB_SPEED_FULL
+ || !driver->bind
+ || !driver->disconnect
+ || !driver->setup)
return -EINVAL;
if (!dev)
return -ENODEV;
@@ -471,7 +472,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave(&dev->lock, flags);
@@ -2125,9 +2126,11 @@ static int lh7a40x_udc_remove(struct platform_device *pdev)
DEBUG("%s: %p\n", __FUNCTION__, pdev);
+ if (dev->driver)
+ return -EBUSY;
+
udc_disable(dev);
remove_proc_files();
- usb_gadget_unregister_driver(dev->driver);
free_irq(IRQ_USBINTR, dev);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 3024c679e38..569eb8ccf23 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2020,7 +2020,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
if (!driver
|| driver->speed != USB_SPEED_HIGH
|| !driver->bind
- || !driver->unbind
|| !driver->setup)
return -EINVAL;
if (!dev)
@@ -2107,7 +2106,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave (&dev->lock, flags);
@@ -2803,13 +2802,7 @@ static void net2280_remove (struct pci_dev *pdev)
{
struct net2280 *dev = pci_get_drvdata (pdev);
- /* start with the driver above us */
- if (dev->driver) {
- /* should have been done already by driver model core */
- WARN (dev, "pci remove, driver '%s' is still registered\n",
- dev->driver->driver.name);
- usb_gadget_unregister_driver (dev->driver);
- }
+ BUG_ON(dev->driver);
/* then clean up the resources we allocated during probe() */
net2280_led_shutdown (dev);
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 030d87c28c2..15d77c30793 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2043,7 +2043,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
// FIXME if otg, check: driver->is_otg
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
- || !driver->unbind
|| !driver->setup)
return -EINVAL;
@@ -2087,9 +2086,11 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
status = otg_set_peripheral(udc->transceiver, &udc->gadget);
if (status < 0) {
ERR("can't bind to transceiver\n");
- driver->unbind (&udc->gadget);
- udc->gadget.dev.driver = NULL;
- udc->driver = NULL;
+ if (driver->unbind) {
+ driver->unbind (&udc->gadget);
+ udc->gadget.dev.driver = NULL;
+ udc->driver = NULL;
+ }
goto done;
}
} else {
@@ -2117,7 +2118,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!udc)
return -ENODEV;
- if (!driver || driver != udc->driver)
+ if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
if (machine_is_omap_innovator() || machine_is_omap_osk())
@@ -2870,6 +2871,8 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
if (!udc)
return -ENODEV;
+ if (udc->driver)
+ return -EBUSY;
udc->done = &done;
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 1ed506e9598..b78de969466 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -1623,7 +1623,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!driver
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
- || !driver->unbind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@@ -1694,7 +1693,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
local_irq_disable();
@@ -2638,9 +2637,11 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
{
struct pxa2xx_udc *dev = platform_get_drvdata(pdev);
+ if (dev->driver)
+ return -EBUSY;
+
udc_disable(dev);
remove_proc_files();
- usb_gadget_unregister_driver(dev->driver);
if (dev->got_irq) {
free_irq(IRQ_USB, dev);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 2d12bf9f19d..f8a3ec64635 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -296,7 +296,7 @@ static struct usb_gadget_driver gs_gadget_driver = {
#endif /* CONFIG_USB_GADGET_DUALSPEED */
.function = GS_LONG_NAME,
.bind = gs_bind,
- .unbind = __exit_p(gs_unbind),
+ .unbind = gs_unbind,
.setup = gs_setup,
.disconnect = gs_disconnect,
.driver = {