ambapp.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /* GRLIB AMBA Plug&Play information scanning, relies on assembler
  2. * routines.
  3. *
  4. * (C) Copyright 2010, 2015
  5. * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
  6. *
  7. * SPDX-License-Identifier: GPL-2.0+
  8. */
  9. /* #define DEBUG */
  10. #include <common.h>
  11. #include <malloc.h>
  12. #include <ambapp.h>
  13. #include <config.h>
  14. /************ C INTERFACE OF ASSEMBLER SCAN ROUTINES ************/
  15. struct ambapp_find_apb_info {
  16. /* Address of APB device Plug&Play information */
  17. struct ambapp_pnp_apb *pnp;
  18. /* AHB Bus index of where the APB-Master Bridge device was found */
  19. int ahb_bus_index;
  20. int dec_index;
  21. };
  22. struct ambapp_find_ahb_info {
  23. /* Address of AHB device Plug&Play information */
  24. struct ambapp_pnp_ahb *pnp;
  25. /* AHB Bus index of where the AHB device was found */
  26. int ahb_bus_index;
  27. int dec_index;
  28. };
  29. extern void ambapp_find_buses(unsigned int ioarea, struct ambapp_bus *abus);
  30. extern int ambapp_find_apb(struct ambapp_bus *abus, unsigned int dev_vend,
  31. int index, struct ambapp_find_apb_info *result);
  32. extern int ambapp_find_ahb(struct ambapp_bus *abus, unsigned int dev_vend,
  33. int index, int type, struct ambapp_find_ahb_info *result);
  34. /************ C ROUTINES USED BY U-BOOT AMBA CORE DRIVERS ************/
  35. struct ambapp_bus ambapp_plb __section(.data);
  36. void ambapp_bus_init(
  37. unsigned int ioarea,
  38. unsigned int freq,
  39. struct ambapp_bus *abus)
  40. {
  41. int i;
  42. ambapp_find_buses(ioarea, abus);
  43. for (i = 0; i < 6; i++)
  44. if (abus->ioareas[i] == 0)
  45. break;
  46. abus->buses = i;
  47. abus->freq = freq;
  48. }
  49. /* Parse APB PnP Information */
  50. void ambapp_apb_parse(struct ambapp_find_apb_info *info, ambapp_apbdev *dev)
  51. {
  52. struct ambapp_pnp_apb *apb = info->pnp;
  53. unsigned int apbbase = (unsigned int)apb & 0xfff00000;
  54. dev->vendor = amba_vendor(apb->id);
  55. dev->device = amba_device(apb->id);
  56. dev->irq = amba_irq(apb->id);
  57. dev->ver = amba_ver(apb->id);
  58. dev->address = (apbbase | (((apb->iobar & 0xfff00000) >> 12))) &
  59. (((apb->iobar & 0x0000fff0) << 4) | 0xfff00000);
  60. dev->mask = amba_apb_mask(apb->iobar);
  61. dev->ahb_bus_index = info->ahb_bus_index - 1;
  62. }
  63. /* Parse AHB PnP information */
  64. void ambapp_ahb_parse(struct ambapp_find_ahb_info *info, ambapp_ahbdev *dev)
  65. {
  66. struct ambapp_pnp_ahb *ahb = info->pnp;
  67. unsigned int ahbbase = (unsigned int)ahb & 0xfff00000;
  68. int i, type;
  69. unsigned int addr, mask, mbar;
  70. dev->vendor = amba_vendor(ahb->id);
  71. dev->device = amba_device(ahb->id);
  72. dev->irq = amba_irq(ahb->id);
  73. dev->ver = amba_ver(ahb->id);
  74. dev->userdef[0] = ahb->custom[0];
  75. dev->userdef[1] = ahb->custom[1];
  76. dev->userdef[2] = ahb->custom[2];
  77. dev->ahb_bus_index = info->ahb_bus_index - 1;
  78. for (i = 0; i < 4; i++) {
  79. mbar = ahb->mbar[i];
  80. addr = amba_membar_start(mbar);
  81. type = amba_membar_type(mbar);
  82. if (type == AMBA_TYPE_AHBIO) {
  83. addr = amba_ahbio_adr(addr, ahbbase);
  84. mask = (((unsigned int)
  85. (amba_membar_mask((~mbar))<<8)|0xff))+1;
  86. } else {
  87. /* AHB memory area, absolute address */
  88. mask = (~((unsigned int)
  89. (amba_membar_mask(mbar)<<20)))+1;
  90. }
  91. dev->address[i] = addr;
  92. dev->mask[i] = mask;
  93. dev->type[i] = type;
  94. }
  95. }
  96. int ambapp_apb_find(struct ambapp_bus *abus, int vendor, int device,
  97. int index, ambapp_apbdev *dev)
  98. {
  99. unsigned int devid = AMBA_PNP_ID(vendor, device);
  100. int found;
  101. struct ambapp_find_apb_info apbdev;
  102. found = ambapp_find_apb(abus, devid, index, &apbdev);
  103. if (found == 1)
  104. ambapp_apb_parse(&apbdev, dev);
  105. return found;
  106. }
  107. int ambapp_apb_count(struct ambapp_bus *abus, int vendor, int device)
  108. {
  109. unsigned int devid = AMBA_PNP_ID(vendor, device);
  110. int found;
  111. struct ambapp_find_apb_info apbdev;
  112. found = ambapp_find_apb(abus, devid, 63, &apbdev);
  113. if (found == 1)
  114. return 64;
  115. else
  116. return 63 - apbdev.dec_index;
  117. }
  118. int ambapp_ahb_find(struct ambapp_bus *abus, int vendor, int device,
  119. int index, ambapp_ahbdev *dev, int type)
  120. {
  121. int found;
  122. struct ambapp_find_ahb_info ahbdev;
  123. unsigned int devid = AMBA_PNP_ID(vendor, device);
  124. found = ambapp_find_ahb(abus, devid, index, type, &ahbdev);
  125. if (found == 1)
  126. ambapp_ahb_parse(&ahbdev, dev);
  127. return found;
  128. }
  129. int ambapp_ahbmst_find(struct ambapp_bus *abus, int vendor, int device,
  130. int index, ambapp_ahbdev *dev)
  131. {
  132. return ambapp_ahb_find(abus, vendor, device, index, dev, DEV_AHB_MST);
  133. }
  134. int ambapp_ahbslv_find(struct ambapp_bus *abus, int vendor, int device,
  135. int index, ambapp_ahbdev *dev)
  136. {
  137. return ambapp_ahb_find(abus, vendor, device, index, dev, DEV_AHB_SLV);
  138. }
  139. int ambapp_ahb_count(struct ambapp_bus *abus, int vendor, int device, int type)
  140. {
  141. int found;
  142. struct ambapp_find_ahb_info ahbdev;
  143. unsigned int devid = AMBA_PNP_ID(vendor, device);
  144. found = ambapp_find_ahb(abus, devid, 63, type, &ahbdev);
  145. if (found == 1)
  146. return 64;
  147. else
  148. return 63 - ahbdev.dec_index;
  149. }
  150. int ambapp_ahbmst_count(struct ambapp_bus *abus, int vendor, int device)
  151. {
  152. return ambapp_ahb_count(abus, vendor, device, DEV_AHB_MST);
  153. }
  154. int ambapp_ahbslv_count(struct ambapp_bus *abus, int vendor, int device)
  155. {
  156. return ambapp_ahb_count(abus, vendor, device, DEV_AHB_SLV);
  157. }
  158. /* The define CONFIG_SYS_GRLIB_SINGLE_BUS may be defined on GRLIB systems
  159. * where only one AHB Bus is available - no bridges are present. This option
  160. * is available only to reduce the footprint.
  161. *
  162. * Defining this on a multi-bus GRLIB system may also work depending on the
  163. * design.
  164. */
  165. #ifndef CONFIG_SYS_GRLIB_SINGLE_BUS
  166. /* GAISLER AHB2AHB Version 1 Bridge Definitions */
  167. #define AHB2AHB_V1_FLAG_FFACT 0x0f0 /* Frequency factor against top bus */
  168. #define AHB2AHB_V1_FLAG_FFACT_DIR 0x100 /* Factor direction, 0=down, 1=up */
  169. #define AHB2AHB_V1_FLAG_MBUS 0x00c /* Master bus number mask */
  170. #define AHB2AHB_V1_FLAG_SBUS 0x003 /* Slave bus number mask */
  171. /* Get Parent bus frequency. Note that since we go from a "child" bus
  172. * to a parent bus, the frequency factor direction is inverted.
  173. */
  174. unsigned int gaisler_ahb2ahb_v1_freq(ambapp_ahbdev *ahb, unsigned int freq)
  175. {
  176. int dir;
  177. unsigned char ffact;
  178. /* Get division/multiple factor */
  179. ffact = (ahb->userdef[0] & AHB2AHB_V1_FLAG_FFACT) >> 4;
  180. if (ffact != 0) {
  181. dir = ahb->userdef[0] & AHB2AHB_V1_FLAG_FFACT_DIR;
  182. /* Calculate frequency by dividing or
  183. * multiplying system frequency
  184. */
  185. if (dir)
  186. freq = freq * ffact;
  187. else
  188. freq = freq / ffact;
  189. }
  190. return freq;
  191. }
  192. /* AHB2AHB and L2CACHE ver 2 is not supported yet. */
  193. unsigned int gaisler_ahb2ahb_v2_freq(ambapp_ahbdev *ahb, unsigned int freq)
  194. {
  195. panic("gaisler_ahb2ahb_v2_freq: AHB2AHB ver 2 not supported\n");
  196. return -1;
  197. }
  198. #endif
  199. /* Return the frequency of a AHB bus identified by index found
  200. * note that this is not the AHB Bus number.
  201. */
  202. unsigned int ambapp_bus_freq(struct ambapp_bus *abus, int ahb_bus_index)
  203. {
  204. unsigned int freq = abus->freq;
  205. #ifndef CONFIG_SYS_GRLIB_SINGLE_BUS
  206. unsigned int ioarea, ioarea_parent, bridge_pnp_ofs;
  207. struct ambapp_find_ahb_info ahbinfo;
  208. ambapp_ahbdev ahb;
  209. int parent;
  210. debug("ambapp_bus_freq: get freq on bus %d\n", ahb_bus_index);
  211. while (ahb_bus_index != 0) {
  212. debug(" BUS[0]: 0x%08x\n", abus->ioareas[0]);
  213. debug(" BUS[1]: 0x%08x\n", abus->ioareas[1]);
  214. debug(" BUS[2]: 0x%08x\n", abus->ioareas[2]);
  215. debug(" BUS[3]: 0x%08x\n", abus->ioareas[3]);
  216. debug(" BUS[4]: 0x%08x\n", abus->ioareas[4]);
  217. debug(" BUS[5]: 0x%08x\n", abus->ioareas[5]);
  218. /* Get I/O area of AHB bus */
  219. ioarea = abus->ioareas[ahb_bus_index];
  220. debug(" IOAREA: 0x%08x\n", ioarea);
  221. /* Get parent bus */
  222. parent = (ioarea & 0x7);
  223. if (parent == 0) {
  224. panic("%s: parent=0 indicates no parent! Stopping.\n",
  225. __func__);
  226. return -1;
  227. }
  228. parent = parent - 1;
  229. bridge_pnp_ofs = ioarea & 0x7e0;
  230. debug(" PARENT: %d\n", parent);
  231. debug(" BRIDGE_OFS: 0x%08x\n", bridge_pnp_ofs);
  232. /* Get AHB/AHB bridge PnP address */
  233. ioarea_parent = (abus->ioareas[parent] & 0xfff00000) |
  234. AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA;
  235. ahbinfo.pnp = (struct ambapp_pnp_ahb *)
  236. (ioarea_parent | bridge_pnp_ofs);
  237. debug(" IOAREA PARENT: 0x%08x\n", ioarea_parent);
  238. debug(" BRIDGE PNP: 0x%p\n", ahbinfo.pnp);
  239. /* Parse the AHB information */
  240. ahbinfo.ahb_bus_index = parent;
  241. ambapp_ahb_parse(&ahbinfo, &ahb);
  242. debug(" BRIDGE ID: VENDOR=%d(0x%x), DEVICE=%d(0x%x)\n",
  243. ahb.vendor, ahb.vendor, ahb.device, ahb.device);
  244. /* Different bridges may convert frequency differently */
  245. if ((ahb.vendor == VENDOR_GAISLER) &&
  246. ((ahb.device == GAISLER_AHB2AHB) ||
  247. (ahb.device == GAISLER_L2CACHE))) {
  248. /* Get new frequency */
  249. if (ahb.ver > 1)
  250. freq = gaisler_ahb2ahb_v2_freq(&ahb, freq);
  251. else
  252. freq = gaisler_ahb2ahb_v1_freq(&ahb, freq);
  253. debug(" NEW FREQ: %dHz\n", freq);
  254. } else {
  255. panic("%s: unsupported AMBA bridge\n", __func__);
  256. return -1;
  257. }
  258. /* Step upwards towards system top bus */
  259. ahb_bus_index = parent;
  260. }
  261. #endif
  262. debug("ambapp_bus_freq: %dHz\n", freq);
  263. return freq;
  264. }