Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gen_bd.c
Go to the documentation of this file.
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 */
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 */
53 };
54 
55 /* tx task vars that need to be set before enabling the task */
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 */
73 };
74 
75 /* private structure */
78  int initiator;
79  int ipr;
81 };
82 
83 
84 /* ======================================================================== */
85 /* Task support code */
86 /* ======================================================================== */
87 
88 struct bcom_task *
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 }
116 
117 int
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 
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 }
163 
164 void
166 {
167  /* Nothing special for the GenBD tasks */
168  bcom_task_free(tsk);
169 }
171 
172 
173 extern struct bcom_task *
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 }
200 
201 int
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 
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 }
247 
248 void
250 {
251  /* Nothing special for the GenBD tasks */
252  bcom_task_free(tsk);
253 }
255 
256 /* ---------------------------------------------------------------------
257  * PSC support code
258  */
259 
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 
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 }
331 
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 }
349 
350 
351 MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
352 MODULE_AUTHOR("Jeff Gibbons <[email protected]>");
353 MODULE_LICENSE("GPL v2");
354