diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 20 | ||||
-rw-r--r-- | drivers/usb/host/ehci-xilinx-of.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/isp1362.h | 2 | ||||
-rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/r8a66597.h | 26 | ||||
-rw-r--r-- | drivers/usb/host/xhci-pci.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 31 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 57 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 12 |
9 files changed, 127 insertions, 29 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index ef3e88f0b3c3..a3ef2a9d9dc2 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1135,7 +1135,7 @@ MODULE_LICENSE ("GPL"); #ifdef CONFIG_XPS_USB_HCD_XILINX #include "ehci-xilinx-of.c" -#define OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver +#define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver #endif #ifdef CONFIG_PLAT_ORION @@ -1159,7 +1159,8 @@ MODULE_LICENSE ("GPL"); #endif #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ - !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) + !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ + !defined(XILINX_OF_PLATFORM_DRIVER) #error "missing bus glue for ehci-hcd" #endif @@ -1213,10 +1214,20 @@ static int __init ehci_hcd_init(void) if (retval < 0) goto clean3; #endif + +#ifdef XILINX_OF_PLATFORM_DRIVER + retval = of_register_platform_driver(&XILINX_OF_PLATFORM_DRIVER); + if (retval < 0) + goto clean4; +#endif return retval; +#ifdef XILINX_OF_PLATFORM_DRIVER + /* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */ +clean4: +#endif #ifdef OF_PLATFORM_DRIVER - /* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */ + of_unregister_platform_driver(&OF_PLATFORM_DRIVER); clean3: #endif #ifdef PS3_SYSTEM_BUS_DRIVER @@ -1243,6 +1254,9 @@ module_init(ehci_hcd_init); static void __exit ehci_hcd_cleanup(void) { +#ifdef XILINX_OF_PLATFORM_DRIVER + of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); +#endif #ifdef OF_PLATFORM_DRIVER of_unregister_platform_driver(&OF_PLATFORM_DRIVER); #endif diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 013972bbde57..4899f451add9 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -151,7 +151,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { static int __devinit ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match) { - struct device_node *dn = op->node; + struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; struct ehci_hcd *ehci; struct resource res; diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index 5151516ea1de..d995351f9bed 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h @@ -65,7 +65,7 @@ static inline void delayed_insw(unsigned int addr, void *buf, int len) unsigned short *bp = (unsigned short *)buf; while (len--) { DUMMY_DELAY_ACCESS; - *bp++ = inw((void *)addr); + *bp++ = inw(addr); } } diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 6db57ab6079d..1a2bb4ce638f 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2404,7 +2404,7 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev) del_timer_sync(&r8a66597->rh_timer); usb_remove_hcd(hcd); - iounmap((void *)r8a66597->reg); + iounmap(r8a66597->reg); #ifdef CONFIG_HAVE_CLK if (r8a66597->pdata->on_chip) clk_put(r8a66597->clk); @@ -2496,7 +2496,7 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) init_timer(&r8a66597->rh_timer); r8a66597->rh_timer.function = r8a66597_timer; r8a66597->rh_timer.data = (unsigned long)r8a66597; - r8a66597->reg = (unsigned long)reg; + r8a66597->reg = reg; /* make sure no interrupts are pending */ ret = r8a66597_clock_enable(r8a66597); diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index 228e3fb23854..95d0f5adfdcf 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h @@ -112,7 +112,7 @@ struct r8a66597_root_hub { struct r8a66597 { spinlock_t lock; - unsigned long reg; + void __iomem *reg; #ifdef CONFIG_HAVE_CLK struct clk *clk; #endif @@ -170,67 +170,67 @@ static inline struct urb *r8a66597_get_urb(struct r8a66597 *r8a66597, static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset) { - return inw(r8a66597->reg + offset); + return ioread16(r8a66597->reg + offset); } static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, unsigned long offset, u16 *buf, int len) { - unsigned long fifoaddr = r8a66597->reg + offset; + void __iomem *fifoaddr = r8a66597->reg + offset; unsigned long count; if (r8a66597->pdata->on_chip) { count = len / 4; - insl(fifoaddr, buf, count); + ioread32_rep(fifoaddr, buf, count); if (len & 0x00000003) { - unsigned long tmp = inl(fifoaddr); + unsigned long tmp = ioread32(fifoaddr); memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03); } } else { len = (len + 1) / 2; - insw(fifoaddr, buf, len); + ioread16_rep(fifoaddr, buf, len); } } static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, unsigned long offset) { - outw(val, r8a66597->reg + offset); + iowrite16(val, r8a66597->reg + offset); } static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, unsigned long offset, u16 *buf, int len) { - unsigned long fifoaddr = r8a66597->reg + offset; + void __iomem *fifoaddr = r8a66597->reg + offset; unsigned long count; unsigned char *pb; int i; if (r8a66597->pdata->on_chip) { count = len / 4; - outsl(fifoaddr, buf, count); + iowrite32_rep(fifoaddr, buf, count); 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); + iowrite8(pb[i], fifoaddr + i); else - outb(pb[i], fifoaddr + 3 - i); + iowrite8(pb[i], fifoaddr + 3 - i); } } } else { int odd = len & 0x0001; len = len / 2; - outsw(fifoaddr, buf, len); + ioread16_rep(fifoaddr, buf, len); if (unlikely(odd)) { buf = &buf[len]; - outb((unsigned char)*buf, fifoaddr); + iowrite8((unsigned char)*buf, fifoaddr); } } } diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index edffd81fc253..11482b6b9381 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -78,6 +78,8 @@ static int xhci_pci_setup(struct usb_hcd *hcd) xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" " endpoint cmd after reset endpoint\n"); } + if (pdev->vendor == PCI_VENDOR_ID_NEC) + xhci->quirks |= XHCI_NEC_HOST; /* Make sure the HC is halted. */ retval = xhci_halt(xhci); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 36c858e5b529..9012098add6b 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1071,6 +1071,15 @@ bandwidth_change: xhci_warn(xhci, "Reset device command completion " "for disabled slot %u\n", slot_id); break; + case TRB_TYPE(TRB_NEC_GET_FW): + if (!(xhci->quirks & XHCI_NEC_HOST)) { + xhci->error_bitmask |= 1 << 6; + break; + } + xhci_dbg(xhci, "NEC firmware version %2x.%02x\n", + NEC_FW_MAJOR(event->status), + NEC_FW_MINOR(event->status)); + break; default: /* Skip over unknown commands on the event ring */ xhci->error_bitmask |= 1 << 6; @@ -1079,6 +1088,17 @@ bandwidth_change: inc_deq(xhci, xhci->cmd_ring, false); } +static void handle_vendor_event(struct xhci_hcd *xhci, + union xhci_trb *event) +{ + u32 trb_type; + + trb_type = TRB_FIELD_TO_TYPE(event->generic.field[3]); + xhci_dbg(xhci, "Vendor specific event TRB type = %u\n", trb_type); + if (trb_type == TRB_NEC_CMD_COMP && (xhci->quirks & XHCI_NEC_HOST)) + handle_cmd_completion(xhci, &event->event_cmd); +} + static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event) { @@ -1659,7 +1679,10 @@ void xhci_handle_event(struct xhci_hcd *xhci) update_ptrs = 0; break; default: - xhci->error_bitmask |= 1 << 3; + if ((event->event_cmd.flags & TRB_TYPE_BITMASK) >= TRB_TYPE(48)) + handle_vendor_event(xhci, event); + else + xhci->error_bitmask |= 1 << 3; } /* Any of the above functions may drop and re-acquire the lock, so check * to make sure a watchdog timer didn't mark the host as non-responsive. @@ -2378,6 +2401,12 @@ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, false); } +int xhci_queue_vendor_command(struct xhci_hcd *xhci, + u32 field1, u32 field2, u32 field3, u32 field4) +{ + return queue_command(xhci, field1, field2, field3, field4, false); +} + /* Queue a reset device command TRB */ int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 40e0a0c221b8..27345cd04da0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -106,6 +106,33 @@ int xhci_halt(struct xhci_hcd *xhci) } /* + * Set the run bit and wait for the host to be running. + */ +int xhci_start(struct xhci_hcd *xhci) +{ + u32 temp; + int ret; + + temp = xhci_readl(xhci, &xhci->op_regs->command); + temp |= (CMD_RUN); + xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n", + temp); + xhci_writel(xhci, temp, &xhci->op_regs->command); + + /* + * Wait for the HCHalted Status bit to be 0 to indicate the host is + * running. + */ + ret = handshake(xhci, &xhci->op_regs->status, + STS_HALT, 0, XHCI_MAX_HALT_USEC); + if (ret == -ETIMEDOUT) + xhci_err(xhci, "Host took too long to start, " + "waited %u microseconds.\n", + XHCI_MAX_HALT_USEC); + return ret; +} + +/* * Reset a halted HC, and set the internal HC state to HC_STATE_HALT. * * This resets pipelines, timers, counters, state machines, etc. @@ -116,6 +143,7 @@ int xhci_reset(struct xhci_hcd *xhci) { u32 command; u32 state; + int ret; state = xhci_readl(xhci, &xhci->op_regs->status); if ((state & STS_HALT) == 0) { @@ -130,7 +158,17 @@ int xhci_reset(struct xhci_hcd *xhci) /* XXX: Why does EHCI set this here? Shouldn't other code do this? */ xhci_to_hcd(xhci)->state = HC_STATE_HALT; - return handshake(xhci, &xhci->op_regs->command, CMD_RESET, 0, 250 * 1000); + ret = handshake(xhci, &xhci->op_regs->command, + CMD_RESET, 0, 250 * 1000); + if (ret) + return ret; + + xhci_dbg(xhci, "Wait for controller to be ready for doorbell rings\n"); + /* + * xHCI cannot write to any doorbells or operational registers other + * than status until the "Controller Not Ready" flag is cleared. + */ + return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); } @@ -448,17 +486,20 @@ int xhci_run(struct usb_hcd *hcd) if (NUM_TEST_NOOPS > 0) doorbell = xhci_setup_one_noop(xhci); + if (xhci->quirks & XHCI_NEC_HOST) + xhci_queue_vendor_command(xhci, 0, 0, 0, + TRB_TYPE(TRB_NEC_GET_FW)); + + if (xhci_start(xhci)) { + xhci_halt(xhci); + return -ENODEV; + } - temp = xhci_readl(xhci, &xhci->op_regs->command); - temp |= (CMD_RUN); - xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n", - temp); - xhci_writel(xhci, temp, &xhci->op_regs->command); - /* Flush PCI posted writes */ - temp = xhci_readl(xhci, &xhci->op_regs->command); xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp); if (doorbell) (*doorbell)(xhci); + if (xhci->quirks & XHCI_NEC_HOST) + xhci_ring_cmd_db(xhci); xhci_dbg(xhci, "Finished xhci_run\n"); return 0; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index dada2fb59261..8b4b7d39f79c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -925,6 +925,7 @@ union xhci_trb { /* TRB bit mask */ #define TRB_TYPE_BITMASK (0xfc00) #define TRB_TYPE(p) ((p) << 10) +#define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10) /* TRB type IDs */ /* bulk, interrupt, isoc scatter/gather, and control data stage */ #define TRB_NORMAL 1 @@ -992,6 +993,14 @@ union xhci_trb { #define TRB_MFINDEX_WRAP 39 /* TRB IDs 40-47 reserved, 48-63 is vendor-defined */ +/* Nec vendor-specific command completion event. */ +#define TRB_NEC_CMD_COMP 48 +/* Get NEC firmware revision. */ +#define TRB_NEC_GET_FW 49 + +#define NEC_FW_MINOR(p) (((p) >> 0) & 0xff) +#define NEC_FW_MAJOR(p) (((p) >> 8) & 0xff) + /* * TRBS_PER_SEGMENT must be a multiple of 4, * since the command ring is 64-byte aligned. @@ -1172,6 +1181,7 @@ struct xhci_hcd { unsigned int quirks; #define XHCI_LINK_TRB_QUIRK (1 << 0) #define XHCI_RESET_EP_QUIRK (1 << 1) +#define XHCI_NEC_HOST (1 << 2) }; /* For testing purposes */ @@ -1379,6 +1389,8 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci); int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id); int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id); +int xhci_queue_vendor_command(struct xhci_hcd *xhci, + u32 field1, u32 field2, u32 field3, u32 field4); int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id, unsigned int ep_index); int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, |