fsl_lbc.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Freescale LBC and UPM routines.
  3. *
  4. * Copyright (c) 2007-2008 MontaVista Software, Inc.
  5. *
  6. * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/of.h>
  15. #include <asm/fsl_lbc.h>
  16. spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
  17. struct fsl_lbc_regs __iomem *fsl_lbc_regs;
  18. EXPORT_SYMBOL(fsl_lbc_regs);
  19. static char __initdata *compat_lbc[] = {
  20. "fsl,pq2-localbus",
  21. "fsl,pq2pro-localbus",
  22. "fsl,pq3-localbus",
  23. "fsl,elbc",
  24. };
  25. static int __init fsl_lbc_init(void)
  26. {
  27. struct device_node *lbus;
  28. int i;
  29. for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
  30. lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
  31. if (lbus)
  32. goto found;
  33. }
  34. return -ENODEV;
  35. found:
  36. fsl_lbc_regs = of_iomap(lbus, 0);
  37. of_node_put(lbus);
  38. if (!fsl_lbc_regs)
  39. return -ENOMEM;
  40. return 0;
  41. }
  42. arch_initcall(fsl_lbc_init);
  43. /**
  44. * fsl_lbc_find - find Localbus bank
  45. * @addr_base: base address of the memory bank
  46. *
  47. * This function walks LBC banks comparing "Base address" field of the BR
  48. * registers with the supplied addr_base argument. When bases match this
  49. * function returns bank number (starting with 0), otherwise it returns
  50. * appropriate errno value.
  51. */
  52. int fsl_lbc_find(phys_addr_t addr_base)
  53. {
  54. int i;
  55. if (!fsl_lbc_regs)
  56. return -ENODEV;
  57. for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
  58. __be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
  59. __be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
  60. if (br & BR_V && (br & or & BR_BA) == addr_base)
  61. return i;
  62. }
  63. return -ENOENT;
  64. }
  65. EXPORT_SYMBOL(fsl_lbc_find);
  66. /**
  67. * fsl_upm_find - find pre-programmed UPM via base address
  68. * @addr_base: base address of the memory bank controlled by the UPM
  69. * @upm: pointer to the allocated fsl_upm structure
  70. *
  71. * This function fills fsl_upm structure so you can use it with the rest of
  72. * UPM API. On success this function returns 0, otherwise it returns
  73. * appropriate errno value.
  74. */
  75. int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
  76. {
  77. int bank;
  78. __be32 br;
  79. bank = fsl_lbc_find(addr_base);
  80. if (bank < 0)
  81. return bank;
  82. br = in_be32(&fsl_lbc_regs->bank[bank].br);
  83. switch (br & BR_MSEL) {
  84. case BR_MS_UPMA:
  85. upm->mxmr = &fsl_lbc_regs->mamr;
  86. break;
  87. case BR_MS_UPMB:
  88. upm->mxmr = &fsl_lbc_regs->mbmr;
  89. break;
  90. case BR_MS_UPMC:
  91. upm->mxmr = &fsl_lbc_regs->mcmr;
  92. break;
  93. default:
  94. return -EINVAL;
  95. }
  96. switch (br & BR_PS) {
  97. case BR_PS_8:
  98. upm->width = 8;
  99. break;
  100. case BR_PS_16:
  101. upm->width = 16;
  102. break;
  103. case BR_PS_32:
  104. upm->width = 32;
  105. break;
  106. default:
  107. return -EINVAL;
  108. }
  109. return 0;
  110. }
  111. EXPORT_SYMBOL(fsl_upm_find);