1*ffa8f8b7SJoseph Chen // SPDX-License-Identifier: GPL-2.0 2*ffa8f8b7SJoseph Chen /* 3*ffa8f8b7SJoseph Chen * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd 4*ffa8f8b7SJoseph Chen */ 5*ffa8f8b7SJoseph Chen 6*ffa8f8b7SJoseph Chen #include <common.h> 7*ffa8f8b7SJoseph Chen #include <sysmem.h> 8*ffa8f8b7SJoseph Chen #include <lmb.h> 9*ffa8f8b7SJoseph Chen #include <malloc.h> 10*ffa8f8b7SJoseph Chen #include <asm/io.h> 11*ffa8f8b7SJoseph Chen 12*ffa8f8b7SJoseph Chen DECLARE_GLOBAL_DATA_PTR; 13*ffa8f8b7SJoseph Chen 14*ffa8f8b7SJoseph Chen #define SYSMEM_MAGIC 0x4D454D53 /* "SMEM" */ 15*ffa8f8b7SJoseph Chen #define SYSMEM_ALLOC_ANYWHERE 0 16*ffa8f8b7SJoseph Chen #define SYSMEM_ALLOC_NO_ALIGN 1 17*ffa8f8b7SJoseph Chen 18*ffa8f8b7SJoseph Chen #ifndef CONFIG_SYS_STACK_SIZE 19*ffa8f8b7SJoseph Chen #define CONFIG_SYS_STACK_SIZE SZ_2M 20*ffa8f8b7SJoseph Chen #endif 21*ffa8f8b7SJoseph Chen 22*ffa8f8b7SJoseph Chen #define SIZE_MB(len) ((len) >> 20) 23*ffa8f8b7SJoseph Chen #define SIZE_KB(len) (((len) % (1 << 20)) >> 10) 24*ffa8f8b7SJoseph Chen 25*ffa8f8b7SJoseph Chen #define SYSMEM_I(fmt, args...) printf("Sysmem: "fmt, ##args) 26*ffa8f8b7SJoseph Chen #define SYSMEM_W(fmt, args...) printf("Sysmem Warn: "fmt, ##args) 27*ffa8f8b7SJoseph Chen #define SYSMEM_E(fmt, args...) printf("Sysmem Error: "fmt, ##args) 28*ffa8f8b7SJoseph Chen #define SYSMEM_D(fmt, args...) debug("Sysmem Debug: "fmt, ##args) 29*ffa8f8b7SJoseph Chen 30*ffa8f8b7SJoseph Chen static struct sysmem plat_sysmem; /* Global for platform */ 31*ffa8f8b7SJoseph Chen 32*ffa8f8b7SJoseph Chen struct sysmem_check { 33*ffa8f8b7SJoseph Chen uint32_t magic; 34*ffa8f8b7SJoseph Chen }; 35*ffa8f8b7SJoseph Chen 36*ffa8f8b7SJoseph Chen static int sysmem_has_init(void) 37*ffa8f8b7SJoseph Chen { 38*ffa8f8b7SJoseph Chen if (!plat_sysmem.has_init) { 39*ffa8f8b7SJoseph Chen SYSMEM_E("Framework is not initialized\n"); 40*ffa8f8b7SJoseph Chen return 0; 41*ffa8f8b7SJoseph Chen } 42*ffa8f8b7SJoseph Chen 43*ffa8f8b7SJoseph Chen return 1; 44*ffa8f8b7SJoseph Chen } 45*ffa8f8b7SJoseph Chen 46*ffa8f8b7SJoseph Chen void sysmem_dump(void) 47*ffa8f8b7SJoseph Chen { 48*ffa8f8b7SJoseph Chen #ifdef DEBUG 49*ffa8f8b7SJoseph Chen struct sysmem *sysmem = &plat_sysmem; 50*ffa8f8b7SJoseph Chen struct lmb *lmb = &sysmem->lmb; 51*ffa8f8b7SJoseph Chen struct sysmem_property *prop; 52*ffa8f8b7SJoseph Chen struct sysmem_check *check; 53*ffa8f8b7SJoseph Chen struct list_head *node; 54*ffa8f8b7SJoseph Chen ulong memory_size = 0; 55*ffa8f8b7SJoseph Chen ulong reserved_size = 0; 56*ffa8f8b7SJoseph Chen ulong allocated_size = 0; 57*ffa8f8b7SJoseph Chen ulong i; 58*ffa8f8b7SJoseph Chen 59*ffa8f8b7SJoseph Chen if (!sysmem_has_init()) 60*ffa8f8b7SJoseph Chen return; 61*ffa8f8b7SJoseph Chen 62*ffa8f8b7SJoseph Chen printf("\nsysmem_dump_all:\n"); 63*ffa8f8b7SJoseph Chen 64*ffa8f8b7SJoseph Chen /* Memory pool */ 65*ffa8f8b7SJoseph Chen printf(" ------------------------------------------------------\n"); 66*ffa8f8b7SJoseph Chen for (i = 0; i < lmb->memory.cnt; i++) { 67*ffa8f8b7SJoseph Chen memory_size += lmb->memory.region[i].size; 68*ffa8f8b7SJoseph Chen printf(" memory.rgn[%ld].base = 0x%08lx\n", i, 69*ffa8f8b7SJoseph Chen (ulong)lmb->memory.region[i].base); 70*ffa8f8b7SJoseph Chen printf(" .size = 0x%08lx\n", 71*ffa8f8b7SJoseph Chen (ulong)lmb->memory.region[i].size); 72*ffa8f8b7SJoseph Chen } 73*ffa8f8b7SJoseph Chen printf("\n memory.total = 0x%08lx (%ld MiB. %ld KiB)\n", 74*ffa8f8b7SJoseph Chen (ulong)memory_size, 75*ffa8f8b7SJoseph Chen SIZE_MB((ulong)memory_size), 76*ffa8f8b7SJoseph Chen SIZE_KB((ulong)memory_size)); 77*ffa8f8b7SJoseph Chen 78*ffa8f8b7SJoseph Chen /* Reserved */ 79*ffa8f8b7SJoseph Chen i = 0; 80*ffa8f8b7SJoseph Chen printf(" ------------------------------------------------------\n"); 81*ffa8f8b7SJoseph Chen list_for_each(node, &sysmem->reserved_head) { 82*ffa8f8b7SJoseph Chen prop = list_entry(node, struct sysmem_property, node); 83*ffa8f8b7SJoseph Chen reserved_size += prop->size; 84*ffa8f8b7SJoseph Chen printf(" reserved.rgn[%ld].name = \"%s\"\n", i, prop->name); 85*ffa8f8b7SJoseph Chen printf(" .base = 0x%08lx\n", 86*ffa8f8b7SJoseph Chen (ulong)prop->base); 87*ffa8f8b7SJoseph Chen printf(" .size = 0x%08lx\n", 88*ffa8f8b7SJoseph Chen (ulong)prop->size); 89*ffa8f8b7SJoseph Chen i++; 90*ffa8f8b7SJoseph Chen } 91*ffa8f8b7SJoseph Chen printf("\n reserved.total = 0x%08lx (%ld MiB. %ld KiB)\n", 92*ffa8f8b7SJoseph Chen (ulong)reserved_size, 93*ffa8f8b7SJoseph Chen SIZE_MB((ulong)reserved_size), 94*ffa8f8b7SJoseph Chen SIZE_KB((ulong)reserved_size)); 95*ffa8f8b7SJoseph Chen 96*ffa8f8b7SJoseph Chen /* Allocated */ 97*ffa8f8b7SJoseph Chen i = 0; 98*ffa8f8b7SJoseph Chen printf(" ------------------------------------------------------\n"); 99*ffa8f8b7SJoseph Chen list_for_each(node, &sysmem->allocated_head) { 100*ffa8f8b7SJoseph Chen prop = list_entry(node, struct sysmem_property, node); 101*ffa8f8b7SJoseph Chen allocated_size += prop->size; 102*ffa8f8b7SJoseph Chen check = (struct sysmem_check *) 103*ffa8f8b7SJoseph Chen (prop->base + prop->size - sizeof(*check)); 104*ffa8f8b7SJoseph Chen printf(" allocated.rgn[%ld].name = \"%s\"%s\n", 105*ffa8f8b7SJoseph Chen i, prop->name, 106*ffa8f8b7SJoseph Chen check->magic != SYSMEM_MAGIC ? " (Overflow)" : ""); 107*ffa8f8b7SJoseph Chen printf(" .base = 0x%08lx\n", 108*ffa8f8b7SJoseph Chen (ulong)prop->base); 109*ffa8f8b7SJoseph Chen printf(" .size = 0x%08lx\n", 110*ffa8f8b7SJoseph Chen (ulong)prop->size); 111*ffa8f8b7SJoseph Chen i++; 112*ffa8f8b7SJoseph Chen } 113*ffa8f8b7SJoseph Chen printf("\n allocated.total = 0x%08lx (%ld MiB. %ld KiB)\n", 114*ffa8f8b7SJoseph Chen (ulong)allocated_size, 115*ffa8f8b7SJoseph Chen SIZE_MB((ulong)allocated_size), 116*ffa8f8b7SJoseph Chen SIZE_KB((ulong)allocated_size)); 117*ffa8f8b7SJoseph Chen 118*ffa8f8b7SJoseph Chen /* LMB core reserved */ 119*ffa8f8b7SJoseph Chen printf(" ------------------------------------------------------\n"); 120*ffa8f8b7SJoseph Chen reserved_size = 0; 121*ffa8f8b7SJoseph Chen for (i = 0; i < lmb->reserved.cnt; i++) { 122*ffa8f8b7SJoseph Chen reserved_size += lmb->reserved.region[i].size; 123*ffa8f8b7SJoseph Chen printf(" LMB.reserved[%ld].base = 0x%08lx\n", i, 124*ffa8f8b7SJoseph Chen (ulong)lmb->reserved.region[i].base); 125*ffa8f8b7SJoseph Chen printf(" .size = 0x%08lx\n", 126*ffa8f8b7SJoseph Chen (ulong)lmb->reserved.region[i].size); 127*ffa8f8b7SJoseph Chen } 128*ffa8f8b7SJoseph Chen 129*ffa8f8b7SJoseph Chen printf("\n reserved.core.total = 0x%08lx (%ld MiB. %ld KiB)\n", 130*ffa8f8b7SJoseph Chen (ulong)reserved_size, 131*ffa8f8b7SJoseph Chen SIZE_MB((ulong)reserved_size), 132*ffa8f8b7SJoseph Chen SIZE_KB((ulong)reserved_size)); 133*ffa8f8b7SJoseph Chen printf(" ------------------------------------------------------\n\n"); 134*ffa8f8b7SJoseph Chen #endif 135*ffa8f8b7SJoseph Chen } 136*ffa8f8b7SJoseph Chen 137*ffa8f8b7SJoseph Chen int sysmem_check(void) 138*ffa8f8b7SJoseph Chen { 139*ffa8f8b7SJoseph Chen struct sysmem *sysmem = &plat_sysmem; 140*ffa8f8b7SJoseph Chen struct sysmem_property *prop; 141*ffa8f8b7SJoseph Chen struct sysmem_check *check; 142*ffa8f8b7SJoseph Chen struct list_head *node; 143*ffa8f8b7SJoseph Chen int ret = 0; 144*ffa8f8b7SJoseph Chen 145*ffa8f8b7SJoseph Chen if (!sysmem_has_init()) 146*ffa8f8b7SJoseph Chen return -ENOSYS; 147*ffa8f8b7SJoseph Chen 148*ffa8f8b7SJoseph Chen /* Check allocated */ 149*ffa8f8b7SJoseph Chen list_for_each(node, &sysmem->allocated_head) { 150*ffa8f8b7SJoseph Chen prop = list_entry(node, struct sysmem_property, node); 151*ffa8f8b7SJoseph Chen check = (struct sysmem_check *) 152*ffa8f8b7SJoseph Chen (prop->base + prop->size - sizeof(*check)); 153*ffa8f8b7SJoseph Chen if (check->magic != SYSMEM_MAGIC) { 154*ffa8f8b7SJoseph Chen ret = -EOVERFLOW; 155*ffa8f8b7SJoseph Chen SYSMEM_E("\"%s\" (base=0x%08lx, size=0x%lx) is Overflow!\n", 156*ffa8f8b7SJoseph Chen prop->name, (ulong)prop->base, (ulong)prop->size); 157*ffa8f8b7SJoseph Chen } 158*ffa8f8b7SJoseph Chen } 159*ffa8f8b7SJoseph Chen 160*ffa8f8b7SJoseph Chen /* Check stack */ 161*ffa8f8b7SJoseph Chen check = (struct sysmem_check *)(gd->start_addr_sp - CONFIG_SYS_STACK_SIZE); 162*ffa8f8b7SJoseph Chen if (check->magic != SYSMEM_MAGIC) { 163*ffa8f8b7SJoseph Chen ret = -EOVERFLOW; 164*ffa8f8b7SJoseph Chen SYSMEM_E("Runtime stack is Overflow!\n"); 165*ffa8f8b7SJoseph Chen } 166*ffa8f8b7SJoseph Chen 167*ffa8f8b7SJoseph Chen return ret; 168*ffa8f8b7SJoseph Chen } 169*ffa8f8b7SJoseph Chen 170*ffa8f8b7SJoseph Chen int sysmem_dump_check(void) 171*ffa8f8b7SJoseph Chen { 172*ffa8f8b7SJoseph Chen sysmem_dump(); 173*ffa8f8b7SJoseph Chen 174*ffa8f8b7SJoseph Chen return sysmem_check(); 175*ffa8f8b7SJoseph Chen } 176*ffa8f8b7SJoseph Chen 177*ffa8f8b7SJoseph Chen static int sysmem_is_overlap(phys_addr_t base1, phys_size_t size1, 178*ffa8f8b7SJoseph Chen phys_addr_t base2, phys_size_t size2) 179*ffa8f8b7SJoseph Chen { 180*ffa8f8b7SJoseph Chen return ((base1 < (base2 + size2)) && (base2 < (base1 + size1))); 181*ffa8f8b7SJoseph Chen } 182*ffa8f8b7SJoseph Chen 183*ffa8f8b7SJoseph Chen int sysmem_add(phys_addr_t base, phys_size_t size) 184*ffa8f8b7SJoseph Chen { 185*ffa8f8b7SJoseph Chen struct sysmem *sysmem = &plat_sysmem; 186*ffa8f8b7SJoseph Chen int ret; 187*ffa8f8b7SJoseph Chen 188*ffa8f8b7SJoseph Chen if (!sysmem_has_init()) 189*ffa8f8b7SJoseph Chen return -ENOSYS; 190*ffa8f8b7SJoseph Chen 191*ffa8f8b7SJoseph Chen ret = lmb_add(&sysmem->lmb, base, size); 192*ffa8f8b7SJoseph Chen if (ret < 0) 193*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to add sysmem at 0x%lx for 0x%lx size\n", 194*ffa8f8b7SJoseph Chen (ulong)base, (ulong)size); 195*ffa8f8b7SJoseph Chen 196*ffa8f8b7SJoseph Chen return (ret >= 0) ? 0 : ret; 197*ffa8f8b7SJoseph Chen } 198*ffa8f8b7SJoseph Chen 199*ffa8f8b7SJoseph Chen int sysmem_reserve(const char *name, phys_addr_t base, phys_size_t size) 200*ffa8f8b7SJoseph Chen { 201*ffa8f8b7SJoseph Chen struct sysmem *sysmem = &plat_sysmem; 202*ffa8f8b7SJoseph Chen struct sysmem_property *prop; 203*ffa8f8b7SJoseph Chen struct list_head *node; 204*ffa8f8b7SJoseph Chen int ret = 0; 205*ffa8f8b7SJoseph Chen 206*ffa8f8b7SJoseph Chen if (!sysmem_has_init()) 207*ffa8f8b7SJoseph Chen return -ENOSYS; 208*ffa8f8b7SJoseph Chen 209*ffa8f8b7SJoseph Chen if (!name) { 210*ffa8f8b7SJoseph Chen SYSMEM_E("NULL name for reserved sysmem\n"); 211*ffa8f8b7SJoseph Chen return -EINVAL; 212*ffa8f8b7SJoseph Chen } 213*ffa8f8b7SJoseph Chen 214*ffa8f8b7SJoseph Chen /* Check overlap */ 215*ffa8f8b7SJoseph Chen list_for_each(node, &sysmem->reserved_head) { 216*ffa8f8b7SJoseph Chen prop = list_entry(node, struct sysmem_property, node); 217*ffa8f8b7SJoseph Chen if (!strcmp(prop->name, name)) { 218*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to double reserve for existence \"%s\"\n", name); 219*ffa8f8b7SJoseph Chen return -EEXIST; 220*ffa8f8b7SJoseph Chen } else if (sysmem_is_overlap(prop->base, prop->size, base, size)) { 221*ffa8f8b7SJoseph Chen SYSMEM_W("\"%s\" (base=0x%08lx, size=0x%lx) reserve is " 222*ffa8f8b7SJoseph Chen "overlap with existence \"%s\" (base=0x%08lx, size=0x%lx)\n", 223*ffa8f8b7SJoseph Chen name, (ulong)base, (ulong)size, prop->name, 224*ffa8f8b7SJoseph Chen (ulong)prop->base, (ulong)prop->size); 225*ffa8f8b7SJoseph Chen } 226*ffa8f8b7SJoseph Chen } 227*ffa8f8b7SJoseph Chen 228*ffa8f8b7SJoseph Chen ret = lmb_reserve(&sysmem->lmb, base, size); 229*ffa8f8b7SJoseph Chen if (ret >= 0) { 230*ffa8f8b7SJoseph Chen prop = malloc(sizeof(*prop)); 231*ffa8f8b7SJoseph Chen if (!prop) { 232*ffa8f8b7SJoseph Chen SYSMEM_E("No memory for \"%s\" reserve sysmem\n", name); 233*ffa8f8b7SJoseph Chen return -ENOMEM; 234*ffa8f8b7SJoseph Chen } 235*ffa8f8b7SJoseph Chen 236*ffa8f8b7SJoseph Chen prop->name = name; 237*ffa8f8b7SJoseph Chen prop->base = base; 238*ffa8f8b7SJoseph Chen prop->size = size; 239*ffa8f8b7SJoseph Chen list_add_tail(&prop->node, &sysmem->reserved_head); 240*ffa8f8b7SJoseph Chen } else { 241*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to reserve \"%s\" at 0x%lx\n", name, (ulong)base); 242*ffa8f8b7SJoseph Chen return -EINVAL; 243*ffa8f8b7SJoseph Chen } 244*ffa8f8b7SJoseph Chen 245*ffa8f8b7SJoseph Chen return 0; 246*ffa8f8b7SJoseph Chen } 247*ffa8f8b7SJoseph Chen 248*ffa8f8b7SJoseph Chen void *sysmem_alloc_align_base(const char *name, 249*ffa8f8b7SJoseph Chen phys_addr_t base, 250*ffa8f8b7SJoseph Chen phys_size_t size, 251*ffa8f8b7SJoseph Chen ulong align) 252*ffa8f8b7SJoseph Chen { 253*ffa8f8b7SJoseph Chen struct sysmem *sysmem = &plat_sysmem; 254*ffa8f8b7SJoseph Chen struct sysmem_property *prop; 255*ffa8f8b7SJoseph Chen struct sysmem_check *check; 256*ffa8f8b7SJoseph Chen struct list_head *node; 257*ffa8f8b7SJoseph Chen phys_addr_t paddr; 258*ffa8f8b7SJoseph Chen phys_addr_t alloc_base; 259*ffa8f8b7SJoseph Chen phys_size_t alloc_size; 260*ffa8f8b7SJoseph Chen 261*ffa8f8b7SJoseph Chen if (!sysmem_has_init()) 262*ffa8f8b7SJoseph Chen return NULL; 263*ffa8f8b7SJoseph Chen 264*ffa8f8b7SJoseph Chen if (!name) { 265*ffa8f8b7SJoseph Chen SYSMEM_E("NULL name for alloc sysmem\n"); 266*ffa8f8b7SJoseph Chen return NULL; 267*ffa8f8b7SJoseph Chen } 268*ffa8f8b7SJoseph Chen 269*ffa8f8b7SJoseph Chen /* Already allocated ? */ 270*ffa8f8b7SJoseph Chen list_for_each(node, &sysmem->allocated_head) { 271*ffa8f8b7SJoseph Chen prop = list_entry(node, struct sysmem_property, node); 272*ffa8f8b7SJoseph Chen if (!strcmp(prop->name, name)) { 273*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to double alloc for existence \"%s\"\n", name); 274*ffa8f8b7SJoseph Chen return NULL; 275*ffa8f8b7SJoseph Chen } else if (sysmem_is_overlap(prop->base, prop->size, base, size)) { 276*ffa8f8b7SJoseph Chen SYSMEM_E("\"%s\" (base=0x%08lx, size=0x%lx) alloc is " 277*ffa8f8b7SJoseph Chen "overlap with existence \"%s\" (base=0x%08lx, size=0x%lx)\n", 278*ffa8f8b7SJoseph Chen name, (ulong)base, (ulong)size, 279*ffa8f8b7SJoseph Chen prop->name, (ulong)prop->base, 280*ffa8f8b7SJoseph Chen (ulong)prop->size); 281*ffa8f8b7SJoseph Chen return NULL; 282*ffa8f8b7SJoseph Chen } 283*ffa8f8b7SJoseph Chen } 284*ffa8f8b7SJoseph Chen 285*ffa8f8b7SJoseph Chen alloc_size = size + sizeof(*check); 286*ffa8f8b7SJoseph Chen if (base == SYSMEM_ALLOC_ANYWHERE) 287*ffa8f8b7SJoseph Chen alloc_base = base; 288*ffa8f8b7SJoseph Chen else 289*ffa8f8b7SJoseph Chen alloc_base = base + alloc_size; /* LMB is align down alloc mechanism */ 290*ffa8f8b7SJoseph Chen 291*ffa8f8b7SJoseph Chen paddr = lmb_alloc_base(&sysmem->lmb, alloc_size, align, alloc_base); 292*ffa8f8b7SJoseph Chen if (paddr) { 293*ffa8f8b7SJoseph Chen if ((paddr == base) || (base == SYSMEM_ALLOC_ANYWHERE)) { 294*ffa8f8b7SJoseph Chen prop = malloc(sizeof(*prop)); 295*ffa8f8b7SJoseph Chen if (!prop) { 296*ffa8f8b7SJoseph Chen SYSMEM_E("No memory for \"%s\" alloc sysmem\n", name); 297*ffa8f8b7SJoseph Chen return NULL; 298*ffa8f8b7SJoseph Chen } 299*ffa8f8b7SJoseph Chen 300*ffa8f8b7SJoseph Chen prop->name = name; 301*ffa8f8b7SJoseph Chen prop->base = paddr; 302*ffa8f8b7SJoseph Chen prop->size = alloc_size; 303*ffa8f8b7SJoseph Chen sysmem->allocated_cnt++; 304*ffa8f8b7SJoseph Chen 305*ffa8f8b7SJoseph Chen check = (struct sysmem_check *)(paddr + size); 306*ffa8f8b7SJoseph Chen check->magic = SYSMEM_MAGIC; 307*ffa8f8b7SJoseph Chen 308*ffa8f8b7SJoseph Chen list_add_tail(&prop->node, &sysmem->allocated_head); 309*ffa8f8b7SJoseph Chen } else { 310*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to alloc \"%s\" at expect 0x%lx but " 311*ffa8f8b7SJoseph Chen "alloc at 0x%lx\n", 312*ffa8f8b7SJoseph Chen name, (ulong)base, (ulong)paddr); 313*ffa8f8b7SJoseph Chen return NULL; 314*ffa8f8b7SJoseph Chen } 315*ffa8f8b7SJoseph Chen } else { 316*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to alloc \"%s\" at 0x%lx\n", name, (ulong)base); 317*ffa8f8b7SJoseph Chen } 318*ffa8f8b7SJoseph Chen 319*ffa8f8b7SJoseph Chen SYSMEM_D("Alloc: \"%s\", paddr=0x%lx, size=0x%lx, align=0x%x, anywhere=%d\n", 320*ffa8f8b7SJoseph Chen name, (ulong)paddr, (ulong)size, (u32)align, !base); 321*ffa8f8b7SJoseph Chen 322*ffa8f8b7SJoseph Chen return (void *)paddr; 323*ffa8f8b7SJoseph Chen } 324*ffa8f8b7SJoseph Chen 325*ffa8f8b7SJoseph Chen void *sysmem_alloc_align(const char *name, phys_size_t size, ulong align) 326*ffa8f8b7SJoseph Chen { 327*ffa8f8b7SJoseph Chen return sysmem_alloc_align_base(name, 328*ffa8f8b7SJoseph Chen SYSMEM_ALLOC_ANYWHERE, 329*ffa8f8b7SJoseph Chen size, 330*ffa8f8b7SJoseph Chen align); 331*ffa8f8b7SJoseph Chen } 332*ffa8f8b7SJoseph Chen 333*ffa8f8b7SJoseph Chen void *sysmem_alloc_base(const char *name, phys_addr_t base, phys_size_t size) 334*ffa8f8b7SJoseph Chen { 335*ffa8f8b7SJoseph Chen return sysmem_alloc_align_base(name, 336*ffa8f8b7SJoseph Chen base, 337*ffa8f8b7SJoseph Chen size, 338*ffa8f8b7SJoseph Chen SYSMEM_ALLOC_NO_ALIGN); 339*ffa8f8b7SJoseph Chen } 340*ffa8f8b7SJoseph Chen 341*ffa8f8b7SJoseph Chen void *sysmem_alloc(const char *name, phys_size_t size) 342*ffa8f8b7SJoseph Chen { 343*ffa8f8b7SJoseph Chen return sysmem_alloc_align_base(name, 344*ffa8f8b7SJoseph Chen SYSMEM_ALLOC_ANYWHERE, 345*ffa8f8b7SJoseph Chen size, 346*ffa8f8b7SJoseph Chen SYSMEM_ALLOC_NO_ALIGN); 347*ffa8f8b7SJoseph Chen } 348*ffa8f8b7SJoseph Chen 349*ffa8f8b7SJoseph Chen int sysmem_free(phys_addr_t base) 350*ffa8f8b7SJoseph Chen { 351*ffa8f8b7SJoseph Chen struct sysmem *sysmem = &plat_sysmem; 352*ffa8f8b7SJoseph Chen struct sysmem_property *prop; 353*ffa8f8b7SJoseph Chen struct list_head *node; 354*ffa8f8b7SJoseph Chen int found = 0; 355*ffa8f8b7SJoseph Chen int ret; 356*ffa8f8b7SJoseph Chen 357*ffa8f8b7SJoseph Chen if (!sysmem_has_init()) 358*ffa8f8b7SJoseph Chen return -ENOSYS; 359*ffa8f8b7SJoseph Chen 360*ffa8f8b7SJoseph Chen /* Find existence */ 361*ffa8f8b7SJoseph Chen list_for_each(node, &sysmem->allocated_head) { 362*ffa8f8b7SJoseph Chen prop = list_entry(node, struct sysmem_property, node); 363*ffa8f8b7SJoseph Chen if (prop->base == base) { 364*ffa8f8b7SJoseph Chen found = 1; 365*ffa8f8b7SJoseph Chen break; 366*ffa8f8b7SJoseph Chen } 367*ffa8f8b7SJoseph Chen } 368*ffa8f8b7SJoseph Chen 369*ffa8f8b7SJoseph Chen if (!found) { 370*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to free no allocated sysmem at 0x%lx\n", (ulong)base); 371*ffa8f8b7SJoseph Chen return -EINVAL; 372*ffa8f8b7SJoseph Chen } 373*ffa8f8b7SJoseph Chen 374*ffa8f8b7SJoseph Chen ret = lmb_free(&sysmem->lmb, prop->base, prop->size); 375*ffa8f8b7SJoseph Chen if (ret >= 0) { 376*ffa8f8b7SJoseph Chen SYSMEM_I("Free: \"%s\", paddr=0x%lx, size=0x%lx\n", 377*ffa8f8b7SJoseph Chen prop->name, (ulong)prop->base, (ulong)prop->size); 378*ffa8f8b7SJoseph Chen sysmem->allocated_cnt--; 379*ffa8f8b7SJoseph Chen list_del(&prop->node); 380*ffa8f8b7SJoseph Chen free(prop); 381*ffa8f8b7SJoseph Chen } else { 382*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to free \"%s\" at 0x%lx\n", prop->name, (ulong)base); 383*ffa8f8b7SJoseph Chen } 384*ffa8f8b7SJoseph Chen 385*ffa8f8b7SJoseph Chen return (ret >= 0) ? 0 : ret; 386*ffa8f8b7SJoseph Chen } 387*ffa8f8b7SJoseph Chen 388*ffa8f8b7SJoseph Chen int sysmem_init(void) 389*ffa8f8b7SJoseph Chen { 390*ffa8f8b7SJoseph Chen struct sysmem *sysmem = &plat_sysmem; 391*ffa8f8b7SJoseph Chen struct sysmem_check *check; 392*ffa8f8b7SJoseph Chen phys_addr_t mem_start; 393*ffa8f8b7SJoseph Chen phys_size_t mem_size; 394*ffa8f8b7SJoseph Chen int ret; 395*ffa8f8b7SJoseph Chen 396*ffa8f8b7SJoseph Chen SYSMEM_I("init\n"); 397*ffa8f8b7SJoseph Chen 398*ffa8f8b7SJoseph Chen lmb_init(&sysmem->lmb); 399*ffa8f8b7SJoseph Chen INIT_LIST_HEAD(&sysmem->allocated_head); 400*ffa8f8b7SJoseph Chen INIT_LIST_HEAD(&sysmem->reserved_head); 401*ffa8f8b7SJoseph Chen sysmem->allocated_cnt = 0; 402*ffa8f8b7SJoseph Chen sysmem->has_init = true; 403*ffa8f8b7SJoseph Chen 404*ffa8f8b7SJoseph Chen /* Add all available system memory */ 405*ffa8f8b7SJoseph Chen #ifdef CONFIG_NR_DRAM_BANKS 406*ffa8f8b7SJoseph Chen int i; 407*ffa8f8b7SJoseph Chen 408*ffa8f8b7SJoseph Chen for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 409*ffa8f8b7SJoseph Chen ret = sysmem_add(gd->bd->bi_dram[i].start, 410*ffa8f8b7SJoseph Chen gd->bd->bi_dram[i].size); 411*ffa8f8b7SJoseph Chen if (ret) { 412*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to add sysmem from bi_dram[%d]\n", i); 413*ffa8f8b7SJoseph Chen return ret; 414*ffa8f8b7SJoseph Chen } 415*ffa8f8b7SJoseph Chen } 416*ffa8f8b7SJoseph Chen #else 417*ffa8f8b7SJoseph Chen mem_start = env_get_bootm_low(); 418*ffa8f8b7SJoseph Chen mem_size = env_get_bootm_size(); 419*ffa8f8b7SJoseph Chen ret = sysmem_add(mem_start, mem_size); 420*ffa8f8b7SJoseph Chen if (ret) { 421*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to add sysmem from bootm_low/size\n"); 422*ffa8f8b7SJoseph Chen return ret; 423*ffa8f8b7SJoseph Chen } 424*ffa8f8b7SJoseph Chen #endif 425*ffa8f8b7SJoseph Chen 426*ffa8f8b7SJoseph Chen /* Reserved for arch */ 427*ffa8f8b7SJoseph Chen ret = arch_sysmem_reserve(sysmem); 428*ffa8f8b7SJoseph Chen if (ret) { 429*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to reserve sysmem for arch\n"); 430*ffa8f8b7SJoseph Chen return ret; 431*ffa8f8b7SJoseph Chen } 432*ffa8f8b7SJoseph Chen 433*ffa8f8b7SJoseph Chen /* Reserved for board */ 434*ffa8f8b7SJoseph Chen ret = board_sysmem_reserve(sysmem); 435*ffa8f8b7SJoseph Chen if (ret) { 436*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to reserve sysmem for board\n"); 437*ffa8f8b7SJoseph Chen return ret; 438*ffa8f8b7SJoseph Chen } 439*ffa8f8b7SJoseph Chen 440*ffa8f8b7SJoseph Chen /* Reserved for U-boot framework 'reserve_xxx()' */ 441*ffa8f8b7SJoseph Chen mem_start = gd->start_addr_sp - CONFIG_SYS_STACK_SIZE; 442*ffa8f8b7SJoseph Chen mem_size = gd->ram_top - mem_start; 443*ffa8f8b7SJoseph Chen check = (struct sysmem_check *)mem_start; 444*ffa8f8b7SJoseph Chen check->magic = SYSMEM_MAGIC; 445*ffa8f8b7SJoseph Chen 446*ffa8f8b7SJoseph Chen ret = sysmem_reserve("U-Boot", mem_start, mem_size); 447*ffa8f8b7SJoseph Chen if (ret) { 448*ffa8f8b7SJoseph Chen SYSMEM_E("Failed to reserve sysmem for U-Boot framework\n"); 449*ffa8f8b7SJoseph Chen return ret; 450*ffa8f8b7SJoseph Chen } 451*ffa8f8b7SJoseph Chen 452*ffa8f8b7SJoseph Chen sysmem_dump(); 453*ffa8f8b7SJoseph Chen 454*ffa8f8b7SJoseph Chen return 0; 455*ffa8f8b7SJoseph Chen } 456*ffa8f8b7SJoseph Chen 457*ffa8f8b7SJoseph Chen __weak int board_sysmem_reserve(struct sysmem *sysmem) 458*ffa8f8b7SJoseph Chen { 459*ffa8f8b7SJoseph Chen /* please define platform specific board_sysmem_reserve() */ 460*ffa8f8b7SJoseph Chen return 0; 461*ffa8f8b7SJoseph Chen } 462*ffa8f8b7SJoseph Chen 463*ffa8f8b7SJoseph Chen __weak int arch_sysmem_reserve(struct sysmem *sysmem) 464*ffa8f8b7SJoseph Chen { 465*ffa8f8b7SJoseph Chen /* please define platform specific arch_sysmem_reserve() */ 466*ffa8f8b7SJoseph Chen return 0; 467*ffa8f8b7SJoseph Chen } 468