This source file includes following definitions.
- bcom_task_alloc
- bcom_task_free
- bcom_load_image
- bcom_set_initiator
- bcom_enable
- bcom_disable
- bcom_engine_init
- bcom_engine_cleanup
- mpc52xx_bcom_probe
- mpc52xx_bcom_remove
- mpc52xx_bcom_init
- mpc52xx_bcom_exit
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 #include <linux/module.h>
  17 #include <linux/kernel.h>
  18 #include <linux/slab.h>
  19 #include <linux/of.h>
  20 #include <linux/of_device.h>
  21 #include <linux/of_platform.h>
  22 #include <asm/io.h>
  23 #include <asm/irq.h>
  24 #include <asm/mpc52xx.h>
  25 
  26 #include <linux/fsl/bestcomm/sram.h>
  27 #include <linux/fsl/bestcomm/bestcomm_priv.h>
  28 #include "linux/fsl/bestcomm/bestcomm.h"
  29 
  30 #define DRIVER_NAME "bestcomm-core"
  31 
  32 
  33 static const struct of_device_id mpc52xx_sram_ids[] = {
  34         { .compatible = "fsl,mpc5200-sram", },
  35         { .compatible = "mpc5200-sram", },
  36         {}
  37 };
  38 
  39 
  40 struct bcom_engine *bcom_eng = NULL;
  41 EXPORT_SYMBOL_GPL(bcom_eng);    
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 struct bcom_task *
  50 bcom_task_alloc(int bd_count, int bd_size, int priv_size)
  51 {
  52         int i, tasknum = -1;
  53         struct bcom_task *tsk;
  54 
  55         
  56         if (!bcom_eng)
  57                 return NULL;
  58 
  59         
  60         spin_lock(&bcom_eng->lock);
  61 
  62         for (i=0; i<BCOM_MAX_TASKS; i++)
  63                 if (!bcom_eng->tdt[i].stop) {   
  64                         bcom_eng->tdt[i].stop = 0xfffffffful; 
  65                         tasknum = i;
  66                         break;
  67                 }
  68 
  69         spin_unlock(&bcom_eng->lock);
  70 
  71         if (tasknum < 0)
  72                 return NULL;
  73 
  74         
  75         tsk = kzalloc(sizeof(struct bcom_task) + priv_size, GFP_KERNEL);
  76         if (!tsk)
  77                 goto error;
  78 
  79         tsk->tasknum = tasknum;
  80         if (priv_size)
  81                 tsk->priv = (void*)tsk + sizeof(struct bcom_task);
  82 
  83         
  84         tsk->irq = irq_of_parse_and_map(bcom_eng->ofnode, tsk->tasknum);
  85         if (!tsk->irq)
  86                 goto error;
  87 
  88         
  89         if (bd_count) {
  90                 tsk->cookie = kmalloc_array(bd_count, sizeof(void *),
  91                                             GFP_KERNEL);
  92                 if (!tsk->cookie)
  93                         goto error;
  94 
  95                 tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa);
  96                 if (!tsk->bd)
  97                         goto error;
  98                 memset(tsk->bd, 0x00, bd_count * bd_size);
  99 
 100                 tsk->num_bd = bd_count;
 101                 tsk->bd_size = bd_size;
 102         }
 103 
 104         return tsk;
 105 
 106 error:
 107         if (tsk) {
 108                 if (tsk->irq)
 109                         irq_dispose_mapping(tsk->irq);
 110                 bcom_sram_free(tsk->bd);
 111                 kfree(tsk->cookie);
 112                 kfree(tsk);
 113         }
 114 
 115         bcom_eng->tdt[tasknum].stop = 0;
 116 
 117         return NULL;
 118 }
 119 EXPORT_SYMBOL_GPL(bcom_task_alloc);
 120 
 121 void
 122 bcom_task_free(struct bcom_task *tsk)
 123 {
 124         
 125         bcom_disable_task(tsk->tasknum);
 126 
 127         
 128         bcom_eng->tdt[tsk->tasknum].start = 0;
 129         bcom_eng->tdt[tsk->tasknum].stop  = 0;
 130 
 131         
 132         irq_dispose_mapping(tsk->irq);
 133         bcom_sram_free(tsk->bd);
 134         kfree(tsk->cookie);
 135         kfree(tsk);
 136 }
 137 EXPORT_SYMBOL_GPL(bcom_task_free);
 138 
 139 int
 140 bcom_load_image(int task, u32 *task_image)
 141 {
 142         struct bcom_task_header *hdr = (struct bcom_task_header *)task_image;
 143         struct bcom_tdt *tdt;
 144         u32 *desc, *var, *inc;
 145         u32 *desc_src, *var_src, *inc_src;
 146 
 147         
 148         if (hdr->magic != BCOM_TASK_MAGIC) {
 149                 printk(KERN_ERR DRIVER_NAME
 150                         ": Trying to load invalid microcode\n");
 151                 return -EINVAL;
 152         }
 153 
 154         if ((task < 0) || (task >= BCOM_MAX_TASKS)) {
 155                 printk(KERN_ERR DRIVER_NAME
 156                         ": Trying to load invalid task %d\n", task);
 157                 return -EINVAL;
 158         }
 159 
 160         
 161         tdt = &bcom_eng->tdt[task];
 162 
 163         if (tdt->start) {
 164                 desc = bcom_task_desc(task);
 165                 if (hdr->desc_size != bcom_task_num_descs(task)) {
 166                         printk(KERN_ERR DRIVER_NAME
 167                                 ": Trying to reload wrong task image "
 168                                 "(%d size %d/%d)!\n",
 169                                 task,
 170                                 hdr->desc_size,
 171                                 bcom_task_num_descs(task));
 172                         return -EINVAL;
 173                 }
 174         } else {
 175                 phys_addr_t start_pa;
 176 
 177                 desc = bcom_sram_alloc(hdr->desc_size * sizeof(u32), 4, &start_pa);
 178                 if (!desc)
 179                         return -ENOMEM;
 180 
 181                 tdt->start = start_pa;
 182                 tdt->stop = start_pa + ((hdr->desc_size-1) * sizeof(u32));
 183         }
 184 
 185         var = bcom_task_var(task);
 186         inc = bcom_task_inc(task);
 187 
 188         
 189         memset(var, 0x00, BCOM_VAR_SIZE);
 190         memset(inc, 0x00, BCOM_INC_SIZE);
 191 
 192         desc_src = (u32 *)(hdr + 1);
 193         var_src = desc_src + hdr->desc_size;
 194         inc_src = var_src + hdr->var_size;
 195 
 196         memcpy(desc, desc_src, hdr->desc_size * sizeof(u32));
 197         memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
 198         memcpy(inc, inc_src, hdr->inc_size * sizeof(u32));
 199 
 200         return 0;
 201 }
 202 EXPORT_SYMBOL_GPL(bcom_load_image);
 203 
 204 void
 205 bcom_set_initiator(int task, int initiator)
 206 {
 207         int i;
 208         int num_descs;
 209         u32 *desc;
 210         int next_drd_has_initiator;
 211 
 212         bcom_set_tcr_initiator(task, initiator);
 213 
 214         
 215         
 216         
 217 
 218         desc = bcom_task_desc(task);
 219         next_drd_has_initiator = 1;
 220         num_descs = bcom_task_num_descs(task);
 221 
 222         for (i=0; i<num_descs; i++, desc++) {
 223                 if (!bcom_desc_is_drd(*desc))
 224                         continue;
 225                 if (next_drd_has_initiator)
 226                         if (bcom_desc_initiator(*desc) != BCOM_INITIATOR_ALWAYS)
 227                                 bcom_set_desc_initiator(desc, initiator);
 228                 next_drd_has_initiator = !bcom_drd_is_extended(*desc);
 229         }
 230 }
 231 EXPORT_SYMBOL_GPL(bcom_set_initiator);
 232 
 233 
 234 
 235 
 236 void
 237 bcom_enable(struct bcom_task *tsk)
 238 {
 239         bcom_enable_task(tsk->tasknum);
 240 }
 241 EXPORT_SYMBOL_GPL(bcom_enable);
 242 
 243 void
 244 bcom_disable(struct bcom_task *tsk)
 245 {
 246         bcom_disable_task(tsk->tasknum);
 247 }
 248 EXPORT_SYMBOL_GPL(bcom_disable);
 249 
 250 
 251 
 252 
 253 
 254 
 255 
 256 
 257 static u32 fdt_ops[] = {
 258         0xa0045670,     
 259         0x80045670,     
 260         0x21800000,     
 261         0x21e00000,     
 262         0x21500000,     
 263         0x21400000,     
 264         0x21500000,     
 265         0x20400000,     
 266         0x20500000,     
 267         0x20800000,     
 268         0x20a00000,     
 269         0xc0170000,     
 270         0xc0145670,     
 271         0xc0345670,     
 272         0xa0076540,     
 273         0xa0000760,     
 274 };
 275 
 276 
 277 static int bcom_engine_init(void)
 278 {
 279         int task;
 280         phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
 281         unsigned int tdt_size, ctx_size, var_size, fdt_size;
 282 
 283         
 284         tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt);
 285         ctx_size = BCOM_MAX_TASKS * BCOM_CTX_SIZE;
 286         var_size = BCOM_MAX_TASKS * (BCOM_VAR_SIZE + BCOM_INC_SIZE);
 287         fdt_size = BCOM_FDT_SIZE;
 288 
 289         bcom_eng->tdt = bcom_sram_alloc(tdt_size, sizeof(u32), &tdt_pa);
 290         bcom_eng->ctx = bcom_sram_alloc(ctx_size, BCOM_CTX_ALIGN, &ctx_pa);
 291         bcom_eng->var = bcom_sram_alloc(var_size, BCOM_VAR_ALIGN, &var_pa);
 292         bcom_eng->fdt = bcom_sram_alloc(fdt_size, BCOM_FDT_ALIGN, &fdt_pa);
 293 
 294         if (!bcom_eng->tdt || !bcom_eng->ctx || !bcom_eng->var || !bcom_eng->fdt) {
 295                 printk(KERN_ERR "DMA: SRAM alloc failed in engine init !\n");
 296 
 297                 bcom_sram_free(bcom_eng->tdt);
 298                 bcom_sram_free(bcom_eng->ctx);
 299                 bcom_sram_free(bcom_eng->var);
 300                 bcom_sram_free(bcom_eng->fdt);
 301 
 302                 return -ENOMEM;
 303         }
 304 
 305         memset(bcom_eng->tdt, 0x00, tdt_size);
 306         memset(bcom_eng->ctx, 0x00, ctx_size);
 307         memset(bcom_eng->var, 0x00, var_size);
 308         memset(bcom_eng->fdt, 0x00, fdt_size);
 309 
 310         
 311         memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
 312 
 313         
 314         for (task=0; task<BCOM_MAX_TASKS; task++)
 315         {
 316                 out_be16(&bcom_eng->regs->tcr[task], 0);
 317                 out_8(&bcom_eng->regs->ipr[task], 0);
 318 
 319                 bcom_eng->tdt[task].context     = ctx_pa;
 320                 bcom_eng->tdt[task].var = var_pa;
 321                 bcom_eng->tdt[task].fdt = fdt_pa;
 322 
 323                 var_pa += BCOM_VAR_SIZE + BCOM_INC_SIZE;
 324                 ctx_pa += BCOM_CTX_SIZE;
 325         }
 326 
 327         out_be32(&bcom_eng->regs->taskBar, tdt_pa);
 328 
 329         
 330         out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
 331 
 332         
 333         if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR)
 334                 bcom_disable_prefetch();
 335 
 336         
 337         spin_lock_init(&bcom_eng->lock);
 338 
 339         return 0;
 340 }
 341 
 342 static void
 343 bcom_engine_cleanup(void)
 344 {
 345         int task;
 346 
 347         
 348         for (task=0; task<BCOM_MAX_TASKS; task++)
 349         {
 350                 out_be16(&bcom_eng->regs->tcr[task], 0);
 351                 out_8(&bcom_eng->regs->ipr[task], 0);
 352         }
 353 
 354         out_be32(&bcom_eng->regs->taskBar, 0ul);
 355 
 356         
 357         bcom_sram_free(bcom_eng->tdt);
 358         bcom_sram_free(bcom_eng->ctx);
 359         bcom_sram_free(bcom_eng->var);
 360         bcom_sram_free(bcom_eng->fdt);
 361 }
 362 
 363 
 364 
 365 
 366 
 367 
 368 static int mpc52xx_bcom_probe(struct platform_device *op)
 369 {
 370         struct device_node *ofn_sram;
 371         struct resource res_bcom;
 372 
 373         int rv;
 374 
 375         
 376         printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
 377 
 378         
 379         of_node_get(op->dev.of_node);
 380 
 381         
 382         ofn_sram = of_find_matching_node(NULL, mpc52xx_sram_ids);
 383         if (!ofn_sram) {
 384                 printk(KERN_ERR DRIVER_NAME ": "
 385                         "No SRAM found in device tree\n");
 386                 rv = -ENODEV;
 387                 goto error_ofput;
 388         }
 389         rv = bcom_sram_init(ofn_sram, DRIVER_NAME);
 390         of_node_put(ofn_sram);
 391 
 392         if (rv) {
 393                 printk(KERN_ERR DRIVER_NAME ": "
 394                         "Error in SRAM init\n");
 395                 goto error_ofput;
 396         }
 397 
 398         
 399         bcom_eng = kzalloc(sizeof(struct bcom_engine), GFP_KERNEL);
 400         if (!bcom_eng) {
 401                 rv = -ENOMEM;
 402                 goto error_sramclean;
 403         }
 404 
 405         
 406         bcom_eng->ofnode = op->dev.of_node;
 407 
 408         
 409         if (of_address_to_resource(op->dev.of_node, 0, &res_bcom)) {
 410                 printk(KERN_ERR DRIVER_NAME ": "
 411                         "Can't get resource\n");
 412                 rv = -EINVAL;
 413                 goto error_sramclean;
 414         }
 415 
 416         if (!request_mem_region(res_bcom.start, resource_size(&res_bcom),
 417                                 DRIVER_NAME)) {
 418                 printk(KERN_ERR DRIVER_NAME ": "
 419                         "Can't request registers region\n");
 420                 rv = -EBUSY;
 421                 goto error_sramclean;
 422         }
 423 
 424         bcom_eng->regs_base = res_bcom.start;
 425         bcom_eng->regs = ioremap(res_bcom.start, sizeof(struct mpc52xx_sdma));
 426         if (!bcom_eng->regs) {
 427                 printk(KERN_ERR DRIVER_NAME ": "
 428                         "Can't map registers\n");
 429                 rv = -ENOMEM;
 430                 goto error_release;
 431         }
 432 
 433         
 434         rv = bcom_engine_init();
 435         if (rv)
 436                 goto error_unmap;
 437 
 438         
 439         printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n",
 440                 (long)bcom_eng->regs_base);
 441 
 442         return 0;
 443 
 444         
 445 error_unmap:
 446         iounmap(bcom_eng->regs);
 447 error_release:
 448         release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma));
 449 error_sramclean:
 450         kfree(bcom_eng);
 451         bcom_sram_cleanup();
 452 error_ofput:
 453         of_node_put(op->dev.of_node);
 454 
 455         printk(KERN_ERR "DMA: MPC52xx BestComm init failed !\n");
 456 
 457         return rv;
 458 }
 459 
 460 
 461 static int mpc52xx_bcom_remove(struct platform_device *op)
 462 {
 463         
 464         bcom_engine_cleanup();
 465 
 466         
 467         bcom_sram_cleanup();
 468 
 469         
 470         iounmap(bcom_eng->regs);
 471         release_mem_region(bcom_eng->regs_base, sizeof(struct mpc52xx_sdma));
 472 
 473         
 474         of_node_put(bcom_eng->ofnode);
 475 
 476         
 477         kfree(bcom_eng);
 478         bcom_eng = NULL;
 479 
 480         return 0;
 481 }
 482 
 483 static const struct of_device_id mpc52xx_bcom_of_match[] = {
 484         { .compatible = "fsl,mpc5200-bestcomm", },
 485         { .compatible = "mpc5200-bestcomm", },
 486         {},
 487 };
 488 
 489 MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
 490 
 491 
 492 static struct platform_driver mpc52xx_bcom_of_platform_driver = {
 493         .probe          = mpc52xx_bcom_probe,
 494         .remove         = mpc52xx_bcom_remove,
 495         .driver = {
 496                 .name = DRIVER_NAME,
 497                 .of_match_table = mpc52xx_bcom_of_match,
 498         },
 499 };
 500 
 501 
 502 
 503 
 504 
 505 
 506 static int __init
 507 mpc52xx_bcom_init(void)
 508 {
 509         return platform_driver_register(&mpc52xx_bcom_of_platform_driver);
 510 }
 511 
 512 static void __exit
 513 mpc52xx_bcom_exit(void)
 514 {
 515         platform_driver_unregister(&mpc52xx_bcom_of_platform_driver);
 516 }
 517 
 518 
 519 
 520 
 521 subsys_initcall(mpc52xx_bcom_init);
 522 module_exit(mpc52xx_bcom_exit);
 523 
 524 MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
 525 MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
 526 MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
 527 MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
 528 MODULE_LICENSE("GPL v2");
 529