mblock_v2.c 45 KB

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