• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/powerpc/sysdev/bestcomm/
1/*
2 * Driver for MPC52xx processor BestComm General Buffer Descriptor
3 *
4 * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
5 * Copyright (C) 2006 AppSpec Computer Technologies Corp.
6 *                    Jeff Gibbons <jeff.gibbons@appspec.com>
7 *
8 * This program is free software; you can redistribute  it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/string.h>
17#include <linux/types.h>
18#include <asm/errno.h>
19#include <asm/io.h>
20
21#include <asm/mpc52xx.h>
22#include <asm/mpc52xx_psc.h>
23
24#include "bestcomm.h"
25#include "bestcomm_priv.h"
26#include "gen_bd.h"
27
28
29/* ======================================================================== */
30/* Task image/var/inc                                                       */
31/* ======================================================================== */
32
33/* gen_bd tasks images */
34extern u32 bcom_gen_bd_rx_task[];
35extern u32 bcom_gen_bd_tx_task[];
36
37/* rx task vars that need to be set before enabling the task */
38struct bcom_gen_bd_rx_var {
39	u32 enable;		/* (u16*) address of task's control register */
40	u32 fifo;		/* (u32*) address of gen_bd's fifo */
41	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
42	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
43	u32 bd_start;		/* (struct bcom_bd*) current bd */
44	u32 buffer_size;	/* size of receive buffer */
45};
46
47/* rx task incs that need to be set before enabling the task */
48struct bcom_gen_bd_rx_inc {
49	u16 pad0;
50	s16 incr_bytes;
51	u16 pad1;
52	s16 incr_dst;
53};
54
55/* tx task vars that need to be set before enabling the task */
56struct bcom_gen_bd_tx_var {
57	u32 fifo;		/* (u32*) address of gen_bd's fifo */
58	u32 enable;		/* (u16*) address of task's control register */
59	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
60	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
61	u32 bd_start;		/* (struct bcom_bd*) current bd */
62	u32 buffer_size;	/* set by uCode for each packet */
63};
64
65/* tx task incs that need to be set before enabling the task */
66struct bcom_gen_bd_tx_inc {
67	u16 pad0;
68	s16 incr_bytes;
69	u16 pad1;
70	s16 incr_src;
71	u16 pad2;
72	s16 incr_src_ma;
73};
74
75/* private structure */
76struct bcom_gen_bd_priv {
77	phys_addr_t	fifo;
78	int		initiator;
79	int		ipr;
80	int		maxbufsize;
81};
82
83
84/* ======================================================================== */
85/* Task support code                                                        */
86/* ======================================================================== */
87
88struct bcom_task *
89bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
90			int initiator, int ipr, int maxbufsize)
91{
92	struct bcom_task *tsk;
93	struct bcom_gen_bd_priv *priv;
94
95	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
96			sizeof(struct bcom_gen_bd_priv));
97	if (!tsk)
98		return NULL;
99
100	tsk->flags = BCOM_FLAGS_NONE;
101
102	priv = tsk->priv;
103	priv->fifo	= fifo;
104	priv->initiator	= initiator;
105	priv->ipr	= ipr;
106	priv->maxbufsize = maxbufsize;
107
108	if (bcom_gen_bd_rx_reset(tsk)) {
109		bcom_task_free(tsk);
110		return NULL;
111	}
112
113	return tsk;
114}
115EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init);
116
117int
118bcom_gen_bd_rx_reset(struct bcom_task *tsk)
119{
120	struct bcom_gen_bd_priv *priv = tsk->priv;
121	struct bcom_gen_bd_rx_var *var;
122	struct bcom_gen_bd_rx_inc *inc;
123
124	/* Shutdown the task */
125	bcom_disable_task(tsk->tasknum);
126
127	/* Reset the microcode */
128	var = (struct bcom_gen_bd_rx_var *) bcom_task_var(tsk->tasknum);
129	inc = (struct bcom_gen_bd_rx_inc *) bcom_task_inc(tsk->tasknum);
130
131	if (bcom_load_image(tsk->tasknum, bcom_gen_bd_rx_task))
132		return -1;
133
134	var->enable	= bcom_eng->regs_base +
135				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
136	var->fifo	= (u32) priv->fifo;
137	var->bd_base	= tsk->bd_pa;
138	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
139	var->bd_start	= tsk->bd_pa;
140	var->buffer_size = priv->maxbufsize;
141
142	inc->incr_bytes	= -(s16)sizeof(u32);
143	inc->incr_dst	= sizeof(u32);
144
145	/* Reset the BDs */
146	tsk->index = 0;
147	tsk->outdex = 0;
148
149	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
150
151	/* Configure some stuff */
152	bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);
153	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
154
155	out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
156	bcom_set_initiator(tsk->tasknum, priv->initiator);
157
158	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
159
160	return 0;
161}
162EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_reset);
163
164void
165bcom_gen_bd_rx_release(struct bcom_task *tsk)
166{
167	/* Nothing special for the GenBD tasks */
168	bcom_task_free(tsk);
169}
170EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release);
171
172
173extern struct bcom_task *
174bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
175			int initiator, int ipr)
176{
177	struct bcom_task *tsk;
178	struct bcom_gen_bd_priv *priv;
179
180	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
181			sizeof(struct bcom_gen_bd_priv));
182	if (!tsk)
183		return NULL;
184
185	tsk->flags = BCOM_FLAGS_NONE;
186
187	priv = tsk->priv;
188	priv->fifo	= fifo;
189	priv->initiator	= initiator;
190	priv->ipr	= ipr;
191
192	if (bcom_gen_bd_tx_reset(tsk)) {
193		bcom_task_free(tsk);
194		return NULL;
195	}
196
197	return tsk;
198}
199EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init);
200
201int
202bcom_gen_bd_tx_reset(struct bcom_task *tsk)
203{
204	struct bcom_gen_bd_priv *priv = tsk->priv;
205	struct bcom_gen_bd_tx_var *var;
206	struct bcom_gen_bd_tx_inc *inc;
207
208	/* Shutdown the task */
209	bcom_disable_task(tsk->tasknum);
210
211	/* Reset the microcode */
212	var = (struct bcom_gen_bd_tx_var *) bcom_task_var(tsk->tasknum);
213	inc = (struct bcom_gen_bd_tx_inc *) bcom_task_inc(tsk->tasknum);
214
215	if (bcom_load_image(tsk->tasknum, bcom_gen_bd_tx_task))
216		return -1;
217
218	var->enable	= bcom_eng->regs_base +
219				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
220	var->fifo	= (u32) priv->fifo;
221	var->bd_base	= tsk->bd_pa;
222	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
223	var->bd_start	= tsk->bd_pa;
224
225	inc->incr_bytes	= -(s16)sizeof(u32);
226	inc->incr_src	= sizeof(u32);
227	inc->incr_src_ma = sizeof(u8);
228
229	/* Reset the BDs */
230	tsk->index = 0;
231	tsk->outdex = 0;
232
233	memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
234
235	/* Configure some stuff */
236	bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);
237	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
238
239	out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
240	bcom_set_initiator(tsk->tasknum, priv->initiator);
241
242	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
243
244	return 0;
245}
246EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_reset);
247
248void
249bcom_gen_bd_tx_release(struct bcom_task *tsk)
250{
251	/* Nothing special for the GenBD tasks */
252	bcom_task_free(tsk);
253}
254EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);
255
256/* ---------------------------------------------------------------------
257 * PSC support code
258 */
259
260/**
261 * bcom_psc_parameters - Bestcomm initialization value table for PSC devices
262 *
263 * This structure is only used internally.  It is a lookup table for PSC
264 * specific parameters to bestcomm tasks.
265 */
266static struct bcom_psc_params {
267	int rx_initiator;
268	int rx_ipr;
269	int tx_initiator;
270	int tx_ipr;
271} bcom_psc_params[] = {
272	[0] = {
273		.rx_initiator = BCOM_INITIATOR_PSC1_RX,
274		.rx_ipr = BCOM_IPR_PSC1_RX,
275		.tx_initiator = BCOM_INITIATOR_PSC1_TX,
276		.tx_ipr = BCOM_IPR_PSC1_TX,
277	},
278	[1] = {
279		.rx_initiator = BCOM_INITIATOR_PSC2_RX,
280		.rx_ipr = BCOM_IPR_PSC2_RX,
281		.tx_initiator = BCOM_INITIATOR_PSC2_TX,
282		.tx_ipr = BCOM_IPR_PSC2_TX,
283	},
284	[2] = {
285		.rx_initiator = BCOM_INITIATOR_PSC3_RX,
286		.rx_ipr = BCOM_IPR_PSC3_RX,
287		.tx_initiator = BCOM_INITIATOR_PSC3_TX,
288		.tx_ipr = BCOM_IPR_PSC3_TX,
289	},
290	[3] = {
291		.rx_initiator = BCOM_INITIATOR_PSC4_RX,
292		.rx_ipr = BCOM_IPR_PSC4_RX,
293		.tx_initiator = BCOM_INITIATOR_PSC4_TX,
294		.tx_ipr = BCOM_IPR_PSC4_TX,
295	},
296	[4] = {
297		.rx_initiator = BCOM_INITIATOR_PSC5_RX,
298		.rx_ipr = BCOM_IPR_PSC5_RX,
299		.tx_initiator = BCOM_INITIATOR_PSC5_TX,
300		.tx_ipr = BCOM_IPR_PSC5_TX,
301	},
302	[5] = {
303		.rx_initiator = BCOM_INITIATOR_PSC6_RX,
304		.rx_ipr = BCOM_IPR_PSC6_RX,
305		.tx_initiator = BCOM_INITIATOR_PSC6_TX,
306		.tx_ipr = BCOM_IPR_PSC6_TX,
307	},
308};
309
310/**
311 * bcom_psc_gen_bd_rx_init - Allocate a receive bcom_task for a PSC port
312 * @psc_num:	Number of the PSC to allocate a task for
313 * @queue_len:	number of buffer descriptors to allocate for the task
314 * @fifo:	physical address of FIFO register
315 * @maxbufsize:	Maximum receive data size in bytes.
316 *
317 * Allocate a bestcomm task structure for receiving data from a PSC.
318 */
319struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
320					   phys_addr_t fifo, int maxbufsize)
321{
322	if (psc_num >= MPC52xx_PSC_MAXNUM)
323		return NULL;
324
325	return bcom_gen_bd_rx_init(queue_len, fifo,
326				   bcom_psc_params[psc_num].rx_initiator,
327				   bcom_psc_params[psc_num].rx_ipr,
328				   maxbufsize);
329}
330EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init);
331
332/**
333 * bcom_psc_gen_bd_tx_init - Allocate a transmit bcom_task for a PSC port
334 * @psc_num:	Number of the PSC to allocate a task for
335 * @queue_len:	number of buffer descriptors to allocate for the task
336 * @fifo:	physical address of FIFO register
337 *
338 * Allocate a bestcomm task structure for transmitting data to a PSC.
339 */
340struct bcom_task *
341bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo)
342{
343	struct psc;
344	return bcom_gen_bd_tx_init(queue_len, fifo,
345				   bcom_psc_params[psc_num].tx_initiator,
346				   bcom_psc_params[psc_num].tx_ipr);
347}
348EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);
349
350
351MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
352MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>");
353MODULE_LICENSE("GPL v2");
354