aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/bestcomm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/bestcomm')
-rw-r--r--arch/powerpc/sysdev/bestcomm/ata.c3
-rw-r--r--arch/powerpc/sysdev/bestcomm/ata.h19
-rw-r--r--arch/powerpc/sysdev/bestcomm/bestcomm.c7
-rw-r--r--arch/powerpc/sysdev/bestcomm/bestcomm.h61
-rw-r--r--arch/powerpc/sysdev/bestcomm/bestcomm_priv.h20
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
17struct bcom_ata_bd { 17struct 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
23extern struct bcom_task * 23extern struct bcom_task * bcom_ata_init(int queue_len, int maxbufsize);
24bcom_ata_init(int queue_len, int maxbufsize); 24extern void bcom_ata_rx_prepare(struct bcom_task *tsk);
25 25extern void bcom_ata_tx_prepare(struct bcom_task *tsk);
26extern void 26extern void bcom_ata_reset_bd(struct bcom_task *tsk);
27bcom_ata_rx_prepare(struct bcom_task *tsk); 27extern void bcom_ata_release(struct bcom_task *tsk);
28
29extern void
30bcom_ata_tx_prepare(struct bcom_task *tsk);
31
32extern void
33bcom_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
19struct 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 */
28struct 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 */
93struct 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 */
147static 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 */
146static inline int 159static inline int
147bcom_buffer_done(struct bcom_task *tsk) 160bcom_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)
160static inline struct bcom_bd * 176static inline struct bcom_bd *
161bcom_prepare_next_buffer(struct bcom_task *tsk) 177bcom_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
167static inline void 186static inline void
168bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie) 187bcom_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 *
179bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd) 200bcom_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 */
252static 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
244static inline void 260static inline void
245bcom_enable_task(int task) 261bcom_enable_task(int task)
246{ 262{