diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2009-07-27 15:03:31 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-07-28 17:31:12 -0400 |
commit | 8e595a5d30a5ee4bb745d4da6439d73ed7d91054 (patch) | |
tree | 0050cb2c24643b602a8b3c40adef3e7b73fe81fc /drivers/usb/host/xhci.h | |
parent | b11069f5f6ce6e359f853e908b0917303fcdec8f (diff) |
USB: xhci: Represent 64-bit addresses with one u64.
There are several xHCI data structures that use two 32-bit fields to
represent a 64-bit address. Since some architectures don't support 64-bit
PCI writes, the fields need to be written in two 32-bit writes. The xHCI
specification says that if a platform is incapable of generating 64-bit
writes, software must write the low 32-bits first, then the high 32-bits.
Hardware that supports 64-bit addressing will wait for the high 32-bit
write before reading the revised value, and hardware that only supports
32-bit writes will ignore the high 32-bit write.
Previous xHCI code represented 64-bit addresses with two u32 values. This
lead to buggy code that would write the 32-bits in the wrong order, or
forget to write the upper 32-bits. Change the two u32s to one u64 and
create a function call to write all 64-bit addresses in the proper order.
This new function could be modified in the future if all platforms support
64-bit writes.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci.h')
-rw-r--r-- | drivers/usb/host/xhci.h | 65 |
1 files changed, 45 insertions, 20 deletions
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index cde648a524f5..60770c89132b 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/usb.h> | 26 | #include <linux/usb.h> |
27 | #include <linux/timer.h> | 27 | #include <linux/timer.h> |
28 | #include <linux/kernel.h> | ||
28 | 29 | ||
29 | #include "../core/hcd.h" | 30 | #include "../core/hcd.h" |
30 | /* Code sharing between pci-quirks and xhci hcd */ | 31 | /* Code sharing between pci-quirks and xhci hcd */ |
@@ -42,14 +43,6 @@ | |||
42 | * xHCI register interface. | 43 | * xHCI register interface. |
43 | * This corresponds to the eXtensible Host Controller Interface (xHCI) | 44 | * This corresponds to the eXtensible Host Controller Interface (xHCI) |
44 | * Revision 0.95 specification | 45 | * Revision 0.95 specification |
45 | * | ||
46 | * Registers should always be accessed with double word or quad word accesses. | ||
47 | * | ||
48 | * Some xHCI implementations may support 64-bit address pointers. Registers | ||
49 | * with 64-bit address pointers should be written to with dword accesses by | ||
50 | * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second. | ||
51 | * xHCI implementations that do not support 64-bit address pointers will ignore | ||
52 | * the high dword, and write order is irrelevant. | ||
53 | */ | 46 | */ |
54 | 47 | ||
55 | /** | 48 | /** |
@@ -166,10 +159,10 @@ struct xhci_op_regs { | |||
166 | u32 reserved1; | 159 | u32 reserved1; |
167 | u32 reserved2; | 160 | u32 reserved2; |
168 | u32 dev_notification; | 161 | u32 dev_notification; |
169 | u32 cmd_ring[2]; | 162 | u64 cmd_ring; |
170 | /* rsvd: offset 0x20-2F */ | 163 | /* rsvd: offset 0x20-2F */ |
171 | u32 reserved3[4]; | 164 | u32 reserved3[4]; |
172 | u32 dcbaa_ptr[2]; | 165 | u64 dcbaa_ptr; |
173 | u32 config_reg; | 166 | u32 config_reg; |
174 | /* rsvd: offset 0x3C-3FF */ | 167 | /* rsvd: offset 0x3C-3FF */ |
175 | u32 reserved4[241]; | 168 | u32 reserved4[241]; |
@@ -254,7 +247,7 @@ struct xhci_op_regs { | |||
254 | #define CMD_RING_RUNNING (1 << 3) | 247 | #define CMD_RING_RUNNING (1 << 3) |
255 | /* bits 4:5 reserved and should be preserved */ | 248 | /* bits 4:5 reserved and should be preserved */ |
256 | /* Command Ring pointer - bit mask for the lower 32 bits. */ | 249 | /* Command Ring pointer - bit mask for the lower 32 bits. */ |
257 | #define CMD_RING_ADDR_MASK (0xffffffc0) | 250 | #define CMD_RING_RSVD_BITS (0x3f) |
258 | 251 | ||
259 | /* CONFIG - Configure Register - config_reg bitmasks */ | 252 | /* CONFIG - Configure Register - config_reg bitmasks */ |
260 | /* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */ | 253 | /* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */ |
@@ -382,8 +375,8 @@ struct xhci_intr_reg { | |||
382 | u32 irq_control; | 375 | u32 irq_control; |
383 | u32 erst_size; | 376 | u32 erst_size; |
384 | u32 rsvd; | 377 | u32 rsvd; |
385 | u32 erst_base[2]; | 378 | u64 erst_base; |
386 | u32 erst_dequeue[2]; | 379 | u64 erst_dequeue; |
387 | }; | 380 | }; |
388 | 381 | ||
389 | /* irq_pending bitmasks */ | 382 | /* irq_pending bitmasks */ |
@@ -538,7 +531,7 @@ struct xhci_slot_ctx { | |||
538 | struct xhci_ep_ctx { | 531 | struct xhci_ep_ctx { |
539 | u32 ep_info; | 532 | u32 ep_info; |
540 | u32 ep_info2; | 533 | u32 ep_info2; |
541 | u32 deq[2]; | 534 | u64 deq; |
542 | u32 tx_info; | 535 | u32 tx_info; |
543 | /* offset 0x14 - 0x1f reserved for HC internal use */ | 536 | /* offset 0x14 - 0x1f reserved for HC internal use */ |
544 | u32 reserved[3]; | 537 | u32 reserved[3]; |
@@ -641,7 +634,7 @@ struct xhci_virt_device { | |||
641 | */ | 634 | */ |
642 | struct xhci_device_context_array { | 635 | struct xhci_device_context_array { |
643 | /* 64-bit device addresses; we only write 32-bit addresses */ | 636 | /* 64-bit device addresses; we only write 32-bit addresses */ |
644 | u32 dev_context_ptrs[2*MAX_HC_SLOTS]; | 637 | u64 dev_context_ptrs[MAX_HC_SLOTS]; |
645 | /* private xHCD pointers */ | 638 | /* private xHCD pointers */ |
646 | dma_addr_t dma; | 639 | dma_addr_t dma; |
647 | }; | 640 | }; |
@@ -654,7 +647,7 @@ struct xhci_device_context_array { | |||
654 | 647 | ||
655 | struct xhci_stream_ctx { | 648 | struct xhci_stream_ctx { |
656 | /* 64-bit stream ring address, cycle state, and stream type */ | 649 | /* 64-bit stream ring address, cycle state, and stream type */ |
657 | u32 stream_ring[2]; | 650 | u64 stream_ring; |
658 | /* offset 0x14 - 0x1f reserved for HC internal use */ | 651 | /* offset 0x14 - 0x1f reserved for HC internal use */ |
659 | u32 reserved[2]; | 652 | u32 reserved[2]; |
660 | }; | 653 | }; |
@@ -662,7 +655,7 @@ struct xhci_stream_ctx { | |||
662 | 655 | ||
663 | struct xhci_transfer_event { | 656 | struct xhci_transfer_event { |
664 | /* 64-bit buffer address, or immediate data */ | 657 | /* 64-bit buffer address, or immediate data */ |
665 | u32 buffer[2]; | 658 | u64 buffer; |
666 | u32 transfer_len; | 659 | u32 transfer_len; |
667 | /* This field is interpreted differently based on the type of TRB */ | 660 | /* This field is interpreted differently based on the type of TRB */ |
668 | u32 flags; | 661 | u32 flags; |
@@ -744,7 +737,7 @@ struct xhci_transfer_event { | |||
744 | 737 | ||
745 | struct xhci_link_trb { | 738 | struct xhci_link_trb { |
746 | /* 64-bit segment pointer*/ | 739 | /* 64-bit segment pointer*/ |
747 | u32 segment_ptr[2]; | 740 | u64 segment_ptr; |
748 | u32 intr_target; | 741 | u32 intr_target; |
749 | u32 control; | 742 | u32 control; |
750 | }; | 743 | }; |
@@ -755,7 +748,7 @@ struct xhci_link_trb { | |||
755 | /* Command completion event TRB */ | 748 | /* Command completion event TRB */ |
756 | struct xhci_event_cmd { | 749 | struct xhci_event_cmd { |
757 | /* Pointer to command TRB, or the value passed by the event data trb */ | 750 | /* Pointer to command TRB, or the value passed by the event data trb */ |
758 | u32 cmd_trb[2]; | 751 | u64 cmd_trb; |
759 | u32 status; | 752 | u32 status; |
760 | u32 flags; | 753 | u32 flags; |
761 | }; | 754 | }; |
@@ -943,7 +936,7 @@ struct xhci_ring { | |||
943 | 936 | ||
944 | struct xhci_erst_entry { | 937 | struct xhci_erst_entry { |
945 | /* 64-bit event ring segment address */ | 938 | /* 64-bit event ring segment address */ |
946 | u32 seg_addr[2]; | 939 | u64 seg_addr; |
947 | u32 seg_size; | 940 | u32 seg_size; |
948 | /* Set to zero */ | 941 | /* Set to zero */ |
949 | u32 rsvd; | 942 | u32 rsvd; |
@@ -1079,6 +1072,38 @@ static inline void xhci_writel(struct xhci_hcd *xhci, | |||
1079 | writel(val, regs); | 1072 | writel(val, regs); |
1080 | } | 1073 | } |
1081 | 1074 | ||
1075 | /* | ||
1076 | * Registers should always be accessed with double word or quad word accesses. | ||
1077 | * | ||
1078 | * Some xHCI implementations may support 64-bit address pointers. Registers | ||
1079 | * with 64-bit address pointers should be written to with dword accesses by | ||
1080 | * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second. | ||
1081 | * xHCI implementations that do not support 64-bit address pointers will ignore | ||
1082 | * the high dword, and write order is irrelevant. | ||
1083 | */ | ||
1084 | static inline u64 xhci_read_64(const struct xhci_hcd *xhci, | ||
1085 | __u64 __iomem *regs) | ||
1086 | { | ||
1087 | __u32 __iomem *ptr = (__u32 __iomem *) regs; | ||
1088 | u64 val_lo = readl(ptr); | ||
1089 | u64 val_hi = readl(ptr + 1); | ||
1090 | return val_lo + (val_hi << 32); | ||
1091 | } | ||
1092 | static inline void xhci_write_64(struct xhci_hcd *xhci, | ||
1093 | const u64 val, __u64 __iomem *regs) | ||
1094 | { | ||
1095 | __u32 __iomem *ptr = (__u32 __iomem *) regs; | ||
1096 | u32 val_lo = lower_32_bits(val); | ||
1097 | u32 val_hi = upper_32_bits(val); | ||
1098 | |||
1099 | if (!in_interrupt()) | ||
1100 | xhci_dbg(xhci, | ||
1101 | "`MEM_WRITE_DWORD(3'b000, 64'h%p, 64'h%0lx, 4'hf);\n", | ||
1102 | regs, (long unsigned int) val); | ||
1103 | writel(val_lo, ptr); | ||
1104 | writel(val_hi, ptr + 1); | ||
1105 | } | ||
1106 | |||
1082 | /* xHCI debugging */ | 1107 | /* xHCI debugging */ |
1083 | void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num); | 1108 | void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num); |
1084 | void xhci_print_registers(struct xhci_hcd *xhci); | 1109 | void xhci_print_registers(struct xhci_hcd *xhci); |