diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2010-05-24 16:25:28 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-06-04 16:16:19 -0400 |
commit | 0238634d02dd10b678ebe9ea5d8803483277ee93 (patch) | |
tree | 5978fcfdc185e15e407fb16e52daef4225c19882 /drivers/usb/host | |
parent | ed07453fd356025cc25272629e982f5e4607632c (diff) |
USB: xhci: Print NEC firmware version.
The NEC xHCI host controller firmware version can be found by putting a
vendor-specific command on the command ring and extracting the BCD
encoded-version out of the vendor-specific event TRB.
The firmware version debug line in dmesg will look like:
xhci_hcd 0000:05:00.0: NEC firmware version 30.21
(NEC merged with Renesas Technologies and became Renesas Electronics on
April 1, 2010. I have their OK to merge this vendor-specific code.)
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Cc: Satoshi Otani <satoshi.otani.xm@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-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 | 5 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 12 |
4 files changed, 49 insertions, 1 deletions
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) | |||
78 | xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" | 78 | xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" |
79 | " endpoint cmd after reset endpoint\n"); | 79 | " endpoint cmd after reset endpoint\n"); |
80 | } | 80 | } |
81 | if (pdev->vendor == PCI_VENDOR_ID_NEC) | ||
82 | xhci->quirks |= XHCI_NEC_HOST; | ||
81 | 83 | ||
82 | /* Make sure the HC is halted. */ | 84 | /* Make sure the HC is halted. */ |
83 | retval = xhci_halt(xhci); | 85 | 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: | |||
1071 | xhci_warn(xhci, "Reset device command completion " | 1071 | xhci_warn(xhci, "Reset device command completion " |
1072 | "for disabled slot %u\n", slot_id); | 1072 | "for disabled slot %u\n", slot_id); |
1073 | break; | 1073 | break; |
1074 | case TRB_TYPE(TRB_NEC_GET_FW): | ||
1075 | if (!(xhci->quirks & XHCI_NEC_HOST)) { | ||
1076 | xhci->error_bitmask |= 1 << 6; | ||
1077 | break; | ||
1078 | } | ||
1079 | xhci_dbg(xhci, "NEC firmware version %2x.%02x\n", | ||
1080 | NEC_FW_MAJOR(event->status), | ||
1081 | NEC_FW_MINOR(event->status)); | ||
1082 | break; | ||
1074 | default: | 1083 | default: |
1075 | /* Skip over unknown commands on the event ring */ | 1084 | /* Skip over unknown commands on the event ring */ |
1076 | xhci->error_bitmask |= 1 << 6; | 1085 | xhci->error_bitmask |= 1 << 6; |
@@ -1079,6 +1088,17 @@ bandwidth_change: | |||
1079 | inc_deq(xhci, xhci->cmd_ring, false); | 1088 | inc_deq(xhci, xhci->cmd_ring, false); |
1080 | } | 1089 | } |
1081 | 1090 | ||
1091 | static void handle_vendor_event(struct xhci_hcd *xhci, | ||
1092 | union xhci_trb *event) | ||
1093 | { | ||
1094 | u32 trb_type; | ||
1095 | |||
1096 | trb_type = TRB_FIELD_TO_TYPE(event->generic.field[3]); | ||
1097 | xhci_dbg(xhci, "Vendor specific event TRB type = %u\n", trb_type); | ||
1098 | if (trb_type == TRB_NEC_CMD_COMP && (xhci->quirks & XHCI_NEC_HOST)) | ||
1099 | handle_cmd_completion(xhci, &event->event_cmd); | ||
1100 | } | ||
1101 | |||
1082 | static void handle_port_status(struct xhci_hcd *xhci, | 1102 | static void handle_port_status(struct xhci_hcd *xhci, |
1083 | union xhci_trb *event) | 1103 | union xhci_trb *event) |
1084 | { | 1104 | { |
@@ -1659,7 +1679,10 @@ void xhci_handle_event(struct xhci_hcd *xhci) | |||
1659 | update_ptrs = 0; | 1679 | update_ptrs = 0; |
1660 | break; | 1680 | break; |
1661 | default: | 1681 | default: |
1662 | xhci->error_bitmask |= 1 << 3; | 1682 | if ((event->event_cmd.flags & TRB_TYPE_BITMASK) >= TRB_TYPE(48)) |
1683 | handle_vendor_event(xhci, event); | ||
1684 | else | ||
1685 | xhci->error_bitmask |= 1 << 3; | ||
1663 | } | 1686 | } |
1664 | /* Any of the above functions may drop and re-acquire the lock, so check | 1687 | /* Any of the above functions may drop and re-acquire the lock, so check |
1665 | * to make sure a watchdog timer didn't mark the host as non-responsive. | 1688 | * 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, | |||
2378 | false); | 2401 | false); |
2379 | } | 2402 | } |
2380 | 2403 | ||
2404 | int xhci_queue_vendor_command(struct xhci_hcd *xhci, | ||
2405 | u32 field1, u32 field2, u32 field3, u32 field4) | ||
2406 | { | ||
2407 | return queue_command(xhci, field1, field2, field3, field4, false); | ||
2408 | } | ||
2409 | |||
2381 | /* Queue a reset device command TRB */ | 2410 | /* Queue a reset device command TRB */ |
2382 | int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id) | 2411 | int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id) |
2383 | { | 2412 | { |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8a49c6716b69..27345cd04da0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -486,6 +486,9 @@ int xhci_run(struct usb_hcd *hcd) | |||
486 | 486 | ||
487 | if (NUM_TEST_NOOPS > 0) | 487 | if (NUM_TEST_NOOPS > 0) |
488 | doorbell = xhci_setup_one_noop(xhci); | 488 | doorbell = xhci_setup_one_noop(xhci); |
489 | if (xhci->quirks & XHCI_NEC_HOST) | ||
490 | xhci_queue_vendor_command(xhci, 0, 0, 0, | ||
491 | TRB_TYPE(TRB_NEC_GET_FW)); | ||
489 | 492 | ||
490 | if (xhci_start(xhci)) { | 493 | if (xhci_start(xhci)) { |
491 | xhci_halt(xhci); | 494 | xhci_halt(xhci); |
@@ -495,6 +498,8 @@ int xhci_run(struct usb_hcd *hcd) | |||
495 | xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp); | 498 | xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp); |
496 | if (doorbell) | 499 | if (doorbell) |
497 | (*doorbell)(xhci); | 500 | (*doorbell)(xhci); |
501 | if (xhci->quirks & XHCI_NEC_HOST) | ||
502 | xhci_ring_cmd_db(xhci); | ||
498 | 503 | ||
499 | xhci_dbg(xhci, "Finished xhci_run\n"); | 504 | xhci_dbg(xhci, "Finished xhci_run\n"); |
500 | return 0; | 505 | 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 { | |||
925 | /* TRB bit mask */ | 925 | /* TRB bit mask */ |
926 | #define TRB_TYPE_BITMASK (0xfc00) | 926 | #define TRB_TYPE_BITMASK (0xfc00) |
927 | #define TRB_TYPE(p) ((p) << 10) | 927 | #define TRB_TYPE(p) ((p) << 10) |
928 | #define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10) | ||
928 | /* TRB type IDs */ | 929 | /* TRB type IDs */ |
929 | /* bulk, interrupt, isoc scatter/gather, and control data stage */ | 930 | /* bulk, interrupt, isoc scatter/gather, and control data stage */ |
930 | #define TRB_NORMAL 1 | 931 | #define TRB_NORMAL 1 |
@@ -992,6 +993,14 @@ union xhci_trb { | |||
992 | #define TRB_MFINDEX_WRAP 39 | 993 | #define TRB_MFINDEX_WRAP 39 |
993 | /* TRB IDs 40-47 reserved, 48-63 is vendor-defined */ | 994 | /* TRB IDs 40-47 reserved, 48-63 is vendor-defined */ |
994 | 995 | ||
996 | /* Nec vendor-specific command completion event. */ | ||
997 | #define TRB_NEC_CMD_COMP 48 | ||
998 | /* Get NEC firmware revision. */ | ||
999 | #define TRB_NEC_GET_FW 49 | ||
1000 | |||
1001 | #define NEC_FW_MINOR(p) (((p) >> 0) & 0xff) | ||
1002 | #define NEC_FW_MAJOR(p) (((p) >> 8) & 0xff) | ||
1003 | |||
995 | /* | 1004 | /* |
996 | * TRBS_PER_SEGMENT must be a multiple of 4, | 1005 | * TRBS_PER_SEGMENT must be a multiple of 4, |
997 | * since the command ring is 64-byte aligned. | 1006 | * since the command ring is 64-byte aligned. |
@@ -1172,6 +1181,7 @@ struct xhci_hcd { | |||
1172 | unsigned int quirks; | 1181 | unsigned int quirks; |
1173 | #define XHCI_LINK_TRB_QUIRK (1 << 0) | 1182 | #define XHCI_LINK_TRB_QUIRK (1 << 0) |
1174 | #define XHCI_RESET_EP_QUIRK (1 << 1) | 1183 | #define XHCI_RESET_EP_QUIRK (1 << 1) |
1184 | #define XHCI_NEC_HOST (1 << 2) | ||
1175 | }; | 1185 | }; |
1176 | 1186 | ||
1177 | /* For testing purposes */ | 1187 | /* For testing purposes */ |
@@ -1379,6 +1389,8 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci); | |||
1379 | int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id); | 1389 | int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id); |
1380 | int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, | 1390 | int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, |
1381 | u32 slot_id); | 1391 | u32 slot_id); |
1392 | int xhci_queue_vendor_command(struct xhci_hcd *xhci, | ||
1393 | u32 field1, u32 field2, u32 field3, u32 field4); | ||
1382 | int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id, | 1394 | int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id, |
1383 | unsigned int ep_index); | 1395 | unsigned int ep_index); |
1384 | int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, | 1396 | int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, |