Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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