rpi.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * (C) Copyright 2012-2016 Stephen Warren
  4. */
  5. #include <common.h>
  6. #include <inttypes.h>
  7. #include <config.h>
  8. #include <dm.h>
  9. #include <environment.h>
  10. #include <efi_loader.h>
  11. #include <fdt_support.h>
  12. #include <fdt_simplefb.h>
  13. #include <lcd.h>
  14. #include <memalign.h>
  15. #include <mmc.h>
  16. #include <asm/gpio.h>
  17. #include <asm/arch/mbox.h>
  18. #include <asm/arch/msg.h>
  19. #include <asm/arch/sdhci.h>
  20. #include <asm/global_data.h>
  21. #include <dm/platform_data/serial_bcm283x_mu.h>
  22. #ifdef CONFIG_ARM64
  23. #include <asm/armv8/mmu.h>
  24. #endif
  25. #include <watchdog.h>
  26. #include <dm/pinctrl.h>
  27. DECLARE_GLOBAL_DATA_PTR;
  28. /* From lowlevel_init.S */
  29. extern unsigned long fw_dtb_pointer;
  30. /* TODO(sjg@chromium.org): Move these to the msg.c file */
  31. struct msg_get_arm_mem {
  32. struct bcm2835_mbox_hdr hdr;
  33. struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
  34. u32 end_tag;
  35. };
  36. struct msg_get_board_rev {
  37. struct bcm2835_mbox_hdr hdr;
  38. struct bcm2835_mbox_tag_get_board_rev get_board_rev;
  39. u32 end_tag;
  40. };
  41. struct msg_get_board_serial {
  42. struct bcm2835_mbox_hdr hdr;
  43. struct bcm2835_mbox_tag_get_board_serial get_board_serial;
  44. u32 end_tag;
  45. };
  46. struct msg_get_mac_address {
  47. struct bcm2835_mbox_hdr hdr;
  48. struct bcm2835_mbox_tag_get_mac_address get_mac_address;
  49. u32 end_tag;
  50. };
  51. struct msg_get_clock_rate {
  52. struct bcm2835_mbox_hdr hdr;
  53. struct bcm2835_mbox_tag_get_clock_rate get_clock_rate;
  54. u32 end_tag;
  55. };
  56. #ifdef CONFIG_ARM64
  57. #define DTB_DIR "broadcom/"
  58. #else
  59. #define DTB_DIR ""
  60. #endif
  61. /*
  62. * http://raspberryalphaomega.org.uk/2013/02/06/automatic-raspberry-pi-board-revision-detection-model-a-b1-and-b2/
  63. * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=32733
  64. * http://git.drogon.net/?p=wiringPi;a=blob;f=wiringPi/wiringPi.c;h=503151f61014418b9c42f4476a6086f75cd4e64b;hb=refs/heads/master#l922
  65. *
  66. * In http://lists.denx.de/pipermail/u-boot/2016-January/243752.html
  67. * ("[U-Boot] [PATCH] rpi: fix up Model B entries") Dom Cobley at the RPi
  68. * Foundation stated that the following source was accurate:
  69. * https://github.com/AndrewFromMelbourne/raspberry_pi_revision
  70. */
  71. struct rpi_model {
  72. const char *name;
  73. const char *fdtfile;
  74. bool has_onboard_eth;
  75. };
  76. static const struct rpi_model rpi_model_unknown = {
  77. "Unknown model",
  78. DTB_DIR "bcm283x-rpi-other.dtb",
  79. false,
  80. };
  81. static const struct rpi_model rpi_models_new_scheme[] = {
  82. [0x0] = {
  83. "Model A",
  84. DTB_DIR "bcm2835-rpi-a.dtb",
  85. false,
  86. },
  87. [0x1] = {
  88. "Model B",
  89. DTB_DIR "bcm2835-rpi-b.dtb",
  90. true,
  91. },
  92. [0x2] = {
  93. "Model A+",
  94. DTB_DIR "bcm2835-rpi-a-plus.dtb",
  95. false,
  96. },
  97. [0x3] = {
  98. "Model B+",
  99. DTB_DIR "bcm2835-rpi-b-plus.dtb",
  100. true,
  101. },
  102. [0x4] = {
  103. "2 Model B",
  104. DTB_DIR "bcm2836-rpi-2-b.dtb",
  105. true,
  106. },
  107. [0x6] = {
  108. "Compute Module",
  109. DTB_DIR "bcm2835-rpi-cm.dtb",
  110. false,
  111. },
  112. [0x8] = {
  113. "3 Model B",
  114. DTB_DIR "bcm2837-rpi-3-b.dtb",
  115. true,
  116. },
  117. [0x9] = {
  118. "Zero",
  119. DTB_DIR "bcm2835-rpi-zero.dtb",
  120. false,
  121. },
  122. [0xA] = {
  123. "Compute Module 3",
  124. DTB_DIR "bcm2837-rpi-cm3.dtb",
  125. false,
  126. },
  127. [0xC] = {
  128. "Zero W",
  129. DTB_DIR "bcm2835-rpi-zero-w.dtb",
  130. false,
  131. },
  132. [0xD] = {
  133. "3 Model B+",
  134. DTB_DIR "bcm2837-rpi-3-b-plus.dtb",
  135. true,
  136. },
  137. };
  138. static const struct rpi_model rpi_models_old_scheme[] = {
  139. [0x2] = {
  140. "Model B",
  141. DTB_DIR "bcm2835-rpi-b.dtb",
  142. true,
  143. },
  144. [0x3] = {
  145. "Model B",
  146. DTB_DIR "bcm2835-rpi-b.dtb",
  147. true,
  148. },
  149. [0x4] = {
  150. "Model B rev2",
  151. DTB_DIR "bcm2835-rpi-b-rev2.dtb",
  152. true,
  153. },
  154. [0x5] = {
  155. "Model B rev2",
  156. DTB_DIR "bcm2835-rpi-b-rev2.dtb",
  157. true,
  158. },
  159. [0x6] = {
  160. "Model B rev2",
  161. DTB_DIR "bcm2835-rpi-b-rev2.dtb",
  162. true,
  163. },
  164. [0x7] = {
  165. "Model A",
  166. DTB_DIR "bcm2835-rpi-a.dtb",
  167. false,
  168. },
  169. [0x8] = {
  170. "Model A",
  171. DTB_DIR "bcm2835-rpi-a.dtb",
  172. false,
  173. },
  174. [0x9] = {
  175. "Model A",
  176. DTB_DIR "bcm2835-rpi-a.dtb",
  177. false,
  178. },
  179. [0xd] = {
  180. "Model B rev2",
  181. DTB_DIR "bcm2835-rpi-b-rev2.dtb",
  182. true,
  183. },
  184. [0xe] = {
  185. "Model B rev2",
  186. DTB_DIR "bcm2835-rpi-b-rev2.dtb",
  187. true,
  188. },
  189. [0xf] = {
  190. "Model B rev2",
  191. DTB_DIR "bcm2835-rpi-b-rev2.dtb",
  192. true,
  193. },
  194. [0x10] = {
  195. "Model B+",
  196. DTB_DIR "bcm2835-rpi-b-plus.dtb",
  197. true,
  198. },
  199. [0x11] = {
  200. "Compute Module",
  201. DTB_DIR "bcm2835-rpi-cm.dtb",
  202. false,
  203. },
  204. [0x12] = {
  205. "Model A+",
  206. DTB_DIR "bcm2835-rpi-a-plus.dtb",
  207. false,
  208. },
  209. [0x13] = {
  210. "Model B+",
  211. DTB_DIR "bcm2835-rpi-b-plus.dtb",
  212. true,
  213. },
  214. [0x14] = {
  215. "Compute Module",
  216. DTB_DIR "bcm2835-rpi-cm.dtb",
  217. false,
  218. },
  219. [0x15] = {
  220. "Model A+",
  221. DTB_DIR "bcm2835-rpi-a-plus.dtb",
  222. false,
  223. },
  224. };
  225. static uint32_t revision;
  226. static uint32_t rev_scheme;
  227. static uint32_t rev_type;
  228. static const struct rpi_model *model;
  229. #ifdef CONFIG_ARM64
  230. static struct mm_region bcm2837_mem_map[] = {
  231. {
  232. .virt = 0x00000000UL,
  233. .phys = 0x00000000UL,
  234. .size = 0x3f000000UL,
  235. .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
  236. PTE_BLOCK_INNER_SHARE
  237. }, {
  238. .virt = 0x3f000000UL,
  239. .phys = 0x3f000000UL,
  240. .size = 0x01000000UL,
  241. .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
  242. PTE_BLOCK_NON_SHARE |
  243. PTE_BLOCK_PXN | PTE_BLOCK_UXN
  244. }, {
  245. /* List terminator */
  246. 0,
  247. }
  248. };
  249. struct mm_region *mem_map = bcm2837_mem_map;
  250. #endif
  251. int dram_init(void)
  252. {
  253. ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1);
  254. int ret;
  255. BCM2835_MBOX_INIT_HDR(msg);
  256. BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY);
  257. ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
  258. if (ret) {
  259. printf("bcm2835: Could not query ARM memory size\n");
  260. return -1;
  261. }
  262. gd->ram_size = msg->get_arm_mem.body.resp.mem_size;
  263. return 0;
  264. }
  265. static void set_fdtfile(void)
  266. {
  267. const char *fdtfile;
  268. if (env_get("fdtfile"))
  269. return;
  270. fdtfile = model->fdtfile;
  271. env_set("fdtfile", fdtfile);
  272. }
  273. /*
  274. * If the firmware provided a valid FDT at boot time, let's expose it in
  275. * ${fdt_addr} so it may be passed unmodified to the kernel.
  276. */
  277. static void set_fdt_addr(void)
  278. {
  279. if (env_get("fdt_addr"))
  280. return;
  281. if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC)
  282. return;
  283. env_set_hex("fdt_addr", fw_dtb_pointer);
  284. }
  285. /*
  286. * Prevent relocation from stomping on a firmware provided FDT blob.
  287. */
  288. unsigned long board_get_usable_ram_top(unsigned long total_size)
  289. {
  290. if ((gd->ram_top - fw_dtb_pointer) > SZ_64M)
  291. return gd->ram_top;
  292. return fw_dtb_pointer & ~0xffff;
  293. }
  294. static void set_usbethaddr(void)
  295. {
  296. ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_mac_address, msg, 1);
  297. int ret;
  298. if (!model->has_onboard_eth)
  299. return;
  300. if (env_get("usbethaddr"))
  301. return;
  302. BCM2835_MBOX_INIT_HDR(msg);
  303. BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS);
  304. ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
  305. if (ret) {
  306. printf("bcm2835: Could not query MAC address\n");
  307. /* Ignore error; not critical */
  308. return;
  309. }
  310. eth_env_set_enetaddr("usbethaddr", msg->get_mac_address.body.resp.mac);
  311. if (!env_get("ethaddr"))
  312. env_set("ethaddr", env_get("usbethaddr"));
  313. return;
  314. }
  315. #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
  316. static void set_board_info(void)
  317. {
  318. char s[11];
  319. snprintf(s, sizeof(s), "0x%X", revision);
  320. env_set("board_revision", s);
  321. snprintf(s, sizeof(s), "%d", rev_scheme);
  322. env_set("board_rev_scheme", s);
  323. /* Can't rename this to board_rev_type since it's an ABI for scripts */
  324. snprintf(s, sizeof(s), "0x%X", rev_type);
  325. env_set("board_rev", s);
  326. env_set("board_name", model->name);
  327. }
  328. #endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */
  329. static void set_serial_number(void)
  330. {
  331. ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_serial, msg, 1);
  332. int ret;
  333. char serial_string[17] = { 0 };
  334. if (env_get("serial#"))
  335. return;
  336. BCM2835_MBOX_INIT_HDR(msg);
  337. BCM2835_MBOX_INIT_TAG_NO_REQ(&msg->get_board_serial, GET_BOARD_SERIAL);
  338. ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
  339. if (ret) {
  340. printf("bcm2835: Could not query board serial\n");
  341. /* Ignore error; not critical */
  342. return;
  343. }
  344. snprintf(serial_string, sizeof(serial_string), "%016" PRIx64,
  345. msg->get_board_serial.body.resp.serial);
  346. env_set("serial#", serial_string);
  347. }
  348. int misc_init_r(void)
  349. {
  350. set_fdt_addr();
  351. set_fdtfile();
  352. set_usbethaddr();
  353. #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
  354. set_board_info();
  355. #endif
  356. set_serial_number();
  357. return 0;
  358. }
  359. static void get_board_rev(void)
  360. {
  361. ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_rev, msg, 1);
  362. int ret;
  363. const struct rpi_model *models;
  364. uint32_t models_count;
  365. BCM2835_MBOX_INIT_HDR(msg);
  366. BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV);
  367. ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
  368. if (ret) {
  369. printf("bcm2835: Could not query board revision\n");
  370. /* Ignore error; not critical */
  371. return;
  372. }
  373. /*
  374. * For details of old-vs-new scheme, see:
  375. * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py
  376. * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282
  377. * (a few posts down)
  378. *
  379. * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the
  380. * lower byte to use as the board rev:
  381. * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250
  382. * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594
  383. */
  384. revision = msg->get_board_rev.body.resp.rev;
  385. if (revision & 0x800000) {
  386. rev_scheme = 1;
  387. rev_type = (revision >> 4) & 0xff;
  388. models = rpi_models_new_scheme;
  389. models_count = ARRAY_SIZE(rpi_models_new_scheme);
  390. } else {
  391. rev_scheme = 0;
  392. rev_type = revision & 0xff;
  393. models = rpi_models_old_scheme;
  394. models_count = ARRAY_SIZE(rpi_models_old_scheme);
  395. }
  396. if (rev_type >= models_count) {
  397. printf("RPI: Board rev 0x%x outside known range\n", rev_type);
  398. model = &rpi_model_unknown;
  399. } else if (!models[rev_type].name) {
  400. printf("RPI: Board rev 0x%x unknown\n", rev_type);
  401. model = &rpi_model_unknown;
  402. } else {
  403. model = &models[rev_type];
  404. }
  405. printf("RPI %s (0x%x)\n", model->name, revision);
  406. }
  407. int board_init(void)
  408. {
  409. #ifdef CONFIG_HW_WATCHDOG
  410. hw_watchdog_init();
  411. #endif
  412. get_board_rev();
  413. gd->bd->bi_boot_params = 0x100;
  414. return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD);
  415. }
  416. /*
  417. * If the firmware passed a device tree use it for U-Boot.
  418. */
  419. void *board_fdt_blob_setup(void)
  420. {
  421. if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC)
  422. return NULL;
  423. return (void *)fw_dtb_pointer;
  424. }
  425. int ft_board_setup(void *blob, bd_t *bd)
  426. {
  427. /*
  428. * For now, we simply always add the simplefb DT node. Later, we
  429. * should be more intelligent, and e.g. only do this if no enabled DT
  430. * node exists for the "real" graphics driver.
  431. */
  432. lcd_dt_simplefb_add_node(blob);
  433. #ifdef CONFIG_EFI_LOADER
  434. /* Reserve the spin table */
  435. efi_add_memory_map(0, 1, EFI_RESERVED_MEMORY_TYPE, 0);
  436. #endif
  437. return 0;
  438. }