diff options
Diffstat (limited to 'arch/powerpc/sysdev/bestcomm')
-rw-r--r-- | arch/powerpc/sysdev/bestcomm/ata.c | 3 | ||||
-rw-r--r-- | arch/powerpc/sysdev/bestcomm/ata.h | 19 | ||||
-rw-r--r-- | arch/powerpc/sysdev/bestcomm/bestcomm.c | 7 | ||||
-rw-r--r-- | arch/powerpc/sysdev/bestcomm/bestcomm.h | 61 | ||||
-rw-r--r-- | arch/powerpc/sysdev/bestcomm/bestcomm_priv.h | 20 |
5 files changed, 71 insertions, 39 deletions
diff --git a/arch/powerpc/sysdev/bestcomm/ata.c b/arch/powerpc/sysdev/bestcomm/ata.c index 1f5258fb38c3..901c9f91e5dd 100644 --- a/arch/powerpc/sysdev/bestcomm/ata.c +++ b/arch/powerpc/sysdev/bestcomm/ata.c | |||
@@ -61,6 +61,9 @@ bcom_ata_init(int queue_len, int maxbufsize) | |||
61 | struct bcom_ata_var *var; | 61 | struct bcom_ata_var *var; |
62 | struct bcom_ata_inc *inc; | 62 | struct bcom_ata_inc *inc; |
63 | 63 | ||
64 | /* Prefetch breaks ATA DMA. Turn it off for ATA DMA */ | ||
65 | bcom_disable_prefetch(); | ||
66 | |||
64 | tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_ata_bd), 0); | 67 | tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_ata_bd), 0); |
65 | if (!tsk) | 68 | if (!tsk) |
66 | return NULL; | 69 | return NULL; |
diff --git a/arch/powerpc/sysdev/bestcomm/ata.h b/arch/powerpc/sysdev/bestcomm/ata.h index 10982769c465..0b2371811334 100644 --- a/arch/powerpc/sysdev/bestcomm/ata.h +++ b/arch/powerpc/sysdev/bestcomm/ata.h | |||
@@ -16,22 +16,15 @@ | |||
16 | 16 | ||
17 | struct bcom_ata_bd { | 17 | struct bcom_ata_bd { |
18 | u32 status; | 18 | u32 status; |
19 | u32 dst_pa; | ||
20 | u32 src_pa; | 19 | u32 src_pa; |
20 | u32 dst_pa; | ||
21 | }; | 21 | }; |
22 | 22 | ||
23 | extern struct bcom_task * | 23 | extern struct bcom_task * bcom_ata_init(int queue_len, int maxbufsize); |
24 | bcom_ata_init(int queue_len, int maxbufsize); | 24 | extern void bcom_ata_rx_prepare(struct bcom_task *tsk); |
25 | 25 | extern void bcom_ata_tx_prepare(struct bcom_task *tsk); | |
26 | extern void | 26 | extern void bcom_ata_reset_bd(struct bcom_task *tsk); |
27 | bcom_ata_rx_prepare(struct bcom_task *tsk); | 27 | extern void bcom_ata_release(struct bcom_task *tsk); |
28 | |||
29 | extern void | ||
30 | bcom_ata_tx_prepare(struct bcom_task *tsk); | ||
31 | |||
32 | extern void | ||
33 | bcom_ata_reset_bd(struct bcom_task *tsk); | ||
34 | |||
35 | 28 | ||
36 | #endif /* __BESTCOMM_ATA_H__ */ | 29 | #endif /* __BESTCOMM_ATA_H__ */ |
37 | 30 | ||
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c index 446c9ea85b30..378ebd9aac18 100644 --- a/arch/powerpc/sysdev/bestcomm/bestcomm.c +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c | |||
@@ -279,7 +279,6 @@ bcom_engine_init(void) | |||
279 | int task; | 279 | int task; |
280 | phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa; | 280 | phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa; |
281 | unsigned int tdt_size, ctx_size, var_size, fdt_size; | 281 | unsigned int tdt_size, ctx_size, var_size, fdt_size; |
282 | u16 regval; | ||
283 | 282 | ||
284 | /* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */ | 283 | /* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */ |
285 | tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt); | 284 | tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt); |
@@ -331,10 +330,8 @@ bcom_engine_init(void) | |||
331 | out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS); | 330 | out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS); |
332 | 331 | ||
333 | /* Disable COMM Bus Prefetch on the original 5200; it's broken */ | 332 | /* Disable COMM Bus Prefetch on the original 5200; it's broken */ |
334 | if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR) { | 333 | if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR) |
335 | regval = in_be16(&bcom_eng->regs->PtdCntrl); | 334 | bcom_disable_prefetch(); |
336 | out_be16(&bcom_eng->regs->PtdCntrl, regval | 1); | ||
337 | } | ||
338 | 335 | ||
339 | /* Init lock */ | 336 | /* Init lock */ |
340 | spin_lock_init(&bcom_eng->lock); | 337 | spin_lock_init(&bcom_eng->lock); |
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.h b/arch/powerpc/sysdev/bestcomm/bestcomm.h index c960a8b49655..23a95f80dfdb 100644 --- a/arch/powerpc/sysdev/bestcomm/bestcomm.h +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.h | |||
@@ -16,8 +16,19 @@ | |||
16 | #ifndef __BESTCOMM_H__ | 16 | #ifndef __BESTCOMM_H__ |
17 | #define __BESTCOMM_H__ | 17 | #define __BESTCOMM_H__ |
18 | 18 | ||
19 | struct bcom_bd; /* defined later on ... */ | 19 | /** |
20 | 20 | * struct bcom_bd - Structure describing a generic BestComm buffer descriptor | |
21 | * @status: The current status of this buffer. Exact meaning depends on the | ||
22 | * task type | ||
23 | * @data: An array of u32 extra data. Size of array is task dependant. | ||
24 | * | ||
25 | * Note: Don't dereference a bcom_bd pointer as an array. The size of the | ||
26 | * bcom_bd is variable. Use bcom_get_bd() instead. | ||
27 | */ | ||
28 | struct bcom_bd { | ||
29 | u32 status; | ||
30 | u32 data[0]; /* variable payload size */ | ||
31 | }; | ||
21 | 32 | ||
22 | /* ======================================================================== */ | 33 | /* ======================================================================== */ |
23 | /* Generic task management */ | 34 | /* Generic task management */ |
@@ -84,17 +95,6 @@ bcom_get_task_irq(struct bcom_task *tsk) { | |||
84 | /* BD based tasks helpers */ | 95 | /* BD based tasks helpers */ |
85 | /* ======================================================================== */ | 96 | /* ======================================================================== */ |
86 | 97 | ||
87 | /** | ||
88 | * struct bcom_bd - Structure describing a generic BestComm buffer descriptor | ||
89 | * @status: The current status of this buffer. Exact meaning depends on the | ||
90 | * task type | ||
91 | * @data: An array of u32 whose meaning depends on the task type. | ||
92 | */ | ||
93 | struct bcom_bd { | ||
94 | u32 status; | ||
95 | u32 data[1]; /* variable, but at least 1 */ | ||
96 | }; | ||
97 | |||
98 | #define BCOM_BD_READY 0x40000000ul | 98 | #define BCOM_BD_READY 0x40000000ul |
99 | 99 | ||
100 | /** _bcom_next_index - Get next input index. | 100 | /** _bcom_next_index - Get next input index. |
@@ -140,15 +140,31 @@ bcom_queue_full(struct bcom_task *tsk) | |||
140 | } | 140 | } |
141 | 141 | ||
142 | /** | 142 | /** |
143 | * bcom_get_bd - Get a BD from the queue | ||
144 | * @tsk: The BestComm task structure | ||
145 | * index: Index of the BD to fetch | ||
146 | */ | ||
147 | static inline struct bcom_bd | ||
148 | *bcom_get_bd(struct bcom_task *tsk, unsigned int index) | ||
149 | { | ||
150 | /* A cast to (void*) so the address can be incremented by the | ||
151 | * real size instead of by sizeof(struct bcom_bd) */ | ||
152 | return ((void *)tsk->bd) + (index * tsk->bd_size); | ||
153 | } | ||
154 | |||
155 | /** | ||
143 | * bcom_buffer_done - Checks if a BestComm | 156 | * bcom_buffer_done - Checks if a BestComm |
144 | * @tsk: The BestComm task structure | 157 | * @tsk: The BestComm task structure |
145 | */ | 158 | */ |
146 | static inline int | 159 | static inline int |
147 | bcom_buffer_done(struct bcom_task *tsk) | 160 | bcom_buffer_done(struct bcom_task *tsk) |
148 | { | 161 | { |
162 | struct bcom_bd *bd; | ||
149 | if (bcom_queue_empty(tsk)) | 163 | if (bcom_queue_empty(tsk)) |
150 | return 0; | 164 | return 0; |
151 | return !(tsk->bd[tsk->outdex].status & BCOM_BD_READY); | 165 | |
166 | bd = bcom_get_bd(tsk, tsk->outdex); | ||
167 | return !(bd->status & BCOM_BD_READY); | ||
152 | } | 168 | } |
153 | 169 | ||
154 | /** | 170 | /** |
@@ -160,16 +176,21 @@ bcom_buffer_done(struct bcom_task *tsk) | |||
160 | static inline struct bcom_bd * | 176 | static inline struct bcom_bd * |
161 | bcom_prepare_next_buffer(struct bcom_task *tsk) | 177 | bcom_prepare_next_buffer(struct bcom_task *tsk) |
162 | { | 178 | { |
163 | tsk->bd[tsk->index].status = 0; /* cleanup last status */ | 179 | struct bcom_bd *bd; |
164 | return &tsk->bd[tsk->index]; | 180 | |
181 | bd = bcom_get_bd(tsk, tsk->index); | ||
182 | bd->status = 0; /* cleanup last status */ | ||
183 | return bd; | ||
165 | } | 184 | } |
166 | 185 | ||
167 | static inline void | 186 | static inline void |
168 | bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie) | 187 | bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie) |
169 | { | 188 | { |
189 | struct bcom_bd *bd = bcom_get_bd(tsk, tsk->index); | ||
190 | |||
170 | tsk->cookie[tsk->index] = cookie; | 191 | tsk->cookie[tsk->index] = cookie; |
171 | mb(); /* ensure the bd is really up-to-date */ | 192 | mb(); /* ensure the bd is really up-to-date */ |
172 | tsk->bd[tsk->index].status |= BCOM_BD_READY; | 193 | bd->status |= BCOM_BD_READY; |
173 | tsk->index = _bcom_next_index(tsk); | 194 | tsk->index = _bcom_next_index(tsk); |
174 | if (tsk->flags & BCOM_FLAGS_ENABLE_TASK) | 195 | if (tsk->flags & BCOM_FLAGS_ENABLE_TASK) |
175 | bcom_enable(tsk); | 196 | bcom_enable(tsk); |
@@ -179,10 +200,12 @@ static inline void * | |||
179 | bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd) | 200 | bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd) |
180 | { | 201 | { |
181 | void *cookie = tsk->cookie[tsk->outdex]; | 202 | void *cookie = tsk->cookie[tsk->outdex]; |
203 | struct bcom_bd *bd = bcom_get_bd(tsk, tsk->outdex); | ||
204 | |||
182 | if (p_status) | 205 | if (p_status) |
183 | *p_status = tsk->bd[tsk->outdex].status; | 206 | *p_status = bd->status; |
184 | if (p_bd) | 207 | if (p_bd) |
185 | *p_bd = &tsk->bd[tsk->outdex]; | 208 | *p_bd = bd; |
186 | tsk->outdex = _bcom_next_outdex(tsk); | 209 | tsk->outdex = _bcom_next_outdex(tsk); |
187 | return cookie; | 210 | return cookie; |
188 | } | 211 | } |
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h index 866a2915ef2f..eb0d1c883c31 100644 --- a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h +++ b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h | |||
@@ -198,8 +198,8 @@ struct bcom_task_header { | |||
198 | #define BCOM_IPR_SCTMR_1 2 | 198 | #define BCOM_IPR_SCTMR_1 2 |
199 | #define BCOM_IPR_FEC_RX 6 | 199 | #define BCOM_IPR_FEC_RX 6 |
200 | #define BCOM_IPR_FEC_TX 5 | 200 | #define BCOM_IPR_FEC_TX 5 |
201 | #define BCOM_IPR_ATA_RX 4 | 201 | #define BCOM_IPR_ATA_RX 7 |
202 | #define BCOM_IPR_ATA_TX 3 | 202 | #define BCOM_IPR_ATA_TX 7 |
203 | #define BCOM_IPR_SCPCI_RX 2 | 203 | #define BCOM_IPR_SCPCI_RX 2 |
204 | #define BCOM_IPR_SCPCI_TX 2 | 204 | #define BCOM_IPR_SCPCI_TX 2 |
205 | #define BCOM_IPR_PSC3_RX 2 | 205 | #define BCOM_IPR_PSC3_RX 2 |
@@ -241,6 +241,22 @@ extern void bcom_set_initiator(int task, int initiator); | |||
241 | 241 | ||
242 | #define TASK_ENABLE 0x8000 | 242 | #define TASK_ENABLE 0x8000 |
243 | 243 | ||
244 | /** | ||
245 | * bcom_disable_prefetch - Hook to disable bus prefetching | ||
246 | * | ||
247 | * ATA DMA and the original MPC5200 need this due to silicon bugs. At the | ||
248 | * moment disabling prefetch is a one-way street. There is no mechanism | ||
249 | * in place to turn prefetch back on after it has been disabled. There is | ||
250 | * no reason it couldn't be done, it would just be more complex to implement. | ||
251 | */ | ||
252 | static inline void bcom_disable_prefetch(void) | ||
253 | { | ||
254 | u16 regval; | ||
255 | |||
256 | regval = in_be16(&bcom_eng->regs->PtdCntrl); | ||
257 | out_be16(&bcom_eng->regs->PtdCntrl, regval | 1); | ||
258 | }; | ||
259 | |||
244 | static inline void | 260 | static inline void |
245 | bcom_enable_task(int task) | 261 | bcom_enable_task(int task) |
246 | { | 262 | { |