host_soc.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Sonics Silicon Backplane SoC host related functions.
  3. * Subsystem core
  4. *
  5. * Copyright 2005, Broadcom Corporation
  6. * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
  7. *
  8. * Licensed under the GNU/GPL. See COPYING for details.
  9. */
  10. #include "ssb_private.h"
  11. #include <linux/bcm47xx_nvram.h>
  12. #include <linux/ssb/ssb.h>
  13. static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset)
  14. {
  15. struct ssb_bus *bus = dev->bus;
  16. offset += dev->core_index * SSB_CORE_SIZE;
  17. return readb(bus->mmio + offset);
  18. }
  19. static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset)
  20. {
  21. struct ssb_bus *bus = dev->bus;
  22. offset += dev->core_index * SSB_CORE_SIZE;
  23. return readw(bus->mmio + offset);
  24. }
  25. static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset)
  26. {
  27. struct ssb_bus *bus = dev->bus;
  28. offset += dev->core_index * SSB_CORE_SIZE;
  29. return readl(bus->mmio + offset);
  30. }
  31. #ifdef CONFIG_SSB_BLOCKIO
  32. static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer,
  33. size_t count, u16 offset, u8 reg_width)
  34. {
  35. struct ssb_bus *bus = dev->bus;
  36. void __iomem *addr;
  37. offset += dev->core_index * SSB_CORE_SIZE;
  38. addr = bus->mmio + offset;
  39. switch (reg_width) {
  40. case sizeof(u8): {
  41. u8 *buf = buffer;
  42. while (count) {
  43. *buf = __raw_readb(addr);
  44. buf++;
  45. count--;
  46. }
  47. break;
  48. }
  49. case sizeof(u16): {
  50. __le16 *buf = buffer;
  51. WARN_ON(count & 1);
  52. while (count) {
  53. *buf = (__force __le16)__raw_readw(addr);
  54. buf++;
  55. count -= 2;
  56. }
  57. break;
  58. }
  59. case sizeof(u32): {
  60. __le32 *buf = buffer;
  61. WARN_ON(count & 3);
  62. while (count) {
  63. *buf = (__force __le32)__raw_readl(addr);
  64. buf++;
  65. count -= 4;
  66. }
  67. break;
  68. }
  69. default:
  70. WARN_ON(1);
  71. }
  72. }
  73. #endif /* CONFIG_SSB_BLOCKIO */
  74. static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value)
  75. {
  76. struct ssb_bus *bus = dev->bus;
  77. offset += dev->core_index * SSB_CORE_SIZE;
  78. writeb(value, bus->mmio + offset);
  79. }
  80. static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value)
  81. {
  82. struct ssb_bus *bus = dev->bus;
  83. offset += dev->core_index * SSB_CORE_SIZE;
  84. writew(value, bus->mmio + offset);
  85. }
  86. static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value)
  87. {
  88. struct ssb_bus *bus = dev->bus;
  89. offset += dev->core_index * SSB_CORE_SIZE;
  90. writel(value, bus->mmio + offset);
  91. }
  92. #ifdef CONFIG_SSB_BLOCKIO
  93. static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer,
  94. size_t count, u16 offset, u8 reg_width)
  95. {
  96. struct ssb_bus *bus = dev->bus;
  97. void __iomem *addr;
  98. offset += dev->core_index * SSB_CORE_SIZE;
  99. addr = bus->mmio + offset;
  100. switch (reg_width) {
  101. case sizeof(u8): {
  102. const u8 *buf = buffer;
  103. while (count) {
  104. __raw_writeb(*buf, addr);
  105. buf++;
  106. count--;
  107. }
  108. break;
  109. }
  110. case sizeof(u16): {
  111. const __le16 *buf = buffer;
  112. WARN_ON(count & 1);
  113. while (count) {
  114. __raw_writew((__force u16)(*buf), addr);
  115. buf++;
  116. count -= 2;
  117. }
  118. break;
  119. }
  120. case sizeof(u32): {
  121. const __le32 *buf = buffer;
  122. WARN_ON(count & 3);
  123. while (count) {
  124. __raw_writel((__force u32)(*buf), addr);
  125. buf++;
  126. count -= 4;
  127. }
  128. break;
  129. }
  130. default:
  131. WARN_ON(1);
  132. }
  133. }
  134. #endif /* CONFIG_SSB_BLOCKIO */
  135. /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
  136. const struct ssb_bus_ops ssb_host_soc_ops = {
  137. .read8 = ssb_host_soc_read8,
  138. .read16 = ssb_host_soc_read16,
  139. .read32 = ssb_host_soc_read32,
  140. .write8 = ssb_host_soc_write8,
  141. .write16 = ssb_host_soc_write16,
  142. .write32 = ssb_host_soc_write32,
  143. #ifdef CONFIG_SSB_BLOCKIO
  144. .block_read = ssb_host_soc_block_read,
  145. .block_write = ssb_host_soc_block_write,
  146. #endif
  147. };
  148. int ssb_host_soc_get_invariants(struct ssb_bus *bus,
  149. struct ssb_init_invariants *iv)
  150. {
  151. char buf[20];
  152. int len, err;
  153. /* Fill boardinfo structure */
  154. memset(&iv->boardinfo, 0, sizeof(struct ssb_boardinfo));
  155. len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf));
  156. if (len > 0) {
  157. err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor);
  158. if (err)
  159. pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n",
  160. buf);
  161. }
  162. if (!iv->boardinfo.vendor)
  163. iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
  164. len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
  165. if (len > 0) {
  166. err = kstrtou16(strim(buf), 0, &iv->boardinfo.type);
  167. if (err)
  168. pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n",
  169. buf);
  170. }
  171. memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
  172. ssb_fill_sprom_with_fallback(bus, &iv->sprom);
  173. if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
  174. iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
  175. return 0;
  176. }