raspi.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. #include "raspi.h"
  2. #include <stdint.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include "rpi-boot/timer.h"
  6. // from https://github.com/rsta2/uspi/blob/ebc7cbe9cbc637c9cd54b5362764581990f41d00/env/lib/synchronize.c
  7. //
  8. // Cache maintenance operations for ARMv7-A
  9. //
  10. // See: ARMv7-A Architecture Reference Manual, Section B4.2.1
  11. //
  12. // NOTE: The following functions should hold all variables in CPU registers. Currently this will be
  13. // ensured using the register keyword and maximum optimization (see uspienv/synchronize.h).
  14. //
  15. // The following numbers can be determined (dynamically) using CTR, CSSELR, CCSIDR and CLIDR.
  16. // As long we use the Cortex-A7 implementation in the BCM2836 these static values will work:
  17. //
  18. #define SETWAY_LEVEL_SHIFT 1
  19. #define L1_DATA_CACHE_SETS 128
  20. #define L1_DATA_CACHE_WAYS 4
  21. #define L1_SETWAY_WAY_SHIFT 30 // 32-Log2(L1_DATA_CACHE_WAYS)
  22. #define L1_DATA_CACHE_LINE_LENGTH 64
  23. #define L1_SETWAY_SET_SHIFT 6 // Log2(L1_DATA_CACHE_LINE_LENGTH)
  24. #define L2_CACHE_SETS 1024
  25. #define L2_CACHE_WAYS 8
  26. #define L2_SETWAY_WAY_SHIFT 29 // 32-Log2(L2_CACHE_WAYS)
  27. #define L2_CACHE_LINE_LENGTH 64
  28. #define L2_SETWAY_SET_SHIFT 6 // Log2(L2_CACHE_LINE_LENGTH)
  29. #define DATA_CACHE_LINE_LENGTH_MIN 64 // min(L1_DATA_CACHE_LINE_LENGTH, L2_CACHE_LINE_LENGTH)
  30. void arm_invalidate_data_caches(void)
  31. {
  32. // invalidate L1 data cache
  33. for (register unsigned nSet = 0; nSet < L1_DATA_CACHE_SETS; nSet++)
  34. {
  35. for (register unsigned nWay = 0; nWay < L1_DATA_CACHE_WAYS; nWay++)
  36. {
  37. register uint32_t nSetWayLevel = nWay << L1_SETWAY_WAY_SHIFT
  38. | nSet << L1_SETWAY_SET_SHIFT
  39. | 0 << SETWAY_LEVEL_SHIFT;
  40. __asm volatile ("mcr p15, 0, %0, c7, c6, 2" : : "r" (nSetWayLevel) : "memory"); // DCISW
  41. }
  42. }
  43. // invalidate L2 unified cache
  44. for (register unsigned nSet = 0; nSet < L2_CACHE_SETS; nSet++)
  45. {
  46. for (register unsigned nWay = 0; nWay < L2_CACHE_WAYS; nWay++)
  47. {
  48. register uint32_t nSetWayLevel = nWay << L2_SETWAY_WAY_SHIFT
  49. | nSet << L2_SETWAY_SET_SHIFT
  50. | 1 << SETWAY_LEVEL_SHIFT;
  51. __asm volatile ("mcr p15, 0, %0, c7, c6, 2" : : "r" (nSetWayLevel) : "memory"); // DCISW
  52. }
  53. }
  54. }
  55. void arm_clear_data_caches(void)
  56. {
  57. // clean L1 data cache
  58. for (register unsigned nSet = 0; nSet < L1_DATA_CACHE_SETS; nSet++)
  59. {
  60. for (register unsigned nWay = 0; nWay < L1_DATA_CACHE_WAYS; nWay++)
  61. {
  62. register uint32_t nSetWayLevel = nWay << L1_SETWAY_WAY_SHIFT
  63. | nSet << L1_SETWAY_SET_SHIFT
  64. | 0 << SETWAY_LEVEL_SHIFT;
  65. __asm volatile ("mcr p15, 0, %0, c7, c10, 2" : : "r" (nSetWayLevel) : "memory"); // DCCSW
  66. }
  67. }
  68. // clean L2 unified cache
  69. for (register unsigned nSet = 0; nSet < L2_CACHE_SETS; nSet++)
  70. {
  71. for (register unsigned nWay = 0; nWay < L2_CACHE_WAYS; nWay++)
  72. {
  73. register uint32_t nSetWayLevel = nWay << L2_SETWAY_WAY_SHIFT
  74. | nSet << L2_SETWAY_SET_SHIFT
  75. | 1 << SETWAY_LEVEL_SHIFT;
  76. __asm volatile ("mcr p15, 0, %0, c7, c10, 2" : : "r" (nSetWayLevel) : "memory"); // DCCSW
  77. }
  78. }
  79. }
  80. void mmio_write(uint32_t reg, uint32_t data)
  81. {
  82. *(volatile uint32_t *)reg = data;
  83. }
  84. uint32_t mmio_read(uint32_t reg)
  85. {
  86. return *(volatile uint32_t *)reg;
  87. }
  88. void uart_putc(unsigned char byte)
  89. {
  90. // Wait for UART to become ready to transmit.
  91. while (mmio_read(UART0_FR) & (1 << 5)) { }
  92. mmio_write(UART0_DR, byte);
  93. }
  94. unsigned char uart_getc()
  95. {
  96. // Wait for UART to have received something.
  97. while (mmio_read(UART0_FR) & (1 << 4)) { }
  98. return mmio_read(UART0_DR);
  99. }
  100. void delay(int32_t count)
  101. {
  102. __asm("__delay_%=: subs %[count], %[count], #1; bne __delay_%=\n"
  103. : : [count]"r"(count) : "cc");
  104. }
  105. void uart_write(const unsigned char* buffer, uint32_t size)
  106. {
  107. for (uint32_t i = 0; i < size; i++) {
  108. uart_putc(buffer[i]);
  109. }
  110. }
  111. void uart_puts(const char* str)
  112. {
  113. uart_write((const unsigned char*) str, strlen(str));
  114. }
  115. /*
  116. void uart_init()
  117. {
  118. // Disable UART0.
  119. mmio_write(UART0_CR, 0x00000000);
  120. // Setup the GPIO pin 14 && 15.
  121. // Disable pull up/down for all GPIO pins & delay for 150 cycles.
  122. mmio_write(GPPUD, 0x00000000);
  123. delay(150);
  124. // Disable pull up/down for pin 14,15 & delay for 150 cycles.
  125. mmio_write(GPPUDCLK0, (1 << 14) | (1 << 15));
  126. delay(150);
  127. // Write 0 to GPPUDCLK0 to make it take effect.
  128. mmio_write(GPPUDCLK0, 0x00000000);
  129. // Clear pending interrupts.
  130. mmio_write(UART0_ICR, 0x7FF);
  131. // Set integer & fractional part of baud rate.
  132. // Divider = UART_CLOCK/(16 * Baud)
  133. // Fraction part register = (Fractional part * 64) + 0.5
  134. // UART_CLOCK = 3000000; Baud = 115200.
  135. // Divider = 3000000 / (16 * 115200) = 1.627 = ~1.
  136. // Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40.
  137. mmio_write(UART0_IBRD, 1);
  138. mmio_write(UART0_FBRD, 40);
  139. // Enable FIFO & 8 bit data transmissio (1 stop bit, no parity).
  140. mmio_write(UART0_LCRH, (1 << 4) | (1 << 5) | (1 << 6));
  141. // Mask all interrupts.
  142. mmio_write(UART0_IMSC, (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) |
  143. (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10));
  144. // Enable UART0, receive & transfer part of UART.
  145. mmio_write(UART0_CR, (1 << 0) | (1 << 8) | (1 << 9));
  146. }*/
  147. void uart_init()
  148. {
  149. mmio_write(UART0_CR, 0x0);
  150. mmio_write(GPPUD, 0x0);
  151. usleep(150000);
  152. mmio_write(GPPUDCLK0, (1 << 14) | (1 << 15));
  153. usleep(150000);
  154. mmio_write(GPPUDCLK0, 0x0);
  155. mmio_write(UART0_ICR, 0x7ff);
  156. mmio_write(UART0_IBRD, 1);
  157. mmio_write(UART0_FBRD, 40);
  158. mmio_write(UART0_LCRH, (1 << 4) | (1 << 5) | (1 << 6));
  159. mmio_write(UART0_IMSC, (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) |
  160. (1 << 8) | (1 << 9) | (1 << 10));
  161. mmio_write(UART0_CR, (1 << 0) | (1 << 8) | (1 << 9));
  162. }
  163. void mailbox_write(uint32_t* fbinfo_addr, unsigned int channel)
  164. {
  165. while(1)
  166. {
  167. //uart_puts("write loop 1\n");
  168. if((mmio_read(mailbox+0x18)&0x80000000)==0) break;
  169. }
  170. mmio_write(mailbox+0x20, (uint32_t)fbinfo_addr+channel);
  171. }
  172. unsigned int mailbox_read(unsigned int channel)
  173. {
  174. uint32_t ra;
  175. while(1)
  176. {
  177. while(1)
  178. {
  179. //uart_puts("read loop 1\n");
  180. ra=mmio_read(mailbox+0x18);
  181. if((ra&0x40000000)==0) break;
  182. }
  183. //uart_puts("read loop 2\n");
  184. ra=mmio_read(mailbox);
  185. if((ra&0xf)==channel) break;
  186. }
  187. return ra;
  188. }
  189. #define t_set_physical_display 0x00048003
  190. #define t_set_virtual_buffer 0x00048004
  191. #define t_set_depth 0x00048005
  192. #define t_set_virtual_offset 0x00048009
  193. #define t_allocate_buffer 0x00040001
  194. static volatile uint32_t gfx_message[] __attribute__ ((aligned (16))) = {
  195. 27*4, // size
  196. 0,
  197. t_set_physical_display,
  198. 8,
  199. 8,
  200. 1920,
  201. 1080,
  202. t_set_virtual_buffer,
  203. 8,
  204. 8,
  205. 1920,
  206. 1080,
  207. t_set_depth,
  208. 4,
  209. 4,
  210. 16,
  211. t_set_virtual_offset,
  212. 8,
  213. 8,
  214. 0,
  215. 0,
  216. t_allocate_buffer,
  217. 8,
  218. 8,
  219. 0,
  220. 0,
  221. 0
  222. };
  223. uint32_t* init_rpi_gfx()
  224. {
  225. unsigned int ra,rb;
  226. unsigned int ry,rx;
  227. arm_dsb();
  228. // https://github.com/PeterLemon/RaspberryPi/blob/master/HelloWorld/CPU/LIB/R_PI2.INC
  229. *((volatile uint32_t*)(PERIPHERAL_BASE + 0xb880 + 0x20 + 0x8)) = (uint32_t)gfx_message + 0x8; // MAIL_TAGS = 8
  230. uint32_t* framebuffer = 0;
  231. do {
  232. arm_dmb();
  233. arm_isb();
  234. framebuffer = (uint32_t*)gfx_message[24];
  235. printf("-- waiting for framebuffer…\r\n");
  236. } while (!framebuffer);
  237. return framebuffer;
  238. }
  239. static volatile uint32_t qpu_message[] __attribute__ ((aligned (16))) = {
  240. 12*4, // size
  241. 0,
  242. SET_CLOCK_RATE,
  243. 8,
  244. 8,
  245. CLK_V3D_ID,
  246. 250*1000*1000, // 250 mhz
  247. ENABLE_QPU,
  248. 4,
  249. 4,
  250. 1,
  251. 0
  252. };
  253. void init_rpi_qpu() {
  254. *((volatile uint32_t*)(PERIPHERAL_BASE + 0xb880 + 0x20 + 0x8)) = (uint32_t)qpu_message + 0x8; // MAIL_TAGS = 8
  255. do {
  256. arm_dmb();
  257. arm_isb();
  258. printf("-- waiting for qpu ack…\r\n");
  259. } while (!qpu_message[1]);
  260. }
  261. #include "mmu.c"