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