ops-sh4-202.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * arch/sh/drivers/superhyway/ops-sh4-202.c
  3. *
  4. * SuperHyway bus support for SH4-202
  5. *
  6. * Copyright (C) 2005 Paul Mundt
  7. *
  8. * This file is subject to the terms and conditions of the GNU
  9. * General Public License. See the file "COPYING" in the main
  10. * directory of this archive for more details.
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/init.h>
  14. #include <linux/superhyway.h>
  15. #include <linux/string.h>
  16. #include <asm/addrspace.h>
  17. #include <asm/io.h>
  18. #define PHYS_EMI_CBLOCK P4SEGADDR(0x1ec00000)
  19. #define PHYS_EMI_DBLOCK P4SEGADDR(0x08000000)
  20. #define PHYS_FEMI_CBLOCK P4SEGADDR(0x1f800000)
  21. #define PHYS_FEMI_DBLOCK P4SEGADDR(0x00000000)
  22. #define PHYS_EPBR_BLOCK P4SEGADDR(0x1de00000)
  23. #define PHYS_DMAC_BLOCK P4SEGADDR(0x1fa00000)
  24. #define PHYS_PBR_BLOCK P4SEGADDR(0x1fc00000)
  25. static struct resource emi_resources[] = {
  26. [0] = {
  27. .start = PHYS_EMI_CBLOCK,
  28. .end = PHYS_EMI_CBLOCK + 0x00300000 - 1,
  29. .flags = IORESOURCE_MEM,
  30. },
  31. [1] = {
  32. .start = PHYS_EMI_DBLOCK,
  33. .end = PHYS_EMI_DBLOCK + 0x08000000 - 1,
  34. .flags = IORESOURCE_MEM,
  35. },
  36. };
  37. static struct superhyway_device emi_device = {
  38. .name = "emi",
  39. .num_resources = ARRAY_SIZE(emi_resources),
  40. .resource = emi_resources,
  41. };
  42. static struct resource femi_resources[] = {
  43. [0] = {
  44. .start = PHYS_FEMI_CBLOCK,
  45. .end = PHYS_FEMI_CBLOCK + 0x00100000 - 1,
  46. .flags = IORESOURCE_MEM,
  47. },
  48. [1] = {
  49. .start = PHYS_FEMI_DBLOCK,
  50. .end = PHYS_FEMI_DBLOCK + 0x08000000 - 1,
  51. .flags = IORESOURCE_MEM,
  52. },
  53. };
  54. static struct superhyway_device femi_device = {
  55. .name = "femi",
  56. .num_resources = ARRAY_SIZE(femi_resources),
  57. .resource = femi_resources,
  58. };
  59. static struct resource epbr_resources[] = {
  60. [0] = {
  61. .start = P4SEGADDR(0x1e7ffff8),
  62. .end = P4SEGADDR(0x1e7ffff8 + (sizeof(u32) * 2) - 1),
  63. .flags = IORESOURCE_MEM,
  64. },
  65. [1] = {
  66. .start = PHYS_EPBR_BLOCK,
  67. .end = PHYS_EPBR_BLOCK + 0x00a00000 - 1,
  68. .flags = IORESOURCE_MEM,
  69. },
  70. };
  71. static struct superhyway_device epbr_device = {
  72. .name = "epbr",
  73. .num_resources = ARRAY_SIZE(epbr_resources),
  74. .resource = epbr_resources,
  75. };
  76. static struct resource dmac_resource = {
  77. .start = PHYS_DMAC_BLOCK,
  78. .end = PHYS_DMAC_BLOCK + 0x00100000 - 1,
  79. .flags = IORESOURCE_MEM,
  80. };
  81. static struct superhyway_device dmac_device = {
  82. .name = "dmac",
  83. .num_resources = 1,
  84. .resource = &dmac_resource,
  85. };
  86. static struct resource pbr_resources[] = {
  87. [0] = {
  88. .start = P4SEGADDR(0x1ffffff8),
  89. .end = P4SEGADDR(0x1ffffff8 + (sizeof(u32) * 2) - 1),
  90. .flags = IORESOURCE_MEM,
  91. },
  92. [1] = {
  93. .start = PHYS_PBR_BLOCK,
  94. .end = PHYS_PBR_BLOCK + 0x00400000 - (sizeof(u32) * 2) - 1,
  95. .flags = IORESOURCE_MEM,
  96. },
  97. };
  98. static struct superhyway_device pbr_device = {
  99. .name = "pbr",
  100. .num_resources = ARRAY_SIZE(pbr_resources),
  101. .resource = pbr_resources,
  102. };
  103. static struct superhyway_device *sh4202_devices[] __initdata = {
  104. &emi_device, &femi_device, &epbr_device, &dmac_device, &pbr_device,
  105. };
  106. static int sh4202_read_vcr(unsigned long base, struct superhyway_vcr_info *vcr)
  107. {
  108. u32 vcrh, vcrl;
  109. u64 tmp;
  110. /*
  111. * XXX: Even though the SH4-202 Evaluation Device documentation
  112. * indicates that VCRL is mapped first with VCRH at a + 0x04
  113. * offset, the opposite seems to be true.
  114. *
  115. * Some modules (PBR and ePBR for instance) also appear to have
  116. * VCRL/VCRH flipped in the documentation, but on the SH4-202
  117. * itself it appears that these are all consistently mapped with
  118. * VCRH preceding VCRL.
  119. *
  120. * Do not trust the documentation, for it is evil.
  121. */
  122. vcrh = __raw_readl(base);
  123. vcrl = __raw_readl(base + sizeof(u32));
  124. tmp = ((u64)vcrh << 32) | vcrl;
  125. memcpy(vcr, &tmp, sizeof(u64));
  126. return 0;
  127. }
  128. static int sh4202_write_vcr(unsigned long base, struct superhyway_vcr_info vcr)
  129. {
  130. u64 tmp = *(u64 *)&vcr;
  131. __raw_writel((tmp >> 32) & 0xffffffff, base);
  132. __raw_writel(tmp & 0xffffffff, base + sizeof(u32));
  133. return 0;
  134. }
  135. static struct superhyway_ops sh4202_superhyway_ops = {
  136. .read_vcr = sh4202_read_vcr,
  137. .write_vcr = sh4202_write_vcr,
  138. };
  139. struct superhyway_bus superhyway_channels[] = {
  140. { &sh4202_superhyway_ops, },
  141. { 0, },
  142. };
  143. int __init superhyway_scan_bus(struct superhyway_bus *bus)
  144. {
  145. return superhyway_add_devices(bus, sh4202_devices,
  146. ARRAY_SIZE(sh4202_devices));
  147. }