ops-sh4-202.c 4.0 KB

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