malta-dtshim.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * Copyright (C) 2015 Imagination Technologies
  3. * Author: Paul Burton <paul.burton@imgtec.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. */
  10. #include <linux/bug.h>
  11. #include <linux/kernel.h>
  12. #include <linux/libfdt.h>
  13. #include <linux/of_fdt.h>
  14. #include <linux/sizes.h>
  15. #include <asm/bootinfo.h>
  16. #include <asm/fw/fw.h>
  17. #include <asm/page.h>
  18. static unsigned char fdt_buf[16 << 10] __initdata;
  19. /* determined physical memory size, not overridden by command line args */
  20. extern unsigned long physical_memsize;
  21. #define MAX_MEM_ARRAY_ENTRIES 1
  22. static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size)
  23. {
  24. unsigned long size_preio;
  25. unsigned entries;
  26. entries = 1;
  27. mem_array[0] = cpu_to_be32(PHYS_OFFSET);
  28. if (config_enabled(CONFIG_EVA)) {
  29. /*
  30. * The current Malta EVA configuration is "special" in that it
  31. * always makes use of addresses in the upper half of the 32 bit
  32. * physical address map, which gives it a contiguous region of
  33. * DDR but limits it to 2GB.
  34. */
  35. mem_array[1] = cpu_to_be32(size);
  36. } else {
  37. size_preio = min_t(unsigned long, size, SZ_256M);
  38. mem_array[1] = cpu_to_be32(size_preio);
  39. }
  40. BUG_ON(entries > MAX_MEM_ARRAY_ENTRIES);
  41. return entries;
  42. }
  43. static void __init append_memory(void *fdt, int root_off)
  44. {
  45. __be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES];
  46. unsigned long memsize;
  47. unsigned mem_entries;
  48. int i, err, mem_off;
  49. char *var, param_name[10], *var_names[] = {
  50. "ememsize", "memsize",
  51. };
  52. /* if a memory node already exists, leave it alone */
  53. mem_off = fdt_path_offset(fdt, "/memory");
  54. if (mem_off >= 0)
  55. return;
  56. /* find memory size from the bootloader environment */
  57. for (i = 0; i < ARRAY_SIZE(var_names); i++) {
  58. var = fw_getenv(var_names[i]);
  59. if (!var)
  60. continue;
  61. err = kstrtoul(var, 0, &physical_memsize);
  62. if (!err)
  63. break;
  64. pr_warn("Failed to read the '%s' env variable '%s'\n",
  65. var_names[i], var);
  66. }
  67. if (!physical_memsize) {
  68. pr_warn("The bootloader didn't provide memsize: defaulting to 32MB\n");
  69. physical_memsize = 32 << 20;
  70. }
  71. if (config_enabled(CONFIG_CPU_BIG_ENDIAN)) {
  72. /*
  73. * SOC-it swaps, or perhaps doesn't swap, when DMA'ing
  74. * the last word of physical memory.
  75. */
  76. physical_memsize -= PAGE_SIZE;
  77. }
  78. /* default to using all available RAM */
  79. memsize = physical_memsize;
  80. /* allow the user to override the usable memory */
  81. for (i = 0; i < ARRAY_SIZE(var_names); i++) {
  82. snprintf(param_name, sizeof(param_name), "%s=", var_names[i]);
  83. var = strstr(arcs_cmdline, param_name);
  84. if (!var)
  85. continue;
  86. memsize = memparse(var + strlen(param_name), NULL);
  87. }
  88. /* if the user says there's more RAM than we thought, believe them */
  89. physical_memsize = max_t(unsigned long, physical_memsize, memsize);
  90. /* append memory to the DT */
  91. mem_off = fdt_add_subnode(fdt, root_off, "memory");
  92. if (mem_off < 0)
  93. panic("Unable to add memory node to DT: %d", mem_off);
  94. err = fdt_setprop_string(fdt, mem_off, "device_type", "memory");
  95. if (err)
  96. panic("Unable to set memory node device_type: %d", err);
  97. mem_entries = gen_fdt_mem_array(mem_array, physical_memsize);
  98. err = fdt_setprop(fdt, mem_off, "reg", mem_array,
  99. mem_entries * 2 * sizeof(mem_array[0]));
  100. if (err)
  101. panic("Unable to set memory regs property: %d", err);
  102. mem_entries = gen_fdt_mem_array(mem_array, memsize);
  103. err = fdt_setprop(fdt, mem_off, "linux,usable-memory", mem_array,
  104. mem_entries * 2 * sizeof(mem_array[0]));
  105. if (err)
  106. panic("Unable to set linux,usable-memory property: %d", err);
  107. }
  108. void __init *malta_dt_shim(void *fdt)
  109. {
  110. int root_off, len, err;
  111. const char *compat;
  112. if (fdt_check_header(fdt))
  113. panic("Corrupt DT");
  114. err = fdt_open_into(fdt, fdt_buf, sizeof(fdt_buf));
  115. if (err)
  116. panic("Unable to open FDT: %d", err);
  117. root_off = fdt_path_offset(fdt_buf, "/");
  118. if (root_off < 0)
  119. panic("No / node in DT");
  120. compat = fdt_getprop(fdt_buf, root_off, "compatible", &len);
  121. if (!compat)
  122. panic("No root compatible property in DT: %d", len);
  123. /* if this isn't Malta, leave the DT alone */
  124. if (strncmp(compat, "mti,malta", len))
  125. return fdt;
  126. append_memory(fdt_buf, root_off);
  127. err = fdt_pack(fdt_buf);
  128. if (err)
  129. panic("Unable to pack FDT: %d\n", err);
  130. return fdt_buf;
  131. }