Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/sysdev/bestcomm/gen_bd.c
10818 views
1
/*
2
* Driver for MPC52xx processor BestComm General Buffer Descriptor
3
*
4
* Copyright (C) 2007 Sylvain Munaut <[email protected]>
5
* Copyright (C) 2006 AppSpec Computer Technologies Corp.
6
* Jeff Gibbons <[email protected]>
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 */
34
extern u32 bcom_gen_bd_rx_task[];
35
extern u32 bcom_gen_bd_tx_task[];
36
37
/* rx task vars that need to be set before enabling the task */
38
struct 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 */
48
struct 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 */
56
struct 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 */
66
struct 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 */
76
struct 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
88
struct bcom_task *
89
bcom_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
}
115
EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init);
116
117
int
118
bcom_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
}
162
EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_reset);
163
164
void
165
bcom_gen_bd_rx_release(struct bcom_task *tsk)
166
{
167
/* Nothing special for the GenBD tasks */
168
bcom_task_free(tsk);
169
}
170
EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release);
171
172
173
extern struct bcom_task *
174
bcom_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
}
199
EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init);
200
201
int
202
bcom_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
}
246
EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_reset);
247
248
void
249
bcom_gen_bd_tx_release(struct bcom_task *tsk)
250
{
251
/* Nothing special for the GenBD tasks */
252
bcom_task_free(tsk);
253
}
254
EXPORT_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
*/
266
static 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
*/
319
struct 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
}
330
EXPORT_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
*/
340
struct bcom_task *
341
bcom_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
}
348
EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);
349
350
351
MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
352
MODULE_AUTHOR("Jeff Gibbons <[email protected]>");
353
MODULE_LICENSE("GPL v2");
354
355
356