diff options
author | Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | 2013-07-29 11:42:14 -0400 |
---|---|---|
committer | Dan Williams <djbw@fb.com> | 2013-08-23 01:57:37 -0400 |
commit | e03bc654f85604bcd5304debb597f398d1d03778 (patch) | |
tree | 380052c9f15b3b01034dac678acc1b3fcf21bf37 /drivers | |
parent | 5733c38ae3473115ac7df3fe19bd2502149d8c51 (diff) |
mv_xor: support big endian systems using descriptor swap feature
The mv_xor driver had never been used in a big-endian context, and
therefore was not using the hardware features to support such an
execution environment. The hardware provides a "descriptor swap" bit
that automatically swaps the bytes of the DMA descriptors, within
blocks of 8 bytes. This requires a different DMA descriptor layout on
big-endian systems, as well as enabling this "descriptor swap" bit.
This mechanism is exactly identical to the one already used in the
mv643xx_eth network driver and the mvneta network driver.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Dan Williams <djbw@fb.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dma/mv_xor.c | 11 | ||||
-rw-r--r-- | drivers/dma/mv_xor.h | 28 |
2 files changed, 36 insertions, 3 deletions
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index c026b27f76e1..d332b9e3f9ce 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c | |||
@@ -64,7 +64,7 @@ static u32 mv_desc_get_src_addr(struct mv_xor_desc_slot *desc, | |||
64 | int src_idx) | 64 | int src_idx) |
65 | { | 65 | { |
66 | struct mv_xor_desc *hw_desc = desc->hw_desc; | 66 | struct mv_xor_desc *hw_desc = desc->hw_desc; |
67 | return hw_desc->phy_src_addr[src_idx]; | 67 | return hw_desc->phy_src_addr[mv_phy_src_idx(src_idx)]; |
68 | } | 68 | } |
69 | 69 | ||
70 | 70 | ||
@@ -107,7 +107,7 @@ static void mv_desc_set_src_addr(struct mv_xor_desc_slot *desc, | |||
107 | int index, dma_addr_t addr) | 107 | int index, dma_addr_t addr) |
108 | { | 108 | { |
109 | struct mv_xor_desc *hw_desc = desc->hw_desc; | 109 | struct mv_xor_desc *hw_desc = desc->hw_desc; |
110 | hw_desc->phy_src_addr[index] = addr; | 110 | hw_desc->phy_src_addr[mv_phy_src_idx(index)] = addr; |
111 | if (desc->type == DMA_XOR) | 111 | if (desc->type == DMA_XOR) |
112 | hw_desc->desc_command |= (1 << index); | 112 | hw_desc->desc_command |= (1 << index); |
113 | } | 113 | } |
@@ -192,6 +192,13 @@ static void mv_set_mode(struct mv_xor_chan *chan, | |||
192 | 192 | ||
193 | config &= ~0x7; | 193 | config &= ~0x7; |
194 | config |= op_mode; | 194 | config |= op_mode; |
195 | |||
196 | #if defined(__BIG_ENDIAN) | ||
197 | config |= XOR_DESCRIPTOR_SWAP; | ||
198 | #else | ||
199 | config &= ~XOR_DESCRIPTOR_SWAP; | ||
200 | #endif | ||
201 | |||
195 | writel_relaxed(config, XOR_CONFIG(chan)); | 202 | writel_relaxed(config, XOR_CONFIG(chan)); |
196 | chan->current_type = type; | 203 | chan->current_type = type; |
197 | } | 204 | } |
diff --git a/drivers/dma/mv_xor.h b/drivers/dma/mv_xor.h index c619359cb7fe..06b067f24c9b 100644 --- a/drivers/dma/mv_xor.h +++ b/drivers/dma/mv_xor.h | |||
@@ -29,8 +29,10 @@ | |||
29 | #define MV_XOR_THRESHOLD 1 | 29 | #define MV_XOR_THRESHOLD 1 |
30 | #define MV_XOR_MAX_CHANNELS 2 | 30 | #define MV_XOR_MAX_CHANNELS 2 |
31 | 31 | ||
32 | /* Values for the XOR_CONFIG register */ | ||
32 | #define XOR_OPERATION_MODE_XOR 0 | 33 | #define XOR_OPERATION_MODE_XOR 0 |
33 | #define XOR_OPERATION_MODE_MEMCPY 2 | 34 | #define XOR_OPERATION_MODE_MEMCPY 2 |
35 | #define XOR_DESCRIPTOR_SWAP BIT(14) | ||
34 | 36 | ||
35 | #define XOR_CURR_DESC(chan) (chan->mmr_base + 0x210 + (chan->idx * 4)) | 37 | #define XOR_CURR_DESC(chan) (chan->mmr_base + 0x210 + (chan->idx * 4)) |
36 | #define XOR_NEXT_DESC(chan) (chan->mmr_base + 0x200 + (chan->idx * 4)) | 38 | #define XOR_NEXT_DESC(chan) (chan->mmr_base + 0x200 + (chan->idx * 4)) |
@@ -143,7 +145,16 @@ struct mv_xor_desc_slot { | |||
143 | #endif | 145 | #endif |
144 | }; | 146 | }; |
145 | 147 | ||
146 | /* This structure describes XOR descriptor size 64bytes */ | 148 | /* |
149 | * This structure describes XOR descriptor size 64bytes. The | ||
150 | * mv_phy_src_idx() macro must be used when indexing the values of the | ||
151 | * phy_src_addr[] array. This is due to the fact that the 'descriptor | ||
152 | * swap' feature, used on big endian systems, swaps descriptors data | ||
153 | * within blocks of 8 bytes. So two consecutive values of the | ||
154 | * phy_src_addr[] array are actually swapped in big-endian, which | ||
155 | * explains the different mv_phy_src_idx() implementation. | ||
156 | */ | ||
157 | #if defined(__LITTLE_ENDIAN) | ||
147 | struct mv_xor_desc { | 158 | struct mv_xor_desc { |
148 | u32 status; /* descriptor execution status */ | 159 | u32 status; /* descriptor execution status */ |
149 | u32 crc32_result; /* result of CRC-32 calculation */ | 160 | u32 crc32_result; /* result of CRC-32 calculation */ |
@@ -155,6 +166,21 @@ struct mv_xor_desc { | |||
155 | u32 reserved0; | 166 | u32 reserved0; |
156 | u32 reserved1; | 167 | u32 reserved1; |
157 | }; | 168 | }; |
169 | #define mv_phy_src_idx(src_idx) (src_idx) | ||
170 | #else | ||
171 | struct mv_xor_desc { | ||
172 | u32 crc32_result; /* result of CRC-32 calculation */ | ||
173 | u32 status; /* descriptor execution status */ | ||
174 | u32 phy_next_desc; /* next descriptor address pointer */ | ||
175 | u32 desc_command; /* type of operation to be carried out */ | ||
176 | u32 phy_dest_addr; /* destination block address */ | ||
177 | u32 byte_count; /* size of src/dst blocks in bytes */ | ||
178 | u32 phy_src_addr[8]; /* source block addresses */ | ||
179 | u32 reserved1; | ||
180 | u32 reserved0; | ||
181 | }; | ||
182 | #define mv_phy_src_idx(src_idx) (src_idx ^ 1) | ||
183 | #endif | ||
158 | 184 | ||
159 | #define to_mv_sw_desc(addr_hw_desc) \ | 185 | #define to_mv_sw_desc(addr_hw_desc) \ |
160 | container_of(addr_hw_desc, struct mv_xor_desc_slot, hw_desc) | 186 | container_of(addr_hw_desc, struct mv_xor_desc_slot, hw_desc) |