mblock_v2.c 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2015. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. *
  31. * The following software/firmware and/or related documentation ("MediaTek Software")
  32. * have been modified by MediaTek Inc. All revisions are subject to any receiver's
  33. * applicable license agreements with MediaTek Inc.
  34. */
  35. #include <debug.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <platform.h>
  39. #include <platform/boot_mode.h>
  40. #include <libfdt.h>
  41. #include <arch/arm/mmu.h>
  42. #include <ssmr.h>
  43. #ifdef MBLOCK_LIB_SUPPORT
  44. #ifdef NEW_MEMORY_RESERVED_MODEL
  45. #error NEW_MEMORY_RESERVED_MODEL is deprecated , you should not define it and still enable MBLOCK_LIB_SUPPORT Plz choose either
  46. #endif
  47. /*please acquire mblock_lock before traverse the list*/
  48. #define for_each_mblock_reserved(Mmblock_info, pp_reserve) \
  49. for (pp_reserve = &Mmblock_info->reserved[0];\
  50. pp_reserve <= &Mmblock_info->reserved[Mmblock_info->reserved_num - 1]; pp_reserve++)
  51. #define mblock_debug 0
  52. int get_mblock_num(void)
  53. {
  54. return g_boot_arg->mblock_info.mblock_num;
  55. }
  56. static void mblock_version_check(void)
  57. {
  58. mblock_info_t *mblock_info = &g_boot_arg->mblock_info;
  59. if (mblock_info->mblock_magic != MBLOCK_MAGIC || mblock_info->mblock_version != MBLOCK_VERSION) {
  60. dprintf(CRITICAL, "\n\n\n ***Critical ERROR, PL and LK mblock mismatch , halt stop boot*****\n\n\n");
  61. while (1)
  62. ;
  63. }
  64. }
  65. int setup_mem_property_use_mblock_info(dt_dram_info *property, size_t p_size)
  66. {
  67. dram_info_t *dram_info = &g_boot_arg->orig_dram_info;
  68. dt_dram_info *p;
  69. unsigned int i;
  70. mblock_info_t * mblock_info = &g_boot_arg->mblock_info;
  71. u64 mblock_low_start = 0, mblock_high_end = 0, reserved_low_start = 0
  72. , reserved_high_end = 0, mem_start,mem_sz;
  73. /* FixMe: assum physical memory is continuous with multiple bank
  74. * ban0 and ban1 should be continuous , if not , we need to modify
  75. * accordinly. Search for lowest value in mblock and reerved info
  76. * the lowest value will be the start of mem and the highest will
  77. * be end of dram , we only need to setup one mem dts node accordingly */
  78. if (p_size < 1) {
  79. dprintf(CRITICAL, "dram_info->rank_num =%d is bigger than mem_property=%d\n", dram_info->rank_num, p_size);
  80. return 1;
  81. }
  82. /* mblock is ordered, we can assum first mblock have the lowest value
  83. * so is highest*/
  84. mblock_low_start = mblock_info->mblock[0].start;
  85. mblock_high_end = mblock_info->mblock[mblock_info->mblock_num - 1].start +
  86. mblock_info->mblock[mblock_info->mblock_num - 1].size;
  87. /* reserved info is not ordered , we need to traverse to find out min
  88. * and max value */
  89. reserved_low_start = mblock_info->reserved[0].start;
  90. reserved_high_end = mblock_info->reserved[mblock_info->reserved_num - 1].start + \
  91. mblock_info->reserved[mblock_info->reserved_num - 1].size;
  92. for (i = 0; i<mblock_info->reserved_num; i++) {
  93. if (mblock_info->reserved[i].start < reserved_low_start) {
  94. reserved_low_start = mblock_info->reserved[i].start;
  95. }
  96. if ((mblock_info->reserved[i].start + mblock_info->reserved[i].size) > reserved_high_end) {
  97. reserved_high_end = mblock_info->reserved[i].start + mblock_info->reserved[i].size;
  98. }
  99. }
  100. mem_start = (reserved_low_start < mblock_low_start)?reserved_low_start:mblock_low_start;
  101. mem_sz = (reserved_high_end > mblock_high_end)\
  102. ?(reserved_high_end - mem_start):(mblock_high_end - mem_start);
  103. p = (property );
  104. p->start_hi = cpu_to_fdt32(mem_start>>32);
  105. p->start_lo = cpu_to_fdt32(mem_start);
  106. p->size_hi = cpu_to_fdt32((mem_sz>>32));
  107. p->size_lo = cpu_to_fdt32(mem_sz);
  108. dprintf(INFO, " mem_start=0x%llx mem_sz=0x%llx\n", mem_start, mem_sz);
  109. dprintf(INFO, " mem_reg_property[%d].start_hi = 0x%08X\n", i, p->start_hi);
  110. dprintf(INFO, " mem_reg_property[%d].start_lo = 0x%08X\n", i, p->start_lo);
  111. dprintf(INFO, " mem_reg_property[%d].size_hi = 0x%08X\n", i, p->size_hi);
  112. dprintf(INFO, " mem_reg_property[%d].size_lo = 0x%08X\n", i, p->size_lo);
  113. return 0;
  114. }
  115. int mblock_reserved_append(void *fdt)
  116. {
  117. int offset, ret = 0;
  118. int nodeoffset = 0;
  119. unsigned int i;
  120. char node_name[128];
  121. char compatible[MBLOCK_RESERVED_NAME_SIZE + 64];
  122. dt_dram_info reg_info;
  123. reserved_t *reserved;
  124. offset = fdt_path_offset(fdt, "/reserved-memory");
  125. if (offset < 0) {
  126. dprintf(CRITICAL, "couldn't find /reserved-memory\n");
  127. return 1;
  128. }
  129. for (i = 0; i < g_boot_arg->mblock_info.reserved_num; i++) {
  130. reserved = &g_boot_arg->mblock_info.reserved[i];
  131. snprintf(node_name, sizeof(node_name), "mblock-%d-%s", i+1, reserved->name);
  132. #if mblock_debug
  133. dprintf(INFO, "%s: add_subnode name=%s start:0x%llx size:0x%llx\n", __func__, node_name, reserved->start, reserved->size);
  134. #endif
  135. nodeoffset = fdt_add_subnode(fdt, offset, node_name);
  136. if (nodeoffset < 0) {
  137. dprintf(CRITICAL, "Warning: can't add mblock-reserved-memory node in device tree nodeoffset=0x%x\n", nodeoffset);
  138. return 1;
  139. }
  140. snprintf(compatible, sizeof(compatible), "mediatek,%s", reserved->name);
  141. ret = fdt_setprop_string(fdt, nodeoffset, "compatible", compatible);
  142. if (ret) {
  143. dprintf(CRITICAL, "Warning: can't add mblock-reserved-memory compatible property in device tree ret=0x%x\n", ret);
  144. return 1;
  145. }
  146. if (!reserved->mapping) {
  147. ret = fdt_setprop(fdt, nodeoffset, "no-map", NULL, 0);
  148. if (ret) {
  149. dprintf(CRITICAL, "Warning: can't add mblock-reserved-memory no-map property in device tree ret=0x%x\n", ret);
  150. return 1;
  151. }
  152. }
  153. reg_info.start_hi = cpu_to_fdt32(reserved->start>>32);
  154. reg_info.start_lo = cpu_to_fdt32(reserved->start);
  155. reg_info.size_hi = cpu_to_fdt32((reserved->size)>>32);
  156. reg_info.size_lo = cpu_to_fdt32(reserved->size);
  157. ret = fdt_setprop(fdt, nodeoffset, "reg", &reg_info, sizeof(reg_info));
  158. if (ret) {
  159. dprintf(CRITICAL, "Warning: can't add mblock-reserved-memory reg property in device tree ret=0x%x\n", ret);
  160. return 1;
  161. }
  162. #if mblock_debug
  163. dprintf(SPEW, "mblock-reserved-memory is appended (0x%llx, 0x%llx)\n",
  164. reserved->start, reserved->size);
  165. #endif
  166. }
  167. return ret;
  168. }
  169. void mblock_show_info(void)
  170. {
  171. mblock_info_t *mblock_info = &g_boot_arg->mblock_info;
  172. unsigned int i;
  173. u64 start, sz;
  174. dprintf(CRITICAL, "mblock_magic:0x%x mblock_version:0x%x\n", \
  175. mblock_info->mblock_magic, mblock_info->mblock_version);
  176. mblock_version_check();
  177. for (i = 0; i < mblock_info->mblock_num; i++) {
  178. start = mblock_info->mblock[i].start;
  179. sz = mblock_info->mblock[i].size;
  180. dprintf(CRITICAL, "mblock[%d].start: 0x%llx, size: 0x%llx\n", i,
  181. start, sz);
  182. }
  183. for (i = 0; i < mblock_info->reserved_num; i++) {
  184. start = mblock_info->reserved[i].start;
  185. sz = mblock_info->reserved[i].size;
  186. dprintf(CRITICAL, "mblock_reserve-R[%d].start: 0x%llx, size: 0x%llx map:%d name:%s\n", i,
  187. start, sz, mblock_info->reserved[i].mapping, mblock_info->reserved[i].name);
  188. }
  189. }
  190. /*
  191. * reserve a memory from mblock
  192. * @mblock_info: address of mblock_info
  193. * @reserved_size: size of memory
  194. * @align: alignment
  195. * @limit: address limit. Must higher than return address + reserved_size
  196. * @mapping: describe kernel mapping mechanism , 1:map or 0:no-map
  197. * @name: assign a dedicated name for this memory area
  198. * It returns as high address as possible.
  199. */
  200. u64 mblock_reserve_ext(mblock_info_t *mblock_info, u64 reserved_size, u64 align, u64 limit,
  201. u32 mapping, char *name)
  202. {
  203. unsigned int i;
  204. int target = -1;
  205. u64 start, end, sz, max_addr = 0;
  206. u64 reserved_addr = 0;
  207. mblock_t mblock;
  208. mblock_version_check();
  209. if (mblock_info->mblock_num >= (MBLOCK_NUM_MAX - 1) || mblock_info->reserved_num >= (MBLOCK_RESERVED_NUM_MAX - 1)||\
  210. (mapping >> 1) || (name)?(strlen(name) >= (MBLOCK_RESERVED_NAME_SIZE - 1)):true) {
  211. /* the mblock[] is full */
  212. dprintf(CRITICAL, "mblock_reserve error: mblock_num or reserved_num is full mblock_num=%d, \
  213. reserved_num=%d mapping=%d name=%s\n", mblock_info->mblock_num, mblock_info->reserved_num, mapping, name);
  214. return 0;
  215. }
  216. if (!align)
  217. align = 0x1000;
  218. /* must be at least 4k aligned */
  219. if (align & (0x1000 - 1))
  220. align &= ~(0x1000 - 1);
  221. for (i = 0; i < mblock_info->mblock_num; i++) {
  222. start = mblock_info->mblock[i].start;
  223. sz = mblock_info->mblock[i].size;
  224. end = limit < (start + sz) ? limit : (start + sz);
  225. if( reserved_size > sz || limit <= start || end <= start) {
  226. #if mblock_debug
  227. dprintf(CRITICAL,"skip this mblock start=%llx sz=%llx limit=%llx end=%llx\n",
  228. start, sz, limit, end);
  229. #endif
  230. continue;
  231. }
  232. reserved_addr = (end - reserved_size);
  233. reserved_addr &= ~(align - 1);
  234. #if mblock_debug
  235. dprintf(CRITICAL, "mblock[%d].start: 0x%llx, sz: 0x%llx, limit: 0x%llx, max_addr: 0x%llx, target: %d, reserved_addr: 0x%llx,"
  236. "reserved_size: 0x%llx\n",
  237. i, start, sz, limit, max_addr,
  238. target, reserved_addr, reserved_size);
  239. dprintf(CRITICAL, "mblock_reserve dbg[%d]: %d, %d, %d, %d\n",
  240. i, (reserved_addr + reserved_size <= start + sz),
  241. (reserved_addr >= start),
  242. (start + sz > max_addr),
  243. (reserved_addr + reserved_size <= limit));
  244. #endif
  245. if ((reserved_addr + reserved_size <= start + sz) &&
  246. (reserved_addr >= start) &&
  247. (start + sz > max_addr) &&
  248. (reserved_addr + reserved_size <= limit)) {
  249. max_addr = start + sz;
  250. target = i;
  251. }
  252. }
  253. if (target < 0) {
  254. dprintf(CRITICAL, "mblock_reserve error: cannot find a target\n");
  255. dprintf(CRITICAL, "requester info => sz: 0x%llx map:%d name:%s\n", reserved_size, mapping, name);
  256. mblock_show_info();
  257. return 0;
  258. }
  259. /* update variable reference to correct target info*/
  260. start = mblock_info->mblock[target].start;
  261. sz = mblock_info->mblock[target].size;
  262. end = limit < (start + sz) ? limit : (start + sz);
  263. reserved_addr = (end - reserved_size);
  264. reserved_addr &= ~(align - 1);
  265. /* store reserved_t info */
  266. /* dprintf(CRITICAL,"mblock_info->reserved_num=%d\n",mblock_info->reserved_num); */
  267. /*sanity check , reserved_num of array must be empty */
  268. if (mblock_info->reserved[mblock_info->reserved_num].start) {
  269. dprintf(CRITICAL, "mblock_reserve error , resreved slot already exist\
  270. start=0x%llx size=0x%llx\n", mblock_info->reserved[mblock_info->reserved_num].start
  271. , mblock_info->reserved[mblock_info->reserved_num].size);
  272. dprintf(CRITICAL, "Requester info => sz: 0x%llx map:%d name:%s\n", reserved_size, mapping, name);
  273. mblock_show_info();
  274. return 0;
  275. }
  276. mblock_info->reserved[mblock_info->reserved_num].start = reserved_addr;
  277. mblock_info->reserved[mblock_info->reserved_num].size = reserved_size;
  278. mblock_info->reserved[mblock_info->reserved_num].mapping = mapping;
  279. strncpy((char*)&mblock_info->reserved[mblock_info->reserved_num].name, name,
  280. (strlen(name) >= MBLOCK_RESERVED_NAME_SIZE)? MBLOCK_RESERVED_NAME_SIZE - 1: strlen(name));
  281. if (strlen(name) < MBLOCK_RESERVED_NAME_SIZE)
  282. mblock_info->reserved[mblock_info->reserved_num].name[strlen(name)] = '\0';
  283. else
  284. mblock_info->reserved[mblock_info->reserved_num].name[MBLOCK_RESERVED_NAME_SIZE - 1] = '\0';
  285. mblock_info->reserved_num++;
  286. /* split mblock if necessary */
  287. if (reserved_addr == start) {
  288. /*
  289. * only needs to fixup target mblock
  290. * [reserved_addr, reserved_size](reserved) +
  291. * [reserved_addr + reserved_size, sz - reserved_size]
  292. */
  293. mblock_info->mblock[target].start = reserved_addr + reserved_size;
  294. mblock_info->mblock[target].size -= reserved_size;
  295. } else if ((reserved_addr + reserved_size) == (start + sz)) {
  296. /*
  297. * only needs to fixup target mblock
  298. * [start, reserved_addr - start] +
  299. * [reserved_addr, reserved_size](reserved)
  300. */
  301. mblock_info->mblock[target].size = reserved_addr - start;
  302. } else {
  303. /*
  304. * fixup target mblock and create a new mblock
  305. * [start, reserved_addr - start] +
  306. * [reserved_addr, reserved_size](reserved) +
  307. * [reserved_addr + reserved_size, start + sz - reserved_addr - reserved_size]
  308. */
  309. /* fixup original mblock */
  310. mblock_info->mblock[target].size = reserved_addr - start;
  311. /* new mblock */
  312. mblock.rank = mblock_info->mblock[target].rank;
  313. mblock.start = reserved_addr + reserved_size;
  314. mblock.size = start + sz - (reserved_addr + reserved_size);
  315. /* insert the new node, keep the list sorted */
  316. memmove(&mblock_info->mblock[target + 2],
  317. &mblock_info->mblock[target + 1],
  318. sizeof(mblock_t) *
  319. (mblock_info->mblock_num - target - 1));
  320. mblock_info->mblock[target + 1] = mblock;
  321. mblock_info->mblock_num += 1;
  322. #if mblock_debug
  323. dprintf(CRITICAL, "mblock[%d]: %llx, %llx from mblock\n"
  324. "mblock[%d]: %llx, %llx from mblock\n",
  325. target,
  326. mblock_info->mblock[target].start,
  327. mblock_info->mblock[target].size,
  328. target + 1,
  329. mblock_info->mblock[target + 1].start,
  330. mblock_info->mblock[target + 1].size);
  331. #endif
  332. }
  333. dprintf(CRITICAL, "mblock_reserve-R start: 0x%llx, sz: 0x%llx map:%d name:%s\n",
  334. reserved_addr, reserved_size, mapping, name);
  335. #ifdef MTK_3LEVEL_PAGETABLE
  336. {
  337. u64 m_start = (u64)reserved_addr;
  338. u32 m_size = (u32)reserved_size;
  339. if ((m_start + m_size) <= 0x100000000ULL) {
  340. arch_mmu_map((uint64_t)m_start, (uint32_t)m_start,
  341. MMU_MEMORY_TYPE_NORMAL_WRITE_BACK | MMU_MEMORY_AP_P_RW_U_NA, ROUNDUP(m_size, PAGE_SIZE));
  342. }
  343. }
  344. #endif
  345. /* print debug info */
  346. #if mblock_debug
  347. for (i = 0; i < mblock_info->mblock_num; i++) {
  348. start = mblock_info->mblock[i].start;
  349. sz = mblock_info->mblock[i].size;
  350. dprintf(CRITICAL, "mblock_reserve [%d].start: 0x%llx, sz: 0x%llx\n",
  351. i, start, sz);
  352. }
  353. for (i = 0; i < mblock_info->reserved_num; i++) {
  354. start = mblock_info->reserved[i].start;
  355. sz = mblock_info->reserved[i].size;
  356. dprintf(CRITICAL, "mblock_reserve-R[%d].start: 0x%llx, sz: 0x%llx map:%d name:%s\n",
  357. i, start, sz, mblock_info->reserved[i].mapping, mblock_info->reserved[i].name);
  358. }
  359. #endif
  360. return reserved_addr;
  361. }
  362. /*
  363. * mblock_resize - resize mblock started at addr from oldsize to newsize,
  364. * current implementation only consider oldsize >= newsize.
  365. *
  366. * @mblock_info: mblock information
  367. * @orig_dram_info: original dram information
  368. * @addr: start address of a mblock
  369. * @oldsize: origianl size of the mblock
  370. * @newsize: new size of the given block
  371. * return 0 on success, otherwise 1
  372. */
  373. int mblock_resize(mblock_info_t *mblock_info, dram_info_t *orig_dram_info,
  374. u64 addr, u64 oldsize, u64 newsize)
  375. {
  376. int err = 1;
  377. unsigned int i, map;
  378. u64 start, sz;
  379. mblock_t mblock;
  380. unsigned int found, target = 0;
  381. mblock_version_check();
  382. /* check size, oldsize must larger than newsize */
  383. if (oldsize <= newsize) {
  384. dprintf(CRITICAL, "mblock_resize error: mblock %llx oldsize(%llx) <= newsize(%llx)",
  385. addr, oldsize, newsize);
  386. goto error;
  387. }
  388. /* check alignment, at least 4k aligned */
  389. if ((oldsize & (0x1000 - 1)) || (newsize & (0x1000 - 1))) {
  390. dprintf(CRITICAL, "mblock_resize alignment error: oldsize(%llx) or newsize(%llx)\n",
  391. oldsize, newsize);
  392. goto error;
  393. }
  394. /* check mblock for overlap
  395. * resized memory must not exist in mblock[i]
  396. * it msut be in reserved[i]*/
  397. for (i = 0; i < mblock_info->mblock_num; i++) {
  398. start = mblock_info->mblock[i].start;
  399. sz = mblock_info->mblock[i].size;
  400. /* invalid mblock */
  401. if (sz && (((start >= addr) && (start < (addr + oldsize)))
  402. || ((start < addr) && (start + sz > addr)))) {
  403. dprintf(CRITICAL, "mblock_resize error:");
  404. dprintf(CRITICAL,
  405. "addr %llx, oldsize: %llx start: 0x%llx sz: 0x%llx is free\n",
  406. addr, oldsize, start, sz);
  407. dprintf(CRITICAL,
  408. "mblock_resize failed while(1) force hang\n");
  409. assert(0);
  410. }
  411. }
  412. /* check reserved */
  413. /* this record must exist exactly */
  414. found = 0;
  415. for (i = 0; i < mblock_info->reserved_num; i++) {
  416. if (addr == mblock_info->reserved[i].start && oldsize == mblock_info->reserved[i].size) {
  417. dprintf(SPEW, "mblock_resize start: %llx, size: %llx addr = %llx oldsize = %llx\n",
  418. mblock_info->reserved[i].start, mblock_info->reserved[i].size, addr, oldsize);
  419. found = 1;
  420. target = i;
  421. }
  422. }
  423. if (!found) {
  424. dprintf(CRITICAL, "mblock_resize error: mblock %llx, size: %llx is not exist\n",
  425. addr, oldsize);
  426. goto error;
  427. }
  428. /*
  429. * ok, the mblock is valid and oldsize > newsize, let's
  430. * shrink this mblock
  431. */
  432. /* setup a new mblock */
  433. mblock.start = addr + newsize;
  434. mblock.size = oldsize - newsize;
  435. dprintf(CRITICAL, "mblock_resize putback mblock %llx size: %llx\n",
  436. mblock.start, mblock.size);
  437. /* setup rank */
  438. for (i = 0; i < orig_dram_info->rank_num; i++) {
  439. start = orig_dram_info->rank_info[i].start;
  440. sz = orig_dram_info->rank_info[i].size;
  441. if ((mblock.start >= start) && ((mblock.start + mblock.size) <= (start + sz))) {
  442. mblock.rank = i;
  443. break;
  444. }
  445. }
  446. if (i >= orig_dram_info->rank_num) {
  447. dprintf(CRITICAL, "mblock_resize error: mblock not in orig_dram_info: %llx, size(%llx)\n",
  448. mblock.start, mblock.size);
  449. goto error;
  450. }
  451. /* here , we decide to shrink or delete this reserved record*/
  452. if (newsize == 0) {
  453. /* destroy current record first */
  454. memset(&mblock_info->reserved[target], 0, sizeof(reserved_t));
  455. /* more than one record exist , we need to shift record */
  456. /* we no need to shif record once it's the last one */
  457. if (mblock_info->reserved_num > 1 && target != mblock_info->reserved_num - 1) {
  458. memmove(&mblock_info->reserved[target], &mblock_info->reserved[target + 1]\
  459. , sizeof(reserved_t) * ((mblock_info->reserved_num - 1) - target));
  460. }
  461. mblock_info->reserved_num--;
  462. }
  463. /* shirnk size directly */
  464. else {
  465. mblock_info->reserved[target].size = newsize;
  466. }
  467. /* put the mblock back to mblock_info */
  468. for (i = 0; i < mblock_info->mblock_num; i++) {
  469. start = mblock_info->mblock[i].start;
  470. sz = mblock_info->mblock[i].size;
  471. if (mblock.rank == mblock_info->mblock[i].rank) {
  472. if (mblock.start == start + sz) {
  473. /*
  474. * the new mblock can be merged to this mblock
  475. * [start, start + sz] +
  476. * [mblock.start, mblock.start + mblock.size](new)
  477. */
  478. mblock_info->mblock[i].size += mblock.size;
  479. /* destroy block */
  480. mblock.size = 0;
  481. } else if (start == mblock.start + mblock.size) {
  482. /*
  483. * the new mblock can be merged to this mblock
  484. * [mblock.start, mblock.start + * mblock.size](new) +
  485. * [start, start + sz]
  486. */
  487. mblock_info->mblock[i].start = mblock.start;
  488. mblock_info->mblock[i].size += mblock.size;
  489. /* destroy block */
  490. mblock.size = 0;
  491. }
  492. }
  493. }
  494. /*
  495. * mblock cannot be merge info mblock_info, insert it into mblock_info
  496. */
  497. if (mblock.size) {
  498. for (i = 0; i < mblock_info->mblock_num; i++) {
  499. if (mblock.start < mblock_info->mblock[i].start)
  500. break;
  501. }
  502. memmove(&mblock_info->mblock[i + 1],
  503. &mblock_info->mblock[i],
  504. sizeof(mblock_t) *
  505. (mblock_info->mblock_num - i));
  506. mblock_info->mblock[i] = mblock;
  507. mblock_info->mblock_num += 1;
  508. }
  509. /* print debug info */
  510. for (i = 0; i < mblock_info->mblock_num; i++) {
  511. start = mblock_info->mblock[i].start;
  512. sz = mblock_info->mblock[i].size;
  513. dprintf(INFO, "mblock_resize-debug[%d].start: 0x%llx, sz: 0x%llx\n",
  514. i, start, sz);
  515. }
  516. /* print debug info */
  517. for (i = 0; i < mblock_info->reserved_num; i++) {
  518. start = mblock_info->reserved[i].start;
  519. sz = mblock_info->reserved[i].size;
  520. map = mblock_info->reserved[i].mapping;
  521. dprintf(INFO, "mblock_resize-debug-R[%d].start: 0x%llx, sz: 0x%llx map: %d name: %s\n",
  522. i, start, sz, map, mblock_info->reserved[i].name);
  523. }
  524. return 0;
  525. error:
  526. return err;
  527. }
  528. /*
  529. * mblock_create - create mblock started at addr or merge with existing mblock
  530. *
  531. * @mblock_info: mblock information
  532. * @orig_dram_info: original dram information
  533. * @addr: start address of a mblock, must be 4k align
  534. * @size: size of the given block, must be 4K align
  535. * return 0 on success, otherwise 1
  536. */
  537. int mblock_create(mblock_info_t *mblock_info, dram_info_t *orig_dram_info
  538. , u64 addr, u64 size)
  539. {
  540. int err = -1;
  541. unsigned int i, valid, target;
  542. u64 start, sz;
  543. mblock_t mblock;
  544. reserved_t reserved;
  545. mblock_t *mblock_candidate_left = NULL, *mblock_candidate_right = NULL;
  546. mblock_version_check();
  547. /* check size, addr valid and align with 4K*/
  548. if (!size || size&(0x1000 - 1) || addr&(0x1000 - 1)) {
  549. dprintf(CRITICAL, "mblock_create size invalid size=%llx\n", size);
  550. goto error;
  551. }
  552. /* for lca check*/
  553. if (g_boot_arg->lca_reserved_mem.start && g_boot_arg->lca_reserved_mem.size) {
  554. if ((addr >= g_boot_arg->lca_reserved_mem.start && addr < g_boot_arg->lca_reserved_mem.start \
  555. + g_boot_arg->lca_reserved_mem.size) || \
  556. (addr + size > g_boot_arg->lca_reserved_mem.start \
  557. && (addr + size) < g_boot_arg->lca_reserved_mem.start + g_boot_arg->lca_reserved_mem.size)) {
  558. dprintf(CRITICAL, "mblock_create ERROR , overlap with LCA addr and size invalid addr = %llx size=%llx\n", addr, size);
  559. goto error;
  560. }
  561. }
  562. /* for tee check*/
  563. if (g_boot_arg->tee_reserved_mem.start && g_boot_arg->tee_reserved_mem.size) {
  564. if ((addr >= g_boot_arg->tee_reserved_mem.start && addr < g_boot_arg->tee_reserved_mem.start \
  565. + g_boot_arg->tee_reserved_mem.size) || \
  566. (addr + size > g_boot_arg->tee_reserved_mem.start \
  567. && (addr + size) < g_boot_arg->tee_reserved_mem.start + g_boot_arg->tee_reserved_mem.size)) {
  568. dprintf(CRITICAL, "mblock_create ERROR , overlap with tee addr and size invalid addr = %llx size=%llx\n", addr, size);
  569. goto error;
  570. }
  571. }
  572. /*it's not allow to create mblock which is cross rank
  573. * and mblock should not exceed rank size */
  574. for (i = 0, valid = 0; i < orig_dram_info->rank_num; i++) {
  575. start = orig_dram_info->rank_info[i].start;
  576. sz = orig_dram_info->rank_info[i].size;
  577. if (addr >= start && addr < start + sz && addr + size <= start + sz) {
  578. valid = 1;
  579. break;
  580. }
  581. }
  582. if (!valid) {
  583. dprintf(CRITICAL, "mblock_create addr \
  584. and size invalid addr=%llx size=%llx\n", addr, size);
  585. goto error;
  586. }
  587. /* check every mblock the addr and size should not be within any existing mblock */
  588. for (i = 0; i < mblock_info->mblock_num; i++) {
  589. start = mblock_info->mblock[i].start;
  590. sz = mblock_info->mblock[i].size;
  591. /*addr should start from reserved memory space and addr + size should not overlap with mblock
  592. * when addr is smaller than start*/
  593. if (((addr >= start) && (addr < start + sz)) || (addr < start && addr + size > start)) {
  594. dprintf(CRITICAL, "mblock_create error: addr %llx overlap with mblock %llx, size: %llx\n",
  595. addr, start, sz);
  596. goto error;
  597. }
  598. }
  599. /* check if reserved record contain this one , it must exist */
  600. for (i = 0, valid = 0; i < mblock_info->reserved_num; i++) {
  601. start = mblock_info->reserved[i].start;
  602. sz = mblock_info->reserved[i].size;
  603. /* dprintf(CRITICAL, "mblock_create start=0x%llx sz=0x%llx addr=0x%lx size=0x%llx\n",
  604. start, sz, addr, size);
  605. */
  606. if (addr >= start && ((addr + size) <= (start + sz))) {
  607. valid = 1;
  608. target = i;
  609. break;
  610. }
  611. }
  612. if (!valid) {
  613. dprintf(CRITICAL, "mblock_create error: not exist in reserved record\n addr=0x%llx size=0x%llx\n",
  614. addr, size);
  615. mblock_show_info();
  616. goto error;
  617. }
  618. /* dealling with 4 case */
  619. /* 1. create whole reserved record means destroy it and shit rest record*/
  620. /* 2. create from the left most side to the middle of record*/
  621. /* 3. create from the right most side to the middle of record*/
  622. /* 4. create from the middle of record, and then divide it*/
  623. start = mblock_info->reserved[target].start;
  624. sz = mblock_info->reserved[target].size;
  625. if (addr == start && size == sz) {
  626. /* destroy current record first */
  627. memset(&mblock_info->reserved[i], 0, sizeof(reserved_t));
  628. /* more than one record exist , we need to shift record */
  629. /* we no need to shift record once it's the last one */
  630. if (mblock_info->reserved_num > 1 && target != mblock_info->reserved_num - 1) {
  631. memmove(&mblock_info->reserved[target], &mblock_info->reserved[target + 1]\
  632. , sizeof(reserved_t) * ((mblock_info->reserved_num - 1) - target));
  633. /* after memmove, we must clean the last one */
  634. memset(&mblock_info->reserved[mblock_info->reserved_num - 1], 0, sizeof(reserved_t));
  635. }
  636. mblock_info->reserved_num--;
  637. } else if (addr == start || (addr + size == start + sz)) {
  638. /*Now we deal with lef and right most case*/
  639. /* we just shrink the record */
  640. if (addr == start) {
  641. mblock_info->reserved[target].start = start + size;
  642. mblock_info->reserved[target].size = sz - size;
  643. } else {/* (addr + size == start + sz)*/
  644. mblock_info->reserved[target].size = sz - size;
  645. }
  646. } else {/* this is middle case we need to divide it*/
  647. /* shrink original one and create new one after */
  648. if (mblock_info->reserved_num >= MBLOCK_RESERVED_NUM_MAX) {
  649. dprintf(CRITICAL, "mblock_create error: can not split , reserved_num reach the max\n");
  650. goto error;
  651. }
  652. reserved.start = addr + size;
  653. reserved.size = (start + sz) - (addr + size);
  654. /* clone from original one*/
  655. reserved.mapping = mblock_info->reserved[target].mapping;
  656. memcpy(&reserved.name, &mblock_info->reserved[target].name, MBLOCK_RESERVED_NAME_SIZE);
  657. /* check if this target is last one or not */
  658. /* target start from 0 , reserved_num start from 1 */
  659. if (target != mblock_info->reserved_num - 1) {
  660. for (i = 0; i < (mblock_info->reserved_num - target - 1); i++) {
  661. mblock_info->reserved[mblock_info->reserved_num - i] = \
  662. mblock_info->reserved[mblock_info->reserved_num - i - 1];
  663. }
  664. mblock_info->reserved[target+1] = reserved;
  665. } else {/*target is the last one */
  666. mblock_info->reserved[mblock_info->reserved_num] = reserved;
  667. }
  668. /* shrink original target size at last step */
  669. mblock_info->reserved[target].size = addr - start;
  670. mblock_info->reserved_num++;
  671. }
  672. /*
  673. * ok, the mblock is valid let's create the mblock
  674. * and try to merge it with the same bank and choose the bigger size one
  675. */
  676. /* setup a new mblock */
  677. mblock.start = addr;
  678. mblock.size = size;
  679. dprintf(CRITICAL, "mblock_create mblock start: 0x%llx size: 0x%llx\n",
  680. mblock.start, mblock.size);
  681. /* setup rank */
  682. for (i = 0; i < orig_dram_info->rank_num; i++) {
  683. start = orig_dram_info->rank_info[i].start;
  684. sz = orig_dram_info->rank_info[i].size;
  685. if ((mblock.start >= start) && ((mblock.start + mblock.size) <= (start + sz))) {
  686. mblock.rank = i;
  687. break;
  688. }
  689. }
  690. if (i >= orig_dram_info->rank_num) {
  691. dprintf(CRITICAL, "mblock_create error: mblock not in orig_dram_info: %llx, size(%llx)\n",
  692. mblock.start, mblock.size);
  693. goto error;
  694. }
  695. /* put the mblock back to mblock_info */
  696. for (i = 0; i < mblock_info->mblock_num; i++) {
  697. start = mblock_info->mblock[i].start;
  698. sz = mblock_info->mblock[i].size;
  699. if (mblock.rank == mblock_info->mblock[i].rank) {
  700. if (mblock.start + mblock.size == start) {
  701. /*
  702. * the new mblock could be merged to this mblock
  703. */
  704. mblock_candidate_right = &mblock_info->mblock[i];
  705. } else if (start + sz == mblock.start) {
  706. /*
  707. * the new mblock can be merged to this mblock
  708. */
  709. mblock_candidate_left = &mblock_info->mblock[i];
  710. }
  711. }
  712. }
  713. /*we can merge either left or right , choose the bigger one */
  714. if (mblock_candidate_right && mblock_candidate_left) {
  715. if (mblock_candidate_right->size >= mblock_candidate_left->size) {
  716. #if mblock_debug
  717. dprintf(CRITICAL, "mblock_candidate_right->size = %llx \
  718. mblock_candidate_left->size = %llx \n", mblock_candidate_right->size, mblock_candidate_left->size);
  719. #endif
  720. mblock_candidate_right->start = mblock.start;
  721. mblock_candidate_right->size += mblock.size;
  722. } else { /*left bigger*/
  723. #if mblock_debug
  724. dprintf(CRITICAL, "mblock_candidate_right->size = %llx \
  725. mblock_candidate_left->size = %llx \n", mblock_candidate_right->size, mblock_candidate_left->size);
  726. #endif
  727. mblock_candidate_left->size += mblock.size;
  728. }
  729. /* destroy block */
  730. mblock.size = 0;
  731. } else {
  732. if (mblock_candidate_right) {
  733. mblock_candidate_right->start = mblock.start;
  734. mblock_candidate_right->size += mblock.size;
  735. /* destroy block */
  736. mblock.size = 0;
  737. }
  738. if (mblock_candidate_left) {
  739. mblock_candidate_left->size += mblock.size;
  740. /* destroy block */
  741. mblock.size = 0;
  742. }
  743. }
  744. /*
  745. * mblock cannot be merge into mblock_info, insert it into mblock_info
  746. */
  747. if (mblock.size) {
  748. for (i = 0; i < mblock_info->mblock_num; i++) {
  749. if (mblock.start < mblock_info->mblock[i].start)
  750. break;
  751. }
  752. /* insert the new node, keep the list sorted */
  753. if (i != mblock_info->mblock_num) {
  754. memmove(&mblock_info->mblock[i + 1],
  755. &mblock_info->mblock[i],
  756. sizeof(mblock_t) *
  757. (mblock_info->mblock_num - i));
  758. }
  759. mblock_info->mblock[i] = mblock;
  760. mblock_info->mblock_num += 1;
  761. dprintf(INFO, "create mblock[%d]: start: 0x%llx, size: 0x%llx\n",
  762. i,
  763. mblock_info->mblock[i].start,
  764. mblock_info->mblock[i].size);
  765. }
  766. /* print debug info */
  767. #if mblock_debug
  768. unsigned int map;
  769. for (i = 0; i < mblock_info->mblock_num; i++) {
  770. start = mblock_info->mblock[i].start;
  771. sz = mblock_info->mblock[i].size;
  772. dprintf(INFO, "mblock-create-debug[%d].start: 0x%llx, sz: 0x%llx\n",
  773. i, start, sz);
  774. }
  775. /* print debug info */
  776. for (i = 0; i < mblock_info->reserved_num; i++) {
  777. start = mblock_info->reserved[i].start;
  778. sz = mblock_info->reserved[i].size;
  779. map = mblock_info->reserved[i].mapping;
  780. dprintf(INFO, "mblock-create-debug-R[%d].start: 0x%llx, sz: 0x%llx map: %d name: %s\n",
  781. i, start, sz, map, mblock_info->reserved[i].name);
  782. }
  783. #endif
  784. return 0;
  785. error:
  786. mblock_show_info();
  787. return err;
  788. }
  789. static u64 mlp_reserved_end = ULLONG_MAX;
  790. void memory_lowpwer_prev_fixup(u64 start)
  791. {
  792. dprintf(CRITICAL, "%s: %d\n", __func__, __LINE__);
  793. if (mlp_reserved_end <= start)
  794. return;
  795. dprintf(CRITICAL, "%s: %d: %llu\n", __func__, __LINE__, start);
  796. mlp_reserved_end = start;
  797. }
  798. int memory_ssmr_fixup(void *fdt)
  799. {
  800. int offset, nodeoffset, len, ret, i, j;
  801. int prop_offset;
  802. const char *name;
  803. const void *val;
  804. u32 node_size[2];
  805. u64 size = 0;
  806. offset = fdt_path_offset(fdt, "/memory-ssmr-features");
  807. if (offset < 0) {
  808. dprintf(CRITICAL,"can't find memory-ssmr-features\n");
  809. goto exit;
  810. }
  811. for (prop_offset = fdt_first_property_offset(fdt, offset);
  812. prop_offset >= 0; prop_offset = fdt_next_property_offset(fdt, prop_offset)) {
  813. val = fdt_getprop_by_offset(fdt, prop_offset, &name, &len);
  814. if (val) {
  815. u32 *out;
  816. for (i = 0; i < __MAX_NR_SSMR_FEATURES; i++) {
  817. if ((!strncmp(name, _ssmr_feats[i].dt_prop_name, strlen(_ssmr_feats[i].dt_prop_name)))) {
  818. for (j = 0; j < __MAX_NR_SCHEME; j++) {
  819. if ((_ssmr_feats[i].scheme_flag &_ssmrscheme[j].flags)) {
  820. out = (u32 *)fdt_getprop(fdt, offset, name, &len);
  821. if (out != NULL) {
  822. _ssmrscheme[j].usable_size += ((u64)fdt32_to_cpu(*out) << 32) + fdt32_to_cpu(*(out + 1));
  823. }
  824. }
  825. }
  826. break;
  827. }
  828. }
  829. }
  830. }
  831. for (i = 0; i < __MAX_NR_SCHEME; i++) {
  832. dprintf(CRITICAL,"%s, scenario: %s, scenario_size 0x%llx\n", __func__, _ssmrscheme[i].name, _ssmrscheme[i].usable_size);
  833. if (size < _ssmrscheme[i].usable_size)
  834. size = _ssmrscheme[i].usable_size;
  835. }
  836. offset = fdt_path_offset(fdt, "/reserved-memory");
  837. if (offset < 0) {
  838. dprintf(CRITICAL,"%s, get reserved-memory failed\n", __func__);
  839. goto exit;
  840. }
  841. nodeoffset = fdt_subnode_offset(fdt, offset, "ssmr-reserved-cma_memory");
  842. if (nodeoffset < 0) {
  843. dprintf(CRITICAL,"%s, get ssmr-reserved-cma_memory failed\n", __func__);
  844. goto exit;
  845. }
  846. node_size[0] = (u32)cpu_to_fdt32(size >> 32);
  847. node_size[1] = (u32)cpu_to_fdt32(size);
  848. ret = fdt_setprop(fdt, nodeoffset, "size", node_size,
  849. sizeof(u32) * 2);
  850. if (ret) {
  851. dprintf(CRITICAL,"%s, set ssmr-reserved-cma_memory size failed\n", __func__);
  852. goto exit;
  853. }
  854. exit:
  855. return 0;
  856. }
  857. /*
  858. * memory_lowpower_fixup
  859. *
  860. * To support various DRAM size with single logic, we fixup
  861. * the reserved memory used by memory-lowpower feature according
  862. * chip DRAM size.
  863. * It's fine to put the function in common part since it searches
  864. * for specified node and only fixup the node.
  865. *
  866. * input:
  867. * @fdt: pointer to fdt
  868. *
  869. * output:
  870. * return 0 on success, otherwise 1
  871. */
  872. int memory_lowpwer_fixup(void *fdt)
  873. {
  874. int offset, nodeoffset, new_nodeoffset, len, errline, ret;
  875. unsigned int i;
  876. char node_name[128];
  877. char compatible_str[MBLOCK_RESERVED_NAME_SIZE + 64], *compatible;
  878. int prop_offset;
  879. const char *name;
  880. const void *val;
  881. u32 clone_size[2], clone_align[2];
  882. dt_dram_info alloc_range, reg_info;
  883. mblock_info_t *mblock_info = &g_boot_arg->mblock_info;
  884. u32 *psize, *prange, *palign, node_size[2];
  885. u64 size, start, alignment, newstart, end = 0;
  886. offset = fdt_path_offset(fdt, "/reserved-memory");
  887. if (!offset) {
  888. errline = __LINE__;
  889. goto error;
  890. }
  891. /* Create final zmc dts node */
  892. new_nodeoffset = fdt_subnode_offset(fdt, offset,
  893. "zone-movable-cma-memory");
  894. if (new_nodeoffset < 0) {
  895. snprintf(node_name, sizeof(node_name), "zone-movable-cma-memory");
  896. new_nodeoffset = fdt_add_subnode(fdt, offset, node_name);
  897. if (new_nodeoffset < 0) {
  898. dprintf(CRITICAL,"add zone-movable-cma-memory dts node fail\n");
  899. goto exit;
  900. }
  901. }
  902. else {
  903. dprintf(CRITICAL,"zone-movable-cma-memory dts node already exist\n");
  904. goto exit;
  905. }
  906. nodeoffset = fdt_subnode_offset(fdt, offset,
  907. "memory-lowpower-reserved-memory");
  908. if (nodeoffset < 0) {
  909. nodeoffset = fdt_subnode_offset(fdt, offset,
  910. "zmc-default");
  911. if (nodeoffset < 0)
  912. goto exit;
  913. }
  914. /* Clone zmc-default property to final zmc node */
  915. for (prop_offset = fdt_first_property_offset(fdt, nodeoffset);
  916. prop_offset >= 0; prop_offset = fdt_next_property_offset(fdt, prop_offset)) {
  917. val = fdt_getprop_by_offset(fdt, prop_offset, &name, &len);
  918. if (val) {
  919. int update_offset = 0;
  920. u64 out_prop, out_prop_lower;
  921. u32 *out;
  922. if (strncmp(name, "compatible", 10)==0) {
  923. compatible = (char *)fdt_getprop(fdt, nodeoffset, name, &len);
  924. snprintf(compatible_str, sizeof(compatible_str), compatible);
  925. ret = fdt_setprop_string(fdt, new_nodeoffset, "compatible", compatible_str);
  926. if (ret) {
  927. errline = __LINE__;
  928. goto error;
  929. }
  930. }
  931. else if (strncmp(name, "size", 4)==0) {
  932. out = (u32 *)fdt_getprop(fdt, nodeoffset, name, &len);
  933. if (out != NULL) {
  934. out_prop = ((u64)fdt32_to_cpu(*out) << 32) + fdt32_to_cpu(*(out + 1));
  935. clone_size[0] = (u32)cpu_to_fdt32(out_prop >> 32);
  936. clone_size[1] = (u32)cpu_to_fdt32(out_prop);
  937. ret = fdt_setprop(fdt, new_nodeoffset, name, clone_size, sizeof(u32)*2);
  938. if (ret) {
  939. errline = __LINE__;
  940. goto error;
  941. }
  942. }
  943. }
  944. else if (strncmp(name, "alignment", 9)==0) {
  945. out = (u32 *)fdt_getprop(fdt, nodeoffset, name, &len);
  946. if (out != NULL) {
  947. out_prop = ((u64)fdt32_to_cpu(*out) << 32) + fdt32_to_cpu(*(out + 1));
  948. clone_align[0] = (u32)cpu_to_fdt32(out_prop >> 32);
  949. clone_align[1] = (u32)cpu_to_fdt32(out_prop);
  950. ret = fdt_setprop(fdt, new_nodeoffset, name, clone_align, sizeof(u32)*2);
  951. if (ret) {
  952. errline = __LINE__;
  953. goto error;
  954. }
  955. }
  956. }
  957. else if (strncmp(name, "alloc-ranges", 12)==0) {
  958. out = (u32 *)fdt_getprop(fdt, nodeoffset, name, &len);
  959. if (out != NULL) {
  960. out_prop = ((u64)fdt32_to_cpu(*out) << 32) + fdt32_to_cpu(*(out + 1));
  961. out_prop_lower = ((u64)fdt32_to_cpu(*(out + 2)) << 32) + fdt32_to_cpu(*(out + 3));
  962. alloc_range.start_hi = cpu_to_fdt32(out_prop >> 32);
  963. alloc_range.start_lo = cpu_to_fdt32(out_prop);
  964. alloc_range.size_hi = cpu_to_fdt32((out_prop_lower) >> 32);
  965. alloc_range.size_lo = cpu_to_fdt32(out_prop_lower);
  966. ret = fdt_setprop(fdt, new_nodeoffset, name, &alloc_range, sizeof(dt_dram_info));
  967. if (ret) {
  968. errline = __LINE__;
  969. goto error;
  970. }
  971. }
  972. }
  973. else if (strncmp(name, "reg", 3)==0) {
  974. out = (u32 *)fdt_getprop(fdt, nodeoffset, name, &len);
  975. if (out != NULL) {
  976. out_prop = ((u64)fdt32_to_cpu(*out) << 32) + fdt32_to_cpu(*(out + 1));
  977. out_prop_lower = ((u64)fdt32_to_cpu(*(out + 2)) << 32) + fdt32_to_cpu(*(out + 3));
  978. reg_info.start_hi = cpu_to_fdt32(out_prop >> 32);
  979. reg_info.start_lo = cpu_to_fdt32(out_prop);
  980. reg_info.size_hi = cpu_to_fdt32((out_prop_lower) >> 32);
  981. reg_info.size_lo = cpu_to_fdt32(out_prop_lower);
  982. ret = fdt_setprop(fdt, new_nodeoffset, name, &reg_info, sizeof(dt_dram_info));
  983. if (ret) {
  984. errline = __LINE__;
  985. goto error;
  986. }
  987. }
  988. }
  989. else if (strncmp(name, "no-map", 6)==0) {
  990. ret = fdt_setprop(fdt, new_nodeoffset, "no-map", NULL, 0);
  991. if (ret) {
  992. errline = __LINE__;
  993. goto error;
  994. }
  995. }
  996. else if (strncmp(name, "reusable", 8)==0) {
  997. ret = fdt_setprop(fdt, new_nodeoffset, "reusable", NULL, 0);
  998. if (ret) {
  999. errline = __LINE__;
  1000. goto error;
  1001. }
  1002. }
  1003. else
  1004. continue;
  1005. /* Update offset of dts node */
  1006. update_offset = fdt_subnode_offset(fdt, offset, "zmc-default");
  1007. new_nodeoffset = fdt_subnode_offset(fdt, offset, "zone-movable-cma-memory");
  1008. prop_offset = prop_offset + (update_offset - nodeoffset);
  1009. nodeoffset = update_offset;
  1010. }
  1011. }
  1012. /* set status:disable to zmc-default */
  1013. nodeoffset = fdt_subnode_offset(fdt, offset, "zmc-default");
  1014. ret = fdt_setprop_string(fdt, nodeoffset, "status", "disabled");
  1015. if (ret) {
  1016. errline = __LINE__;
  1017. goto error;
  1018. }
  1019. /* direct to zmc final dts node */
  1020. nodeoffset = fdt_subnode_offset(fdt, offset, "zone-movable-cma-memory");
  1021. /* get size */
  1022. psize = (u32 *)fdt_getprop(fdt, nodeoffset, "size", &len);
  1023. if (!psize) {
  1024. errline = __LINE__;
  1025. goto error;
  1026. }
  1027. size = ((u64)fdt32_to_cpu(*psize) << 32) + fdt32_to_cpu(*(psize + 1));
  1028. /* get alignment */
  1029. palign = (u32 *)fdt_getprop(fdt, nodeoffset, "alignment", &len);
  1030. if (palign) {
  1031. alignment = ((u64)fdt32_to_cpu(*palign) << 32) + fdt32_to_cpu(*(palign + 1));
  1032. } else {
  1033. /* fallback to default alignment */
  1034. alignment = 256 * 1024 * 1024;
  1035. }
  1036. /* get alloc_rage */
  1037. prange = (u32 *)fdt_getprop(fdt, nodeoffset, "alloc-ranges", &len);
  1038. if (!prange) {
  1039. errline = __LINE__;
  1040. goto error;
  1041. }
  1042. start = ((u64)fdt32_to_cpu(*prange) << 32) + fdt32_to_cpu(*(prange + 1));
  1043. /* search for max available DRAM address */
  1044. for (i = 0; i < mblock_info->mblock_num; i++) {
  1045. if ((mblock_info->mblock[i].start +
  1046. mblock_info->mblock[i].size) > end)
  1047. end = mblock_info->mblock[i].start +
  1048. mblock_info->mblock[i].size;
  1049. }
  1050. /* bypass if start is not in the range of available DRAM */
  1051. if (end <= start)
  1052. goto exit;
  1053. /* other reservations */
  1054. if (mlp_reserved_end < end) {
  1055. dt_dram_info mlp_reg_property;
  1056. end = mlp_reserved_end;
  1057. mlp_reg_property.start_hi = cpu_to_fdt32(start >> 32);
  1058. mlp_reg_property.start_lo = cpu_to_fdt32(start);
  1059. mlp_reg_property.size_hi = cpu_to_fdt32((end - start) >> 32);
  1060. mlp_reg_property.size_lo = cpu_to_fdt32(end - start);
  1061. ret |= fdt_setprop(fdt, nodeoffset, "alloc-ranges",
  1062. &mlp_reg_property, sizeof(dt_dram_info));
  1063. if (ret) {
  1064. errline = __LINE__;
  1065. goto error;
  1066. }
  1067. }
  1068. /* fix size according to DRAM size */
  1069. if (size > (end - start)) {
  1070. newstart = start + size - (end - start);
  1071. newstart = ((newstart + alignment - 1) / alignment) * alignment;
  1072. dprintf(CRITICAL, "%s: newstart: %llx, size: 0x%llx => 0x%llx)\n",
  1073. __func__, newstart, size, (start + size - newstart));
  1074. if (newstart >= start + size) {
  1075. errline = __LINE__;
  1076. goto error;
  1077. }
  1078. size = start + size - newstart;
  1079. node_size[0] = (u32)cpu_to_fdt32(size >> 32);
  1080. node_size[1] = (u32)cpu_to_fdt32(size);
  1081. ret = fdt_setprop(fdt, nodeoffset, "size", node_size,
  1082. sizeof(u32) * 2);
  1083. if (ret) {
  1084. errline = __LINE__;
  1085. goto error;
  1086. }
  1087. }
  1088. exit:
  1089. return 0;
  1090. error:
  1091. dprintf(CRITICAL, "%s: errline: %d\n", __func__, errline);
  1092. return 1;
  1093. }
  1094. int fdt_memory_append(void *fdt)
  1095. {
  1096. char *ptr;
  1097. int offset;
  1098. int ret = 0;
  1099. offset = fdt_path_offset(fdt, "/memory");
  1100. if (offset < 0) {
  1101. dprintf(CRITICAL, "%s:[%d] get fdt_path_offset of memory failed\n", __func__, __LINE__);
  1102. ret = offset;
  1103. goto exit;
  1104. }
  1105. ptr = (char *)&g_boot_arg->orig_dram_info;
  1106. ret = fdt_setprop(fdt, offset, "orig_dram_info", ptr, sizeof(dram_info_t));
  1107. if (ret) {
  1108. dprintf(CRITICAL, "%s:[%d] fdt_setprop failed, ret=%d\n", __func__, __LINE__, ret);
  1109. goto exit;
  1110. }
  1111. ptr = (char *)&g_boot_arg->mblock_info;
  1112. ret = fdt_setprop(fdt, offset, "mblock_info", ptr, sizeof(mblock_info_t));
  1113. if (ret) {
  1114. dprintf(CRITICAL, "%s:[%d] fdt_setprop failed, ret=%d\n", __func__, __LINE__, ret);
  1115. goto exit;
  1116. }
  1117. ptr = (char *)&g_boot_arg->lca_reserved_mem;
  1118. ret = fdt_setprop(fdt, offset, "lca_reserved_mem", ptr, sizeof(mem_desc_t));
  1119. if (ret) {
  1120. dprintf(CRITICAL, "%s:[%d] fdt_setprop failed, ret=%d\n", __func__, __LINE__, ret);
  1121. goto exit;
  1122. }
  1123. ptr = (char *)&g_boot_arg->tee_reserved_mem;
  1124. ret = fdt_setprop(fdt, offset, "tee_reserved_mem", ptr, sizeof(mem_desc_t));
  1125. if (ret) {
  1126. dprintf(CRITICAL, "%s:[%d] fdt_setprop failed, ret=%d\n", __func__, __LINE__, ret);
  1127. goto exit;
  1128. }
  1129. ret = memory_lowpwer_fixup(fdt);
  1130. if (ret)
  1131. goto exit;
  1132. ret = memory_ssmr_fixup(fdt);
  1133. if (ret)
  1134. goto exit;
  1135. exit:
  1136. if (ret)
  1137. return 1;
  1138. return 0;
  1139. }
  1140. static int reserved_memory_conflict_check(void *fdt, mblock_info_t *mblock_info)
  1141. {
  1142. int reserved_memory_offset, reserved_node, last_node = -1;
  1143. int len, sanity_fail = 0;
  1144. unsigned int i;
  1145. const struct fdt_property *prop;
  1146. dt_dram_info *data;
  1147. u64 start, sz, reserved_start, reserved_sz;
  1148. reserved_memory_offset = fdt_path_offset(fdt, "/reserved-memory");
  1149. if (reserved_memory_offset < 0) {
  1150. dprintf(CRITICAL, "couldn't find /reserved-memory\n");
  1151. return reserved_memory_offset;
  1152. }
  1153. for (reserved_node = fdt_first_subnode(fdt, reserved_memory_offset); reserved_node >= 0;
  1154. reserved_node = fdt_next_subnode(fdt, last_node)) {
  1155. prop = fdt_get_property(fdt, reserved_node, "reg", &len);
  1156. if (!prop) {
  1157. last_node = reserved_node;
  1158. continue;
  1159. }
  1160. data = (dt_dram_info *)prop->data;
  1161. start = (((u64)fdt32_to_cpu(data->start_hi))<<32)|(fdt32_to_cpu(data->start_lo));
  1162. sz = (((u64)fdt32_to_cpu(data->size_hi))<<32)|(fdt32_to_cpu(data->size_lo));
  1163. dprintf(INFO, "DTS node:%s reserved start: 0x%llx size: 0x%llx\n",
  1164. fdt_get_name(fdt, reserved_node, NULL), start, sz);
  1165. for (i = 0; i < mblock_info->reserved_num; i++) {
  1166. reserved_start = mblock_info->reserved[i].start;
  1167. reserved_sz = mblock_info->reserved[i].size;
  1168. if (((start < reserved_start) && \
  1169. ((start + sz) > (reserved_start))) || \
  1170. ((start >= reserved_start) && ((start < (reserved_start + reserved_sz))))) {
  1171. sanity_fail = 1;
  1172. dprintf(CRITICAL, "%s:%d failed i:%d %d:%d:%d:%d\n", __func__, __LINE__, i\
  1173. , (start < reserved_start), ((start + sz) > (reserved_start))\
  1174. , (start >= reserved_start), ((start < (reserved_start + reserved_sz))));
  1175. }
  1176. }
  1177. if (sanity_fail) {
  1178. /* print debug info */
  1179. for (i = 0; i < mblock_info->mblock_num; i++) {
  1180. start = mblock_info->mblock[i].start;
  1181. sz = mblock_info->mblock[i].size;
  1182. dprintf(CRITICAL, "mblock_reserve [%d].start: 0x%llx, sz: 0x%llx\n",
  1183. i, start, sz);
  1184. }
  1185. for (i = 0; i < mblock_info->reserved_num; i++) {
  1186. start = mblock_info->reserved[i].start;
  1187. sz = mblock_info->reserved[i].size;
  1188. dprintf(CRITICAL, "mblock_reserve-R[%d].start: 0x%llx, sz: 0x%llx map:%d name:%s\n",
  1189. i, start, sz, mblock_info->reserved[i].mapping, mblock_info->reserved[i].name);
  1190. }
  1191. } else
  1192. dprintf(INFO, "%s:PASS\n", __func__);
  1193. if (sanity_fail) {
  1194. dprintf(CRITICAL, "%s fatal error keep while (1)\n", __func__);
  1195. while (1)
  1196. ;
  1197. }
  1198. last_node = reserved_node;
  1199. }
  1200. return 0;
  1201. }
  1202. /*
  1203. * mblock_sanity_check
  1204. * after executing mblock related api , we perform
  1205. * sanity check in the last step to confirm there
  1206. * is nothing wrong, we will check overlap and
  1207. * conflict between DTS and mblock API
  1208. *
  1209. * input:
  1210. * @fdt: pointer to fdt
  1211. * @mblock_info: the address of mblock_info
  1212. * @dram_info_t: the address of dram_info
  1213. *
  1214. * output:
  1215. * return 0 on success, otherwise 1
  1216. */
  1217. int mblock_sanity_check(void *fdt, mblock_info_t *mblock_info,
  1218. dram_info_t *dram_info) {
  1219. u64 mblock_start, reserved_start, mblock_sz, reserved_sz;
  1220. unsigned int i, j, sanity_fail = 0, ret = 0;
  1221. /* check if mblock and reserved overlap*/
  1222. mblock_version_check();
  1223. for (i = 0; i < mblock_info->mblock_num; i++) {
  1224. mblock_start = mblock_info->mblock[i].start;
  1225. mblock_sz = mblock_info->mblock[i].size;
  1226. for (j = 0; j < mblock_info->reserved_num; j++) {
  1227. reserved_start = mblock_info->reserved[j].start;
  1228. reserved_sz = mblock_info->reserved[j].size;
  1229. if (((reserved_start >= mblock_start) &&
  1230. (reserved_start < (mblock_start + mblock_sz))) || \
  1231. ((reserved_start < mblock_start) && ((reserved_start + reserved_sz) > mblock_start))) {
  1232. sanity_fail = 1;
  1233. dprintf(CRITICAL, "%s:%d failed i:%d j:%d %d:%d:%d:%d\n",
  1234. __func__, __LINE__, i, j, (reserved_start >= mblock_start)\
  1235. , (reserved_start <= (mblock_start + mblock_sz))\
  1236. , (reserved_start < mblock_start), \
  1237. ((reserved_start + reserved_sz) > mblock_start));
  1238. }
  1239. }
  1240. }
  1241. if (sanity_fail) {
  1242. /* print debug info */
  1243. for (i = 0; i < mblock_info->mblock_num; i++) {
  1244. mblock_start = mblock_info->mblock[i].start;
  1245. mblock_sz = mblock_info->mblock[i].size;
  1246. dprintf(CRITICAL, "mblock_reserve [%d].start: \
  1247. 0x%llx, sz: 0x%llx\n",
  1248. i, mblock_start, mblock_sz);
  1249. }
  1250. for (i = 0; i < mblock_info->reserved_num; i++) {
  1251. reserved_start = mblock_info->reserved[i].start;
  1252. reserved_sz = mblock_info->reserved[i].size;
  1253. dprintf(CRITICAL, "mblock_reserve-R[%d].start:\
  1254. 0x%llx, sz: 0x%llx map:%d name:%s\n",
  1255. i, reserved_start, reserved_sz,
  1256. mblock_info->reserved[i].mapping,\
  1257. mblock_info->reserved[i].name);
  1258. }
  1259. } else {
  1260. dprintf(INFO, "%s:PASS\n", __func__);
  1261. }
  1262. ret = reserved_memory_conflict_check(fdt, mblock_info);
  1263. if (sanity_fail || ret) {
  1264. dprintf(CRITICAL, "%s fatal error keep while (1)\n", __func__);
  1265. while (1)
  1266. ;
  1267. }
  1268. return 0;
  1269. }
  1270. u64 mblock_get_memory_size(mblock_info_t *mblock_info)
  1271. {
  1272. u64 total_size = 0;
  1273. unsigned int i;
  1274. for (i = 0; i < mblock_info->mblock_num; i++) {
  1275. if (mblock_info->mblock[i].start)
  1276. total_size += mblock_info->mblock[i].size;
  1277. }
  1278. for (i = 0; i < mblock_info->reserved_num; i++) {
  1279. if (mblock_info->reserved[i].start)
  1280. total_size += mblock_info->reserved[i].size;
  1281. }
  1282. return total_size;
  1283. }
  1284. const reserved_t *mblock_query_reserved
  1285. (mblock_info_t *mblock_info, const char *name,
  1286. reserved_t *index)
  1287. {
  1288. reserved_t *p_reserved;
  1289. for_each_mblock_reserved(mblock_info, p_reserved) {
  1290. if (index && (p_reserved <= index))
  1291. continue;
  1292. if ((strlen(p_reserved->name) && strlen(name)) &&
  1293. (strlen(p_reserved->name) == strlen(name)) &&
  1294. (strncmp(p_reserved->name, name, strlen(name)) == 0)) {
  1295. return p_reserved;
  1296. }
  1297. }
  1298. return 0;
  1299. }
  1300. int mblock_query_reserved_count(mblock_info_t *mblock_info, const char *name)
  1301. {
  1302. reserved_t *p_reserved;
  1303. int i = 0;
  1304. for_each_mblock_reserved(mblock_info, p_reserved) {
  1305. if ((strlen(p_reserved->name) && strlen(name)) &&
  1306. (strlen(p_reserved->name) == strlen(name)) &&
  1307. (strncmp(p_reserved->name, name, strlen(name)) == 0))
  1308. i++;
  1309. }
  1310. return i;
  1311. }
  1312. #endif