2 * Bestcomm FEC tasks driver
5 * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
6 * Copyright (C) 2003-2004 MontaVista, Software, Inc.
7 * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
9 * This file is licensed under the terms of the GNU General Public License
10 * version 2. This program is licensed "as is" without any warranty of any
11 * kind, whether express or implied.
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/types.h>
20 #include "bestcomm_priv.h"
24 /* ======================================================================== */
25 /* Task image/var/inc */
26 /* ======================================================================== */
28 /* fec tasks images */
29 extern u32 bcom_fec_rx_task
[];
30 extern u32 bcom_fec_tx_task
[];
32 /* rx task vars that need to be set before enabling the task */
33 struct bcom_fec_rx_var
{
34 u32 enable
; /* (u16*) address of task's control register */
35 u32 fifo
; /* (u32*) address of fec's fifo */
36 u32 bd_base
; /* (struct bcom_bd*) beginning of ring buffer */
37 u32 bd_last
; /* (struct bcom_bd*) end of ring buffer */
38 u32 bd_start
; /* (struct bcom_bd*) current bd */
39 u32 buffer_size
; /* size of receive buffer */
42 /* rx task incs that need to be set before enabling the task */
43 struct bcom_fec_rx_inc
{
52 /* tx task vars that need to be set before enabling the task */
53 struct bcom_fec_tx_var
{
54 u32 DRD
; /* (u32*) address of self-modified DRD */
55 u32 fifo
; /* (u32*) address of fec's fifo */
56 u32 enable
; /* (u16*) address of task's control register */
57 u32 bd_base
; /* (struct bcom_bd*) beginning of ring buffer */
58 u32 bd_last
; /* (struct bcom_bd*) end of ring buffer */
59 u32 bd_start
; /* (struct bcom_bd*) current bd */
60 u32 buffer_size
; /* set by uCode for each packet */
63 /* tx task incs that need to be set before enabling the task */
64 struct bcom_fec_tx_inc
{
73 /* private structure in the task */
74 struct bcom_fec_priv
{
80 /* ======================================================================== */
81 /* Task support code */
82 /* ======================================================================== */
85 bcom_fec_rx_init(int queue_len
, phys_addr_t fifo
, int maxbufsize
)
87 struct bcom_task
*tsk
;
88 struct bcom_fec_priv
*priv
;
90 tsk
= bcom_task_alloc(queue_len
, sizeof(struct bcom_fec_bd
),
91 sizeof(struct bcom_fec_priv
));
95 tsk
->flags
= BCOM_FLAGS_NONE
;
99 priv
->maxbufsize
= maxbufsize
;
101 if (bcom_fec_rx_reset(tsk
)) {
108 EXPORT_SYMBOL_GPL(bcom_fec_rx_init
);
111 bcom_fec_rx_reset(struct bcom_task
*tsk
)
113 struct bcom_fec_priv
*priv
= tsk
->priv
;
114 struct bcom_fec_rx_var
*var
;
115 struct bcom_fec_rx_inc
*inc
;
117 /* Shutdown the task */
118 bcom_disable_task(tsk
->tasknum
);
120 /* Reset the microcode */
121 var
= (struct bcom_fec_rx_var
*) bcom_task_var(tsk
->tasknum
);
122 inc
= (struct bcom_fec_rx_inc
*) bcom_task_inc(tsk
->tasknum
);
124 if (bcom_load_image(tsk
->tasknum
, bcom_fec_rx_task
))
127 var
->enable
= bcom_eng
->regs_base
+
128 offsetof(struct mpc52xx_sdma
, tcr
[tsk
->tasknum
]);
129 var
->fifo
= (u32
) priv
->fifo
;
130 var
->bd_base
= tsk
->bd_pa
;
131 var
->bd_last
= tsk
->bd_pa
+ ((tsk
->num_bd
-1) * tsk
->bd_size
);
132 var
->bd_start
= tsk
->bd_pa
;
133 var
->buffer_size
= priv
->maxbufsize
;
135 inc
->incr_bytes
= -(s16
)sizeof(u32
); /* These should be in the */
136 inc
->incr_dst
= sizeof(u32
); /* task image, but we stick */
137 inc
->incr_dst_ma
= sizeof(u8
); /* to the official ones */
143 memset(tsk
->bd
, 0x00, tsk
->num_bd
* tsk
->bd_size
);
145 /* Configure some stuff */
146 bcom_set_task_pragma(tsk
->tasknum
, BCOM_FEC_RX_BD_PRAGMA
);
147 bcom_set_task_auto_start(tsk
->tasknum
, tsk
->tasknum
);
149 out_8(&bcom_eng
->regs
->ipr
[BCOM_INITIATOR_FEC_RX
], BCOM_IPR_FEC_RX
);
151 out_be32(&bcom_eng
->regs
->IntPend
, 1<<tsk
->tasknum
); /* Clear ints */
155 EXPORT_SYMBOL_GPL(bcom_fec_rx_reset
);
158 bcom_fec_rx_release(struct bcom_task
*tsk
)
160 /* Nothing special for the FEC tasks */
163 EXPORT_SYMBOL_GPL(bcom_fec_rx_release
);
167 /* Return 2nd to last DRD */
168 /* This is an ugly hack, but at least it's only done
169 once at initialization */
170 static u32
*self_modified_drd(int tasknum
)
177 num_descs
= bcom_task_num_descs(tasknum
);
178 desc
= bcom_task_desc(tasknum
) + num_descs
- 1;
180 for (i
=0; i
<num_descs
; i
++, desc
--)
181 if (bcom_desc_is_drd(*desc
) && ++drd_count
== 3)
187 bcom_fec_tx_init(int queue_len
, phys_addr_t fifo
)
189 struct bcom_task
*tsk
;
190 struct bcom_fec_priv
*priv
;
192 tsk
= bcom_task_alloc(queue_len
, sizeof(struct bcom_fec_bd
),
193 sizeof(struct bcom_fec_priv
));
197 tsk
->flags
= BCOM_FLAGS_ENABLE_TASK
;
202 if (bcom_fec_tx_reset(tsk
)) {
209 EXPORT_SYMBOL_GPL(bcom_fec_tx_init
);
212 bcom_fec_tx_reset(struct bcom_task
*tsk
)
214 struct bcom_fec_priv
*priv
= tsk
->priv
;
215 struct bcom_fec_tx_var
*var
;
216 struct bcom_fec_tx_inc
*inc
;
218 /* Shutdown the task */
219 bcom_disable_task(tsk
->tasknum
);
221 /* Reset the microcode */
222 var
= (struct bcom_fec_tx_var
*) bcom_task_var(tsk
->tasknum
);
223 inc
= (struct bcom_fec_tx_inc
*) bcom_task_inc(tsk
->tasknum
);
225 if (bcom_load_image(tsk
->tasknum
, bcom_fec_tx_task
))
228 var
->enable
= bcom_eng
->regs_base
+
229 offsetof(struct mpc52xx_sdma
, tcr
[tsk
->tasknum
]);
230 var
->fifo
= (u32
) priv
->fifo
;
231 var
->DRD
= bcom_sram_va2pa(self_modified_drd(tsk
->tasknum
));
232 var
->bd_base
= tsk
->bd_pa
;
233 var
->bd_last
= tsk
->bd_pa
+ ((tsk
->num_bd
-1) * tsk
->bd_size
);
234 var
->bd_start
= tsk
->bd_pa
;
236 inc
->incr_bytes
= -(s16
)sizeof(u32
); /* These should be in the */
237 inc
->incr_src
= sizeof(u32
); /* task image, but we stick */
238 inc
->incr_src_ma
= sizeof(u8
); /* to the official ones */
244 memset(tsk
->bd
, 0x00, tsk
->num_bd
* tsk
->bd_size
);
246 /* Configure some stuff */
247 bcom_set_task_pragma(tsk
->tasknum
, BCOM_FEC_TX_BD_PRAGMA
);
248 bcom_set_task_auto_start(tsk
->tasknum
, tsk
->tasknum
);
250 out_8(&bcom_eng
->regs
->ipr
[BCOM_INITIATOR_FEC_TX
], BCOM_IPR_FEC_TX
);
252 out_be32(&bcom_eng
->regs
->IntPend
, 1<<tsk
->tasknum
); /* Clear ints */
256 EXPORT_SYMBOL_GPL(bcom_fec_tx_reset
);
259 bcom_fec_tx_release(struct bcom_task
*tsk
)
261 /* Nothing special for the FEC tasks */
264 EXPORT_SYMBOL_GPL(bcom_fec_tx_release
);
267 MODULE_DESCRIPTION("BestComm FEC tasks driver");
268 MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
269 MODULE_LICENSE("GPL v2");