1 // SPDX-License-Identifier: GPL-2.0-only
3 * 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> )
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/types.h>
15 #include <linux/fsl/bestcomm/bestcomm.h>
16 #include <linux/fsl/bestcomm/bestcomm_priv.h>
17 #include <linux/fsl/bestcomm/fec.h>
20 /* ======================================================================== */
21 /* Task image/var/inc */
22 /* ======================================================================== */
24 /* fec tasks images */
25 extern u32 bcom_fec_rx_task
[];
26 extern u32 bcom_fec_tx_task
[];
28 /* rx task vars that need to be set before enabling the task */
29 struct bcom_fec_rx_var
{
30 u32 enable
; /* (u16*) address of task's control register */
31 u32 fifo
; /* (u32*) address of fec's fifo */
32 u32 bd_base
; /* (struct bcom_bd*) beginning of ring buffer */
33 u32 bd_last
; /* (struct bcom_bd*) end of ring buffer */
34 u32 bd_start
; /* (struct bcom_bd*) current bd */
35 u32 buffer_size
; /* size of receive buffer */
38 /* rx task incs that need to be set before enabling the task */
39 struct bcom_fec_rx_inc
{
48 /* tx task vars that need to be set before enabling the task */
49 struct bcom_fec_tx_var
{
50 u32 DRD
; /* (u32*) address of self-modified DRD */
51 u32 fifo
; /* (u32*) address of fec's fifo */
52 u32 enable
; /* (u16*) address of task's control register */
53 u32 bd_base
; /* (struct bcom_bd*) beginning of ring buffer */
54 u32 bd_last
; /* (struct bcom_bd*) end of ring buffer */
55 u32 bd_start
; /* (struct bcom_bd*) current bd */
56 u32 buffer_size
; /* set by uCode for each packet */
59 /* tx task incs that need to be set before enabling the task */
60 struct bcom_fec_tx_inc
{
69 /* private structure in the task */
70 struct bcom_fec_priv
{
76 /* ======================================================================== */
77 /* Task support code */
78 /* ======================================================================== */
81 bcom_fec_rx_init(int queue_len
, phys_addr_t fifo
, int maxbufsize
)
83 struct bcom_task
*tsk
;
84 struct bcom_fec_priv
*priv
;
86 tsk
= bcom_task_alloc(queue_len
, sizeof(struct bcom_fec_bd
),
87 sizeof(struct bcom_fec_priv
));
91 tsk
->flags
= BCOM_FLAGS_NONE
;
95 priv
->maxbufsize
= maxbufsize
;
97 if (bcom_fec_rx_reset(tsk
)) {
104 EXPORT_SYMBOL_GPL(bcom_fec_rx_init
);
107 bcom_fec_rx_reset(struct bcom_task
*tsk
)
109 struct bcom_fec_priv
*priv
= tsk
->priv
;
110 struct bcom_fec_rx_var
*var
;
111 struct bcom_fec_rx_inc
*inc
;
113 /* Shutdown the task */
114 bcom_disable_task(tsk
->tasknum
);
116 /* Reset the microcode */
117 var
= (struct bcom_fec_rx_var
*) bcom_task_var(tsk
->tasknum
);
118 inc
= (struct bcom_fec_rx_inc
*) bcom_task_inc(tsk
->tasknum
);
120 if (bcom_load_image(tsk
->tasknum
, bcom_fec_rx_task
))
123 var
->enable
= bcom_eng
->regs_base
+
124 offsetof(struct mpc52xx_sdma
, tcr
[tsk
->tasknum
]);
125 var
->fifo
= (u32
) priv
->fifo
;
126 var
->bd_base
= tsk
->bd_pa
;
127 var
->bd_last
= tsk
->bd_pa
+ ((tsk
->num_bd
-1) * tsk
->bd_size
);
128 var
->bd_start
= tsk
->bd_pa
;
129 var
->buffer_size
= priv
->maxbufsize
;
131 inc
->incr_bytes
= -(s16
)sizeof(u32
); /* These should be in the */
132 inc
->incr_dst
= sizeof(u32
); /* task image, but we stick */
133 inc
->incr_dst_ma
= sizeof(u8
); /* to the official ones */
139 memset_io(tsk
->bd
, 0x00, tsk
->num_bd
* tsk
->bd_size
);
141 /* Configure some stuff */
142 bcom_set_task_pragma(tsk
->tasknum
, BCOM_FEC_RX_BD_PRAGMA
);
143 bcom_set_task_auto_start(tsk
->tasknum
, tsk
->tasknum
);
145 out_8(&bcom_eng
->regs
->ipr
[BCOM_INITIATOR_FEC_RX
], BCOM_IPR_FEC_RX
);
147 out_be32(&bcom_eng
->regs
->IntPend
, 1<<tsk
->tasknum
); /* Clear ints */
151 EXPORT_SYMBOL_GPL(bcom_fec_rx_reset
);
154 bcom_fec_rx_release(struct bcom_task
*tsk
)
156 /* Nothing special for the FEC tasks */
159 EXPORT_SYMBOL_GPL(bcom_fec_rx_release
);
163 /* Return 2nd to last DRD */
164 /* This is an ugly hack, but at least it's only done
165 once at initialization */
166 static u32
*self_modified_drd(int tasknum
)
173 num_descs
= bcom_task_num_descs(tasknum
);
174 desc
= bcom_task_desc(tasknum
) + num_descs
- 1;
176 for (i
=0; i
<num_descs
; i
++, desc
--)
177 if (bcom_desc_is_drd(*desc
) && ++drd_count
== 3)
183 bcom_fec_tx_init(int queue_len
, phys_addr_t fifo
)
185 struct bcom_task
*tsk
;
186 struct bcom_fec_priv
*priv
;
188 tsk
= bcom_task_alloc(queue_len
, sizeof(struct bcom_fec_bd
),
189 sizeof(struct bcom_fec_priv
));
193 tsk
->flags
= BCOM_FLAGS_ENABLE_TASK
;
198 if (bcom_fec_tx_reset(tsk
)) {
205 EXPORT_SYMBOL_GPL(bcom_fec_tx_init
);
208 bcom_fec_tx_reset(struct bcom_task
*tsk
)
210 struct bcom_fec_priv
*priv
= tsk
->priv
;
211 struct bcom_fec_tx_var
*var
;
212 struct bcom_fec_tx_inc
*inc
;
214 /* Shutdown the task */
215 bcom_disable_task(tsk
->tasknum
);
217 /* Reset the microcode */
218 var
= (struct bcom_fec_tx_var
*) bcom_task_var(tsk
->tasknum
);
219 inc
= (struct bcom_fec_tx_inc
*) bcom_task_inc(tsk
->tasknum
);
221 if (bcom_load_image(tsk
->tasknum
, bcom_fec_tx_task
))
224 var
->enable
= bcom_eng
->regs_base
+
225 offsetof(struct mpc52xx_sdma
, tcr
[tsk
->tasknum
]);
226 var
->fifo
= (u32
) priv
->fifo
;
227 var
->DRD
= bcom_sram_va2pa(self_modified_drd(tsk
->tasknum
));
228 var
->bd_base
= tsk
->bd_pa
;
229 var
->bd_last
= tsk
->bd_pa
+ ((tsk
->num_bd
-1) * tsk
->bd_size
);
230 var
->bd_start
= tsk
->bd_pa
;
232 inc
->incr_bytes
= -(s16
)sizeof(u32
); /* These should be in the */
233 inc
->incr_src
= sizeof(u32
); /* task image, but we stick */
234 inc
->incr_src_ma
= sizeof(u8
); /* to the official ones */
240 memset_io(tsk
->bd
, 0x00, tsk
->num_bd
* tsk
->bd_size
);
242 /* Configure some stuff */
243 bcom_set_task_pragma(tsk
->tasknum
, BCOM_FEC_TX_BD_PRAGMA
);
244 bcom_set_task_auto_start(tsk
->tasknum
, tsk
->tasknum
);
246 out_8(&bcom_eng
->regs
->ipr
[BCOM_INITIATOR_FEC_TX
], BCOM_IPR_FEC_TX
);
248 out_be32(&bcom_eng
->regs
->IntPend
, 1<<tsk
->tasknum
); /* Clear ints */
252 EXPORT_SYMBOL_GPL(bcom_fec_tx_reset
);
255 bcom_fec_tx_release(struct bcom_task
*tsk
)
257 /* Nothing special for the FEC tasks */
260 EXPORT_SYMBOL_GPL(bcom_fec_tx_release
);
263 MODULE_DESCRIPTION("BestComm FEC tasks driver");
264 MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
265 MODULE_LICENSE("GPL v2");